Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

generate a matrix of possible combinations using fortran 1

Status
Not open for further replies.

ignacio82

Technical User
Feb 15, 2012
9
US
I have an array X(9,2) and I want to generate another array B(512,9) with all the possible combinations.

I thought about doing 9 do loops, but I was hoping for a more efficient way.

This is what I have
Code:
do i1=1, 2
    do i2=1, 2
        do i3=1,2
            do i4=1,2
                do i5=1,2
                    do i6=1,2
                        do i7=1,2
                            do i8=i,2
                                do i9=1,2
                                    B(row, col) = X(1,i1)
                                    col = col + 1
                                    B(row, col) = X(2,i2)
                                    col = col + 1
                                    B(row, col) = X(3,i3)
                                    col = col + 1
                                    B(row, col) = X(4,i4)
                                    col = col + 1
                                    B(row, col) = X(5,i5)
                                    col = col + 1
                                    B(row, col) = X(6,i6)
                                    col = col + 1
                                    B(row, col) = X(7,i7)
                                    col = col + 1
                                    B(row, col) = X(8,i8)
                                    col = col + 1
                                    B(row, col) = X(9,i9)
                                    col = 1
                                    row = row + 1
                                end do
                            end do
                        end do
                    end do
                end do
            end do
        end do
    end do
end do
Is there something wrong with this? Is there a better way of doing it?

Thanks!
 
Will you please now explain in plain English which possible combinations you are talking about?
 
Sure.

I have X1, X2, X3,..., X9. Each one can take 2 values (i.e. X1=(X11,X22)). Therefore, in total i can create 2^9 vectors of length 9 in which the first element is X1, the second X2, etc.
That is, B(1,:)=(X11, X21, X31, ..., X91)
That makes more sense?

Thanks!
 
I am sure there is a better way of doing it. Just focus in a smaller example, first, say, instead of 9 variables, start with 3...and, because each variable can only take two values...well, it is a binary thing, as you pointed out:
Code:
x1 x2 x3
 0  0  0
 0  0  1
 0  1  0
 0  1  1
 1  0  0
 1  0  1
 1  1  0
 1  1  1
where zero means that you need to insert the first value of such variable and one means the second, if you will.

Notice how the left most column has the same value in the first half and the other value on the second half.

The next column switches values every quarter.

The right most every eigth.

As you can see the matrix above simply contains the binary representation of the number 0 thru 7, a total of 2^3 numbers.



 
salgerman, I think that is exactly what I'm doing with my nested loops
 
Well, I came up with a solution with just 2 nested do loops. Just include the declaration of integer needed and give it a try.

Code:
integer ncol, tot, div, n, m, i, fr, to
.
.
.
ncol = 9
B = 0
tot = 2**ncol
do n = 1, ncol
    div = 2**n
    step = tot/div
    do m = 0, div-1
        fr = 1 + m*step
        to = fr + step
        B(fr:to,n) = X(n, 1+mod(m,2))
    end do
end do

do n = 1, tot
    write(*,*) (B(n,i), i=1,ncol)
end do
 
You may want to add a better format to the write statement if you number are of various widths...you know, so they are nicely lined up.
 
You are awesome salgerman!

I have one more question. Can this be extended to write the cartesian product of n sets is the set of ordered n-tuples containing one element from each set?
I found some C code, but I don't know any C :_(

Thanks a lot!
 
Don't know any C? Do you know "any cartesian product" and "any fortran"...then give it a try! If you can do it by hand, you should be able to do it in a program...granted, it may not end up optimal...but it is a start; once you put something together, it will occur to you how to improve it and improve it...it's call "prototype and re-start".
 
i "sort of" get what you are trying to do.
but, your code seems to be doing 1 thing, and your "description" (of what you're trying to do) seems to want something else.


regarding the nested do loops:- maybe you could try using a recursive subroutine (or recursive function) ? for example, see below :-


in the following, if X3 = (X31,X32) etc, then let XI (J) = X (I,J), with 1 <= I <= 9, and 1 <= J <= 2 ---> e.g. X (3,2) = X32, and X (5,1) = X51
-------------------------------------------
Code:
MAIN PROGRAM


! let E = indicates which variable XI the current (recursive) DO loop is for (e.g. if E = 4, then X4 is current)
! let STATE (E) = indicates the current "state" of XI number E (i.e. it's X1 or X2 value) (e.g. E = 4, then either it's X41 or X42 value)
! let F = indicates which combination number (in B) the current "system" of DO loops represents (where 1 <= F <= 512)

E = 1
F = 1

CALL SUB_1 ( E , STATE , F , X , B )

END MAIN PROGRAM
-------------------------------------------
RECURSIVE SUBROUTINE SUB_1 ( E , STATE , F , X , B )

INTEGER ,INTENT (IN)    :: E
INTEGER ,INTENT (INOUT) :: STATE (9)
INTEGER ,INTENT (INOUT) :: F
??      ,INTENT (IN)    :: X
??      ,INTENT (INOUT) :: B


IF ( E <= 9 ) THEN

! loop over each "state" of current XI

   DO I = 1 , 2
      STATE (E) = I
      NEXT_E    = E + 1
      CALL SUB_1 ( NEXT_E , STATE , F , X , B )
   END DO
ELSE

! assign values to the current combination in B

   DO J = 1 , 9
      T       = STATE (J)
      B (F,J) = X (J,T)
   END DO

! update the next combination number in B

   F = F + 1

   RETURN
END IF

END SUBROUTINE SUB_1

well, it might be a bit rough :) but it should give you the basic idea
i think it does similar to what salgerman suggested

btw i hope your question wasn't a "homework assignment" :)
 
oops ! i forgot some "dimension" details ...

the lines

Code:
??      ,INTENT (IN)    :: X
??      ,INTENT (INOUT) :: B
should instead be

Code:
??      ,INTENT (IN)    :: X (9,2)
??      ,INTENT (INOUT) :: B (512,9)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top