1

I am trying to find all combinations of a four element vector that contains only 1's and -1's. Ex (1,1,1,1),(-1,1,1,1),...(-1,-1,-1,-1) etc My idea to do this is pretty inefficient im sure but I can't think of another way to do it, so here is what I was trying to do. I found how many total vectors there would be, then created that many empty lists. I began with vector A and then compared this to each list in vectors. If A matched any of the lists then I randomly changed the sign of an element of A, and then again checked the new list A against vectors. If A didn't find a match then it replaced on of the lists in vectors, and the while loop was incremented by 1. This should proceed until all possible combinations have been found and printed. However my code is just spitting out the first change in vectors then continually looping without adding any new A's to vectors. Can anyone spot what in my code isn't doing what I intended it to do and/or point me in the right direction? Thanks

import random
numvec = 2**4 # number of macrostates for a 4 component 2-state system

vectors = [[0,0,0,0] for i in range(numvec)] #initializing the numvec vectors 
A = [1,1,1,1]
i = 0
while i < 16:
    if any(x == A for x in vectors):
        y = random.randrange(0, 3)
        A[y] = A[y] * -1
    else:
        vectors[i] = A
        print vectors[i] 
        i += 1

print vectors

Oh and again I realize this method is incredibly inefficient but as this is a homework assignment I am more concerned with being able to get python to do what I want it to do, then using a bunch of built in functions to do the work for me. Thanks again.

3 Answers3

4

I think you can do this easily with the itertools.product built-in function:

list(itertools.product([-1,1], repeat=4))

Alternatively, you could write it all out with a list comprehension. This is much more verbose, but it avoids using the itertools library:

list((i,j,k,l) for i in (-1,1) for j in (-1,1) for k in (-1,1) for l in (-1,1))
DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • yeah I had gotten that impression that I could use `itertools` but I was trying not to use it as that would be too easy. the point of the assignment was to get some experience using if statments – user2727518 Aug 29 '13 at 02:38
  • ok thanks, that's good food for thought, I will defiantly be looking at what `itertools` can do for future projects – user2727518 Aug 29 '13 at 03:03
  • The second answer doesn't use itertools in case you haven't noticed. – Joohwan Aug 29 '13 at 03:09
1
vectors[i] = A

This doesn't create a copy of A. When you change A, the contents of vectors change, because vectors[0] and A are the same object after the first time this line runs. To fix this, make a new A object every time, or copy A and insert the copy into the list.

If you want to make a copy, you can use Python's slice notation:

vectors[i] = A[:]
Community
  • 1
  • 1
user2357112
  • 260,549
  • 28
  • 431
  • 505
0

For educational purposes (considering that people with a similar problem are probably looking for the general recursive approach - a classic task)

def get_possibilities(elements, length=1):
    if length == 0:
        return [[]]

    if length > 0:
        tails = get_possibilities(elements, length=length-1)
        return [[x] + t for x in elements for t in tails]   

results = get_possibilities([1,-1], 4)

How this works by example:

[1,-1], length=4
call get_possibilities([1,-1],4) (main)
call get_possibilities([1,-1],3) (from get_possibilities)
call get_possibilities([1,-1],2) (from get_possibilities)
call get_possibilities([1,-1],1) (from get_possibilities)
call get_possibilities([1,-1],0) (from get_possibilities)

return [[]] (from the [1,-1], 0 call)

merge any element (here 1,-1, as list) with any element of the prior return
return [[1],[-1]] (from the [1,-1], 1 call)

merge any element (here 1,-1, as list) with the prior return
return [[1, 1], [1, -1], [-1, 1], [-1, -1]] (from the [1,-1], 2 call)

merge any element (here 1,-1, as list) with the prior return
return [[1, 1, 1], [1, 1, -1], [1, -1, 1]...] (8 elements, 2**3) (from the [1,-1], 3 call)

merge any element (here 1,-1, as list) with the prior return
return [[1, 1, 1, 1], [1, 1, 1, -1], ...] (16 elements 2**4) (from the [1,-1], 4 call)

greetings

PS: i would guess that itertools.product works similarly ;)

Xevelion
  • 859
  • 6
  • 9