I want to create a class in python that contains variables and a domain for each variable to generate a list of dictionary containing all the possible solutions for variables assignments
for exemple:
x='x'
y='y'
domainx=[1,2]
domainy=[3,4]
def solutions(elt,elt2,domainx,domainy):
for i in domainx:
for j in domainy:
liste.append({elt:i,elt2:j})
return liste
liste now is equal to [{'x':1,'y'=3},{'x':1,'y'=4},{'x':2,'y':3} etc..]
but this function it's not flexible and reutilizable because i must declare the variable one by one. what i want is generate solutions from a liste like : liste=[(x,[1,2]),(y,[3,4])or liste=[(x,[324,3433]),(y,[43,34354,45]),(z,[5445,653,3,34,4,5])]
then i pass the liste to a function that will generate the solutions,i don't know how to do it especially that i should do as many as the length of liste is.
My purpose for this question is to create this class,
class CST:
def __init__(self):
self.variables=[]
self.contraintes=[]
self.VarWithdomaines=[]
def addVarDom(self,variable,domain):
self.VarWithdomaines.append((variable,domain))
# def generate(self): it's not the correct way
# liste=[]
# for repitition in range(len(self.domaines)):
# solution={}
# for noeud in self.domaines:
# var=noeud[0]
# for x in noeud[1]:
# solution[var]=x
# liste.append(solution)
# return liste
Game=CST()
domain = [int(i) for i in range(2)]
domain2 = [int(i) for i in range(3)]
domain3 = [int(i) for i in range(21)]
# domain4 = [int(i) for i in range()]
Game.addVarDom("E1",domain)
Game.addVarDom("E2",domain2)
Game.addVarDom("C20",domain3)
listofsolutions=Game.generate())
#list should be for exemple list=[{E1:1,E2:0,C20:20},{E1:0,E2:2,C20:12}...]
CodePudding user response:
Try using itertools
!
Essentially, itertools.product
does what you want. As explained in the docs, this function takes the Cartesian product of input iterables. So, list(itertools.product([0, 1], [2, 3]))
produces [(0, 2), (0, 3), (1, 2), (1, 3)]
, which is basically all you want.
All that's left is converting that output to the format you're looking for:
import itertools
def assignments(names, values):
combinations = itertools.product(*values)
return [
{
name: value
for name, value in zip(names, combination)
}
for combination in combinations
]
assignments(['x', 'y', 'z'], [[1, 2], [3, 4], [5, 6]])
This would produce the array
[
{'x': 1, 'y': 3, 'z': 5},
{'x': 1, 'y': 3, 'z': 6},
{'x': 1, 'y': 4, 'z': 5},
{'x': 1, 'y': 4, 'z': 6},
{'x': 2, 'y': 3, 'z': 5},
{'x': 2, 'y': 3, 'z': 6},
{'x': 2, 'y': 4, 'z': 5},
{'x': 2, 'y': 4, 'z': 6},
]
CodePudding user response:
Thanks to @BrownieInMotion I have modified the methods in the class and it's worked, modified methods:
def addVarDom(self,variable,domain):
self.variables.append(variable)
self.domaines.append(domain)
def generate(self):#names, values):
combinations = itertools.product(*self.domaines)
return [
{
name: value
for name, value in zip(self.variables, combination)
}
for combination in combinations
]