2016-11-01 5 views
0

私は現在、遺伝的アルゴリズムを作成しようとしています。解決したい問題の解決策を探しています。私は乱数生成を使用して複雑な配列を作成しました。この配列は、配列を正規化する関数に渡します。コードは次のようになります。複雑な配列を関数に渡して、間違った答えを返す

PROGRAM genetic_algorithm 

IMPLICIT NONE 
INTEGER:: a, b 
INTEGER :: i,j 
REAL :: d,e 
INTEGER, DIMENSION(8) :: seed 
COMPLEX,DIMENSION(:,:), ALLOCATABLE :: pop_mat, norm_mat 
COMPLEX :: c, norm 


WRITE(*,*) "Input Seed values - 8" 
READ(*,*) seed 
WRITE(*,*) "Input state vector number" 
READ(*,*) b 
WRITE(*,*) "Input population number" 
READ(*,*) a 

ALLOCATE(pop_mat(a,b)) 
ALLOCATE(norm_mat(a,b)) 

OPEN(1,FILE='Candidate_solutions.txt') 
CALL RANDOM_SEED(PUT=seed) 

DO i = 1,a 
    DO j = 1,b 
     CALL RANDOM_NUMBER(d) 
     CALL RANDOM_NUMBER(e) 
     d = (2*d) -1 
     e = (2*e) - 1 
     c = CMPLX(d,e) 
     pop_mat(i,j)=c 
     WRITE(1,'(2F9.5)',advance='no') pop_mat(i,j) 
    END DO 
    WRITE(1,*) '' 
END DO 
CLOSE(1) 
norm_mat=norm(pop_mat,a,b) 
WRITE(*,*) norm_mat(:,:) 
END PROGRAM genetic_algorithm 

出力をテストするための最終的な書き込みコマンドがあります。私norm関数は次のようになります。

COMPLEX FUNCTION norm(x,y,z) 
IMPLICIT NONE 

COMPLEX, DIMENSION(y,z), INTENT(INOUT) :: x 
INTEGER, INTENT (IN) :: y, z 
REAL :: norm_val 
REAL, DIMENSION(y) :: state_sum 
INTEGER :: i, j 

OPEN(2,FILE='norm_mat.txt') 
DO i = 1, y 
    DO j =1, z 
     norm_val = CONJG(x(i,j))*x(i,j) 
     state_sum(i) = state_sum(i) + norm_val 
    END DO 
END DO 

DO i = 1, y 
    DO j =1, z 
     x(i,j) = (1/SQRT(state_sum(i)))*x(i,j) 
     WRITE(2,'(2F9.5)',advance='no') x(i,j) 
    END DO 
    WRITE(2,*) '' 
END DO 
CLOSE(2) 
WRITE(*,*) x(:,:) 
WRITE(*,*) '' 
END FUNCTION 

FUNCTION norm、それはnorm_mat.txtに正しい値を出力しますが、メインプログラムに至るまで戻って渡されたとき、私は(2.34180515E-38, 0.0000000 )に等しいすべての行列要素を取得します。私は割り振りを混乱させて、マトリックスを通過してからsize(a,1) size(a,2)で割り振りましたが、その方法を使ってstate_sumのサイズを割り振ることができませんでした。

正しい値が返されない理由を理解できません。

+0

'norm'はスカラー関数の結果を持っています。これはあなたの期待ですか?おそらく、あなたはその価値を定義しておらず、それを配列への代入の右辺として持っているかもしれません。 – francescalus

+0

機能について理解していないものがなければなりません。私は関数が私の行列pop_matを取り、それを正規化して、メインプログラムに同じ次元の配列を返すようにしたいので、他の関数に正規化された関数を使うことができます。 – johnahh

+0

あなたのコンパイラは戻り値が決して設定されていないと不平を言っていませんか? – agentp

答えて

4

