generating list for joint distribution - python

I'm pretty sure this is an easy problem but I am completely blacking out on how to fix this. I am trying to work my way through the PGM class on coursera and it starts of with joint probability distribution. So I am trying to generate a list of all possible distributions given n variables, where each variable can take on some discrete value between 0...z
so for instance say we have 3 variables, and each can take on values of just 0 and 1 I want to generate this:
[[0, 0, 1]
[0, 1, 0]
[1, 0, 0]
[1, 1, 0]
[0, 1, 1]
[1, 1, 1]
[1, 0, 1]
[0, 0, 0]]
I am working in python I am drawing a blank on how to dynamically generate this.

If you prefer list comprehension:
[[a, b, c] for a in range(2) for b in range(2) for c in range(2)]
And I forgot to mention that you can use pprint to get the effect you want:
>>> import pprint
>>> pprint.pprint([[a, b, c] for a in range(2) for b in range(2) for c in range(2)])
[[0, 0, 0],
[0, 0, 1],
[0, 1, 0],
[0, 1, 1],
[1, 0, 0],
[1, 0, 1],
[1, 1, 0],
[1, 1, 1]]
>>>

It sounds like you want the Cartesian product:
from itertools import product
for x in product([0,1], [0,1], [0,1]):
print x
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]

Slight improvement over Nathan's method:
>>> import itertools
>>> list(itertools.product([0, 1], repeat=3))
[(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1),
(1, 0, 0),
(1, 0, 1),
(1, 1, 0),
(1, 1, 1)]

Related

How to add an array twice by two TRUE conditions?

this is my code:
import numpy as np
from scipy.ndimage.interpolation import shift
B = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
F = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 0, 0, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
M = np.array([[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 0],
[1, 2, 1, 2, 1],
[1, 2, 1, 2, 1]])
if F[2, 4] == 1:
B = np.add(M, B)
if F[1, 4] == 1:
M_shift = shift(M, (-1, 0), cval=0)
B = np.add(M_shift, B)
print(B)
I want to add M to B if the condition for F is true. In this example both if-conditions are true and i thought that my code will add two times M to B. But apparently it's not working? What is wrong?
Thanks in advance.
EDIT for arra:
My desired output is in this case, my code snippet should add the matrix with B and also the shifted version of M. Because both conditions are True. But as u said the first assignment is overwritten. How can I prevent the overwriting for this case?
The output, after the assignment should look like this:
B = np.array([[2, 4, 2, 4, 2],
[2, 4, 2, 4, 1],
[2, 4, 2, 4, 1],
[2, 4, 2, 4, 2],
[1, 2, 1, 2, 1]])
I guess a good way is to use a for-loop because i want to check all array entries in Matrix F, if there's a 1. But i reckon that if i use the np.add function I'll overwrite it again
You overwrite B in the second if, so any previous value will be erased. Not sure what you are trying to achieve in your code, but don't you want something like:
B = np.add(M_shift, B)
or
intermediateVal = np.add(M_shift, F)
B = np.add(B, intermediateVal)

Correct generation of words in python

I think the intentions of this code are clear. I want to have in X all possible input words, with each digit being an element in a list. The following code works for 4 digits, but it gets unsustainable for bigger words. How can I make it more scalable? Let's assume I want the words of n digits instead of four.
d = [0,1]
X = [[x1,x2,x3,x4] for x1 in d for x2 in d for x3 in d for x4 in d]
You can use itertools.product for that:
from itertools import product
d = [0,1]
x = [list(t) for t in product(d,repeat=4)]
This gives:
>>> x
[[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 1, 1], [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1], [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]]
And by modifying repeat= to for instance 5 you get all possible 5-digit lists.
In case you do not need lists - the elements are not supposed to be altered - tuples can be used, and in that case you can drop the list(..) construction:
# list of tuples
from itertools import product
d = [0,1]
x = list(product(d,repeat=4))
This generates:
>>> x
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]
Note that product(..) itself is a generator: it generates the elements lazily. This can be useful if the number of resulting elements will be huge and you can process them one-at-a-time. In that case you thus better do not construct a list. You can for instance use:
for tup in product(d,repeat=4):
print(tup)
To print all tuples. Although the effect would be the same as with a for tup in x:, now the memory usage can be lower (it depends on the implementation of the garbage collector in the interpreter): since not all tuples have to be in memory at the same time. The next tuple the generator emit can possibly reuse the memory the previous tuple took since that place is now vacant (at least given you do not store the tuples in a list, etc.)

Get all permutations of a numpy array

