n вложено для циклов в fortran90 - PullRequest
1 голос
/ 19 февраля 2012

Я прочитал некоторые темы по этому вопросу, но я не думаю, что это отвечает на мой вопрос. если да, то, пожалуйста, направьте меня к правильной теме, и я обязательно посмотрю снова.

вот моя проблема:

Я хочу написать цикл for, который будет перебирать каждую возможную комбинацию массива, где массив имеет длину 'n'.

то есть, если n = 2, мой цикл for будет

do i1 = 1,2
    do i2 = 1,2
         ! do stuff here
    enddo
enddo

в то время как если n = 3, то мой массив будет выглядеть как

do i1 = 1,3
    do i2 = 1,3
         do i3 = 1,3
             ! do stuff here
         enddo
    enddo
enddo

и так далее. Как мне написать подпрограмму, которая будет делать это автоматически, просто введя переменную 'n'?

Ответы [ 2 ]

1 голос
/ 19 февраля 2012

если вы напишите индексы, то у вас будет n-значное число в базе n (почти - есть смещение 1, потому что вы используете индексы, основанные на 1, в фортране). и вы запрашиваете каждое возможное значение, которое может принять это число.

другими словами, если мы на мгновение используем индексы, основанные на 0, для простоты, у вас есть:

  • n = 2, значения = 00,01,10,11 (двоичный счет от 0 до 3)
  • n = 3, значения = 000,001,002,010,011,012,020,021,022, 100,101,102,110,111,112,120,121,122, 200,201,202,210,211,212,220,221,222 (троичный (?), Считая от 0 до 26)

так что вы спрашиваете, как это сделать в общем случае.

и вы можете сделать это, используя массив для хранения n цифр, начиная с [0,0 .... 0]. затем, внутри цикла while (который заменит ваши n вложенных циклов), попытайтесь увеличить самую правую запись (цифру). если это равно n, вернитесь к нулю и увеличьте влево. как только вам удастся увеличить значение, не доходя до n, тогда вы «сделали» и можете использовать числа в качестве своих индексов.

это довольно просто - вы просто добавляете 1 каждый раз.

затем, для индексации на основе фортера 1, добавьте 1 к каждой цифре. другими словами, измените вышеприведенное, чтобы начать с 1 с и двигаться влево при n + 1.

например, для n = 4:

  • начать с [1,1,1,1]
    • выполнить внутреннюю петлю
  • с шагом вправо до [1,1,1,2]
    • выполнить внутреннюю петлю
  • с шагом вправо до [1,1,1,3]
    • выполнить внутреннюю петлю
  • увеличение вправо до [1,1,1,4]
    • выполнить внутреннюю петлю
  • с шагом вправо до [1,1,1,5]
  • увеличенная вами цифра теперь равна n + 1, что означает возврат к 1 и увеличение цифры влево [1,1,2,1]
    • выполнить действие по внутренней петле
  • с шагом вправо до [1,1,2,2]
    • выполнить действие внутреннего цикла
  • и т.д ..
1 голос
/ 19 февраля 2012

Полагаю, вы могли бы сделать это, только сложив циклы в один цикл n ** n и вычислив отдельные индексы n из свернутого глобального индекса (или просто подсчитав их с разными шагами).

Редактировать: попытка вставить это в пример кода:

do i=1,n**n
  do j=1,n
    ind(j) = mod((i-1)/max((j-1)*n,1),n) + 1
  end do
  ! Some code using ind(1:n)
end do
...