Iteration over n values - python

I'd like to make an iteration to calculate all the possibilities of a given formula. I need to write down nested iteration but couldn't make it right. I am not good at algorithm :(
For calculating all the possibilities(%0-%100) 3 constant{z1,z2,z3} values, I prepared:
a=frange(0,1.0,0.01)
for z1 in a:
for z2 in a:
for z3 in a:
calculate(z1,z2,z3)
and works properly as I expected.
If z is a list which consists of n values(n can be 2-30 in my case), Which algorithm do you suggest to me to handle this? How can I create nested iteration?

The easiest way is to use itertools.product():
a=frange(0,1.0,0.01)
for z in itertools.product(a, repeat=n):
calculate(*z)
If n really would be 30, this would iterate over 100**30 = 10**60 values. Be prepared to wait.

itertools.product will do what you want (and more). Unfortunately it wants the lists whose products it computes in separate arguments, like this:
>>> list(itertools.product([1,2,3],[1,2,3]))
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
so on the face of it you need to do something like this:
a=frange(0,1.0,0.01)
for (z1,z2,z3) in itertools.product(a,a,a): calculate(z1,z2,z3)
but if you want to use the exact code for different numbers of products you can say
a=frange(0,1.0,0.01)
for (z1,z2,z3) in itertools.product(*(3*[a])): calculate(z1,z2,z3)
or
a=frange(0,1.0,0.01)
for (z1,z2,z3) in apply(itertools.product, 3*[a]): calculate(z1,z2,z3)

Related

How to make a matrix from two arrays

I have two arrays:
import numpy as np
MC=np.array([1, 2, 3])
oo=np.array([4,5,6])
for i in range(0, len(MC)):
for j in range(0, len(oo)):
H[i,j]=(MC[i],oo[j])
print(oo)
print(H)
I want an output matrix like this and I get an error (list indices must be integers or slices, not tuple):
H=[[(1,4),(1,5),(1,6)],[(2,4),(2,5),(2,6)],[(3,4),(3,5),(3,6)]]
"I get an error" is quite unspecific. So you should provide more details. But I assume that you get a NameError since H is not defined anywhere before using it. But looking at you implementation I can't see how you would get the desired result anyway. If you generally don't know the length of the given arrays in advance you could try
H = []
for i in range(0, len(MC)):
H.append([])
for j in range(0, len(oo)):
H[-1].append((MC[i], oo[j]))
That should give you the desired output. Or in my opinion even better, particulary in terms of readability:
H = []
for mc_el in MC:
H.append([])
for oo_el in oo:
H[-1].append((mc_el, oo_el))
Or (inspired by nikoros' answer):
H = [[(MC_el, oo_el) for oo_el in oo] for MC_el in MC]
Instead of manually iterating the arrays, you can combine groupby and product from itertools, you can create the required list of list of tuples in List-Comprehension
>>> from itertools import groupby, product
>>> [list(product([k], oo)) for k,v in groupby(MC)]
[[(1, 4), (1, 5), (1, 6)], [(2, 4), (2, 5), (2, 6)], [(3, 4), (3, 5), (3, 6)]]

How to get all permutations of a list taken k things at at a time using a user defined recursive function(Python)

I'd like to make a recursive algorithm generating all permutations of a list of integers taken k things at a time.
To be specific, what I want to do is create a recursive function Perm(list, k) from scratch returning a output satisfying the following condition.
from itertools import permutations
li = [1,2,3,4]
set(permutations(li, 2)) == set(Perm(li, 2))
I tried it by referring to the Shailaja's codes (Perm(lst,n)) from this link: Recursive Algorithm to generate all permutations of length k of a list in Python
Since the function returns a nested list, I've tried to convert the nested list to a set of tuples. However, I was unable to find any solutions because the function is a recursive algorithm. Could anyone help me out to change the Perm function to get the following format of outputs? Thanks a lot.
# the output of set(Perm(li, 2))
{(1, 2),
(1, 3),
(1, 4),
(2, 1),
(2, 3),
(2, 4),
(3, 1),
(3, 2),
(3, 4),
(4, 1),
(4, 2),
(4, 3)}
Since the function returns a nested list, I've tried to convert the nested list to a set of tuples.
Yes, that is indeed what is needed. So Perm should yield tuples.
Here is a possible recursive implementation for Perm:
def Perm(lst, size):
if size <= 0:
yield () # empty tuple
else:
for i, val in enumerate(lst):
for p in Perm(lst[:i] + lst[i+1:], size-1):
yield (val, *p)
This passes the test given in the question.

What is a pythonic way to find set of lists which have all common elements?

Say I have a list a=[[1,2],[1.00000001,2.000000001],[2,3],[4,5],[4.0000000002,5.0000006]], and from that I want to get only a=[[1,2],[2,3],[4,5]] because the other lists have all elements close to some other element of the list. How do we do this in Python? Can set be used in some way?
I tried using numpy's allclose function but then we have to compare all n(n-1)/2 pairs in the list a, which is clearly inefficient. Is there a more efficient Pythonic way to do this?
Edit: I just used some integers in the example, the inputs are floats in general.
If the values are like that (i.e. what looks like floating point inaccuracy, you can round the values to the precision you're interested in, then use set() to reduce things to unique tuples:
>>> a=[[1,2],[1.00000001,2.000000001],[2,3],[4,5],[4.0000000002,5.0000006]]
>>> a_r = [tuple(round(v, 2) for v in pair) for pair in a]
[(1, 2), (1.0, 2.0), (2, 3), (4, 5), (4.0, 5.0)]
>>> set(a_r)
{(2, 3), (4, 5), (1, 2)}
For the data sample in your list and the expected result, as you can use Numpy, i'd suggest to use dtype to convert to integer and use numpy.unique.
So, given your list:
a=[[1,2],[1.00000001,2.000000001],[2,3],[4,5],[4.0000000002,5.0000006]]
You can do as follows:
import numpy as np
a_np = np.unique(np.array(a, dtype=np.uint), axis=0)
print(a_np)
# [[1 2]
# [2 3]
# [4 5]]

Algorithm to generate subsets satisfying binary relation

I am looking for a reasonable algorithm in python (well, because I have rather complicated mathematical objects implemented in python, so I cannot change the language) to achieve the following:
I am given a reflexive, symmetric binary relation bin_rel on a set X. The requested function maximal_compatible_subsets(X, bin_rel) should return all containmentwise maximal subsets of X such that the binary relation holds for all pairs a,b of elements in X.
In some more detail: Suppose I am given a binary relation on a set of objects, say
def bin_rel(elt1,elt2):
# return True if elt1 and elt2 satisfy the relation and False otherwise
# Example: set intersection, in this case, elt1 and elt2 are sets
# and the relation picks those pairs that have a nonempty intersection
return elt1.intersection(elt2)
I can also assume that the relation bin_rel is reflexive (this is, binary_rel(a,a) is True holds) and symmetric (this is, binary_rel(a,b) is binary_rel(b,a) holds).
I am now given a set X and a function bin_rel as above and seek an efficient algorithm to obtain the desired subsets of X
For example, in the case of the set intersection above (with sets replaced by lists for easier reading):
> X = [ [1,2,3], [1,3], [1,6], [3,4], [3,5], [4,5] ]
> maximal_compatible_subsets(X,bin_rel)
[[[1,2,3],[1,3],[1,6]], [[1,2,3],[1,3],[3,4],[3,5]], [[3,4],[3,5],[4,5]]]
This problem doesn't seem to be very exotic, so most welcome would be a pointer to an efficient existing snippet of code.
As Matt Timmermans noted this is finding maximal cliques problem that can be solved by Bron–Kerbosch algorithm. NetworkX has implementation that can be used for Python.
If you want to use python straight out of the box, you could use the following as a starting point:
from itertools import combinations
def maximal_compatible_subsets(X, bin_rel):
retval = []
for i in range(len(X) + 1, 1, -1):
for j in combinations(X, i):
if all(bin_rel(a, b) for a, b in combinations(j, 2)) and not any(set(j).issubset(a) for a in retval):
retval.append(tuple(j))
return tuple(retval)
if __name__ == '__main__':
x = ( (1,2,3), (1,3), (1,6), (3,4), (3,5), (4,5) )
def nonempty_intersection(a, b):
return set(a).intersection(b)
print x
print maximal_compatible_subsets(x, nonempty_intersection)
Outputs:
((1, 2, 3), (1, 3), (1, 6), (3, 4), (3, 5), (4, 5))
(((1, 2, 3), (1, 3), (3, 4), (3, 5)), ((1, 2, 3), (1, 3), (1, 6)), ((3, 4), (3, 5), (4, 5)))

Get all combinations of list elements not ignoring position in Python

I want to combine all elements of a list into sublists (not tuples) with a specified length.
The itertools.combinations_with_replacement generator does nearly what I want to achieve:
>>> list(itertools.combinations_with_replacement([1,2],2))
[(1, 1), (1, 2), (2, 2)]
There are only two things I dislike: It creates tuples instead of sublists (what I could change with a map), and it misses the element (2,1) in the example above.
Is there any builtin module in Python 2 that does what I want? If not, is there any simple way to at least get combinations_with_replacements (or any other module function) to generate the missing element in the provided example?
maybe:
>>> from itertools import product
>>> list(product([1, 2], repeat=2))
[(1, 1), (1, 2), (2, 1), (2, 2)]

Categories

Resources