この関数を間違った方法で使用しています。関数が外部のため、コンパイラはあまり手助けできません。モジュールに配置する必要があります。コンパイラは、特定のエラーが発生した場合に不平を言うことによって、より多くの手助けをすることができます。コンパイラの警告(gfortranでは-Wall、インテルFortranでは-warn)も有効にする必要があります。特に

  1. あなたが関数内でintent(inout)引数を持っています。これは許されていますが、多少混乱させる可能性があります。代わりにサブルーチンを使用することを検討してください。結果としてxを使用したくないのですか?

  2. 関数結果の値は、norm関数のどこにも設定されません。それは深刻な問題です。関数内のどこかに、おそらく末尾に行番号

    norm = something 
    

    があるはずです。

  3. この関数は、1つの複素数(スカラー)を返しますが、(unset!)結果を配列norm_matに割り当てます。 norm_matは配列かスカラーであると考えられますか?一貫性を持たせる必要があります。関数がモジュール内にあるべき配列を実際に返したい場合。

  4. シード配列のサイズが8であると仮定します。これはコンパイラに依存します。最初にRANDOM_SEEDを呼び出して配列のサイズを取得する必要があります。このサイトにいくつかの例があります。

  5. ファイルのオープンには、ユニット番号2が使用されています。それは危険です、少数はしばしば特別な目的のために予約されています。 10を超える数字を使用してください。Fortran 2008には代わりにnewunit=という指定子があります。

+0

私は今から-Wallを使用します。 1)私はメインプログラムから行列を入力し、それを正規化し、正規化された配列を返すようにしたいのですが、これはどのように達成されたのでしょうか? 2)私は何を標準に割り当てるのですか?私はマトリックスマットを正規化しています。それは出力ではありませんか? 3)1つの複素数を出力するのはなぜですか?私は実際に私の機能で出力を与えるものを理解していません。 4)毎回同じコンパイラを使用するので、私はこれを行いました。私はランダム(シード) でそれを修正します5)私は10と11にこれらを変更し、これ以上の値を今から使用します。 ありがとう! – johnahh

+0

関数が何をし、どのようにサブルーチンと異なるのかを理解する必要があります。あなたはこれに混乱しているようです。私はこの小さな場所でそれを繰り返すことはできません、いくつかの教科書やチュートリアルを読む必要があります。あなたはここから始めることができますhttp://stackoverflow.com/documentation/fortran/1106/procedures-functions-and-subroutines#t=201611011644068779987 –

+0

また、関数が配列を返すことを本当に望むなら、それは**必須です**モジュール内にあり、メインプログラムから 'COMPLEX :: NORM'を削除する必要があります。 (あなたはそれを行い、とにかく関数をモジュールに移動する必要があります) –

0

サブルーチンから機能へ、またはその逆に切り替わる馬の中間ストリームを切り替える意味がありません。 そして、私はひどく悩んでいるようですので、答えを大きく編集しています。

私はこれを使用して、このことを覚えています。: https://xkcd.com/849/

基本的にCONJGはコンプレックスを取り込み、コンプレックスを返します。 Norm_Valは実数です。複合体はスカラーに強制されるべきではありません。

したがって、このセグメントは完全に危険な見えます...

DO i = 1, y 
    DO j =1, z 
    norm_val = CONJG(x(i,j))*x(i,j) 
    state_sum(i) = state_sum(i) + norm_val 
    END DO 
END DO 

次のいずれかとします

norm_val = REAL(CONJG(x(i,j))*x(i,j)) 

または

norm_val = (x(i,j)**2)**0.5 

または

norm_val = ABS(x(i,j)) 

私はおそらく最後の1つをお勧めします。

state_sumを初期化するには、state_sum(i)= 0を0にする前に、state_normal(ゼロ)をチェックします。

まず、検証した要素コアから始めて、レイヤード開発アプローチでより多くのコードを取得します。 1バイトで馬を食べようとしないでください。

+0

ええ、私は言語を混在させていたので、スクリプト言語を持っていました。 – Holmz

+1

申し訳ありません@holmz、これは彼が呼び出し側のユニットに結果を返すことに伴う問題に対処していない非常に多くのものです。 – agentp

+0

基本的な問題が複合体内で実際に存在する可能性がある場合、基本的な問題に直面している関数とサブルーチンやその他のスタイルポイントについて、多くの問題がありました。 – Holmz

関連する問題