I have a numpy array [0, 1, 1, 2, 2, 0, 1, ...] which only contains the numbers 0-k. I would like to create a new array that contains the n possible arrays of permutations of 0-k. A small example with k=2 and n=6:
a = [0, 1, 0, 2]
permute(a)
result = [[0, 1, 0, 2]
[0, 2, 0, 1]
[1, 0, 1, 2]
[2, 1, 2, 0]
[1, 2, 1, 0]
[2, 0, 2, 1]]
Does anyone have any ideas/solutions as to how one could achieve this?
Your a is what combinatorists call a multiset. The sympy library has various routines for working with them.
>>> from sympy.utilities.iterables import multiset_permutations
>>> import numpy as np
>>> a = np.array([0, 1, 0, 2])
>>> for p in multiset_permutations(a):
... p
...
[0, 0, 1, 2]
[0, 0, 2, 1]
[0, 1, 0, 2]
[0, 1, 2, 0]
[0, 2, 0, 1]
[0, 2, 1, 0]
[1, 0, 0, 2]
[1, 0, 2, 0]
[1, 2, 0, 0]
[2, 0, 0, 1]
[2, 0, 1, 0]
[2, 1, 0, 0]
if your permutations fit in the memory, you could store them in a set and thus only get the distinguishable permutations.
from itertools import permutations
a = [0, 1, 0, 2]
perms = set(permutations(a))

binary list contains all possible options by knowing its length in python

i am trying to get a binary list contains all possibilities by providing the length of these possible lists , now i found a solution but it is not very handy to be used in other functions.
example : i want a list of lists each one represents one binary option of four digits.
if the length is 4 then the result should be the following.
[[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 1, 1], [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1], [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]]
what i have done is by the following code:
>>> [[a, b, c, d] for a in [0,1] for b in [0,1] for c in [0,1] for d in [0,1]]
Now , i am looking for a way that by knowing the length of each member binary list we can generate the big list without the need to type manually [ a, b, c, d] , so if is possible to generate the list by a function lets say L_set(4) we get the list above . and if we type L_set(3) we get the following:
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
and by typing L_set(2) we get :
[[0, 0], [0, 1], [1, 0], [1, 1]]
and so on.
After spending few hours i felt stuck here in this point , i hope that some of you can help.
Thanks
Looks like a job for itertools.product:
>>> import itertools
>>> n = 4
>>> list(itertools.product((0,1), repeat=n))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]
I think the itertools module in the standard library can help, in particular the product function.
http://docs.python.org/2/library/itertools.html#itertools.product
for x in itertools.product( [0, 1] , repeat=3 ):
print x
gives
(0, 0, 0)
(0, 0, 1)
(0, 1, 0)
(0, 1, 1)
(1, 0, 0)
(1, 0, 1)
(1, 1, 0)
(1, 1, 1)
the repeat parameter is the length of each combination in the output
If you know the length to be n, then try this:
[list(bin(i)[2:]) for i in xrange((2**n)-1)]
In [12]: list(product(range(2), repeat=2)
Out[12]: [(0, 0), (0, 1), (1, 0), (1, 1)]

How to set lower triangular matrix of 0-1?

I need to make a matrix, for n dimensions, to look like this for n=4:
[0,0,0,0]
[1,0,0,0]
[1,1,0,0]
[1,1,1,0]
because I need the positions of the 1s, ie
0, 1
0, 2
0, 3
1, 2
1, 3
2, 3
This is because I want to work out the distances between x points, without wasting time repeating a distance. These coordinates will let me do it only once.
You essentially want to increment the number of 1s (starting from 0) in each row, while padding the rest of the row with 0s, thereby keeping a constant length. Try something like this:
>>> n = 4
>>> [[1]*i + [0]*(n - i) for i in xrange(n)]
[[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0]]
If you're using NumPy:
>>> import numpy as np
>>> np.tril(np.ones((n, n), dtype=int), -1)
array([[0, 0, 0, 0],
[1, 0, 0, 0],
[1, 1, 0, 0],
[1, 1, 1, 0]])
List comprehensions to the rescue!
>>> matrix = [[1]*i + [0]*(4-1) for i in range(4)]
Substitute 4 with any range you want. For Python lower than 3.X you should you xrange instead of range
for n=5
matrix = [[1 if x<y else 0 for x in range(n)] for y in range(n)]
The output:
[0, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 1, 0, 0, 0]
[1, 1, 1, 0, 0]
[1, 1, 1, 1, 0]
You explained that your reason for wanting the lower triangular matrix is to get the positions of the 1s. If that is really the only reason for making the matrix, there are more efficient ways to generate those positions. In particular, itertools.combinations(range(n), 2) would work:
In [209]: import itertools
In [210]: list(itertools.combinations(range(4), 2))
Out[210]: [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]

Categories

Resources