def __init__(self, state_word_len, variables): """ Initialize the internal helper class. """ self.state_word_len = state_word_len self.variables = variables variable_names = map(lambda i: 'S%d' % i, xrange(self.state_word_len)) variable_names += self.variables self.qm = qm.QM(variable_names)
def main(): n = 3 qm1 = qm.QM([chr(code) for code in xrange(ord('A'),ord('A')+n)]) for minterms in itertools.chain(*(itertools.combinations(range(1<<n),i) for i in xrange(1,1<<n+1))): minterms = set(minterms) if max(minterms) == 0: continue for dc in itertools.chain(*(itertools.combinations(minterms,i) for i in xrange(0,len(minterms)+1))): dc = list(dc) ones = list(minterms - set(dc)) check = qm1.solve(ones,dc) correct = qm_orig.qm(ones=ones,dc=dc) if not eq(check, correct, dc): print 'ERROR',ones,dc,t(check, n),qm1.get_function(check[1]),correct,check
def get_canonical_minimal_sop_from_string(boolean_string, boolean_variables): '''Returns the full minimal canonical form for all the variables passed, given the string, or simply '0' if the string always evaluates to False. >>> get_canonical_minimal_sop_from_string('A AND (B OR C)', ['A', 'B', 'C']) [(3, 4), (5, 2)] ''' min_terms = get_minterms_from_string(boolean_string, boolean_variables) _qm = qm.QM(boolean_variables) minimal_sop = _qm.solve(min_terms, []) return minimal_sop[1]
def Getfunc(inputlist, output, onlist, prefix='n', suffix='n', equal_sign='*='): ''' Return a Boolean regulatory rule in the disjuctive normal form (in the format of Booleannet) based on given truth table. For more details about Booleannet, refer to https://github.com/ialbert/booleannet. It is essentially a wrapper for the Quine-McCluskey algorithm to meet the format of Booleannet. Parameters ---------- inputlist : a list of nodenames of all the parent nodes/ regulators output : the nodename of the child node onlist : a list of all configurations(strings) that will give a ON state of the output based on rule e.g. the onlist of C = A OR B will be ['11','10','01'] prefix='n': prefix to encode the node name to avoid one node's name is a part of another node's name suffix='n': suffix to encode the node name to avoid one node's name is a part of another node's name e.g. node name '1' will become 'n1n' in the returned result equal_sign: the equal sign of the rule in the returned result, whose default value follows the Booleannet format Returns ------- The Boolean rule in the disjuctive normal form. References ---------- QM code by George Prekas. ''' #pre-processing to meet the format requirement of QM and Booleannet inputs = [prefix + str(x) + suffix for x in inputlist] inputs.reverse() output = prefix + str(output) + suffix + equal_sign onindexlist = [int(x, 2) for x in onlist] if len(inputs) > 0: qmtemp = qm.QM(inputs) temprule = qmtemp.get_function(qmtemp.solve(onindexlist, [])[1]) temprule = temprule.replace('AND', 'and') temprule = temprule.replace('OR', 'or') temprule = temprule.replace('NOT', 'not') else: temprule = output[:-2] return output + temprule + '\n'
def minimize(Equations): Max = {} for name in Equations: Max[name] = max(Equations[name]) minimized = {} for name in sorted(Equations): minimized[name] = {} for value in Equations[name]: Eq = Equations[name][value] names = [name] + sorted(Eq.variables()) if any([max(Equations[n]) > 1 for n in names]): minimized[name][value] = 'Non-Boolean' continue # sum notation for QM input names = sorted(Eq.variables()) ones = [] size = len(names) for i, y in enumerate(itertools.product(*size * [[0, 1]])): y = dict(zip(names, y)) if Eq(y): ones.append(i) # run QM rev = names[:] rev.reverse() solver = qm.QM(rev) minterms = solver.compute_primes(ones) dcs = [] f = solver.get_function(solver.solve(ones, dcs)[1]) f = f.replace(' AND ', ' & ') f = f.replace(' OR ', ' | ') f = f.replace('NOT', '!') if f[0] == '(' and f[-1] == ')': f = f[1:-1] minimized[name][value] = f return minimized
def _solve( Equation, Max, Minimize ): # one boolean variable for each threshold BooleanVariables = [] for name in Equation.variables(): for v in range(Max[name]+1): # for v in range(1,Max[name]+1): BooleanVariables.append( '%s=%i'%(name,v) ) size = len(Equation.variables()) # sum notation for QM input ones = [] dcs = [] for i,y in enumerate(itertools.product(*len(BooleanVariables)*[[0,1]])): y = zip(BooleanVariables,y) # boolean state to multi value state valid = True x = {} for atom, state in y: if state: name, value = atom.split('=') value = int(value) if name in x: valid = False break x[name] = value if not len(x)==size: valid=False if not valid: dcs.append(i) pass elif Equation(x): ones.append(i) # run QM rev = BooleanVariables[:] rev.reverse() solver = qm.QM( rev ) minterms = solver.compute_primes(ones+dcs) if Minimize: minimized = solver.get_function( solver.solve( ones,dcs )[1] ) minimized = minimized.replace(' AND ',' & ') minimized = minimized.replace(' OR ',' | ') minimized = minimized.replace('NOT','!') return minimized # convert minterms to primes primes = [] for i,minterm in enumerate(minterms): print '---' options = {} #dict([(name,range(Max[name]+1)) for name in Equation.variables()]) valid = True m = [] for j in xrange(len(rev)): name, value = rev[j].split('=') value = int(value) if minterm[0] & 1<<j:# non-negated literal #prime[rev[j]]=1 m.append('%s==%i'%(name,value)) if options.has_key(name):# invalid prime if not value in options[name]: print 'invalid 1' valid=False options[name]=[value] elif not minterm[1] & 1<<j:# negated literal #prime[rev[j]]=0 m.append('%s!=%i'%(name,value)) if not options.has_key(name): options[name]=range(Max[name]+1) options[name] = [k for k in options[name] if not k==value] if not options[name]: valid=False print 'invalid 2' print 'minterm:',','.join(sorted(m)) if not valid: continue print 'options:',options.items() names = sorted(options) ranges = [options[k] for k in names] for p in itertools.product( *ranges ): p = dict(zip(names,p)) if p not in primes: primes.append( p ) for p in primes: print p return primes options = {} #dict([(name,range(Max[name]+1)) for name in Equation.variables()]) valid = True m = [] for j in xrange(len(rev)): name, value = rev[j].split('=') value = int(value) if minterm[0] & 1<<j:# non-negated literal #prime[rev[j]]=1 m.append('%s==%i'%(name,value)) if options.has_key(name):# invalid prime if not value in options[name]: valid=False options[name]=[value] elif not minterm[1] & 1<<j:# negated literal #prime[rev[j]]=0 m.append('%s!=%i'%(name,value)) if not options.has_key(name): options[name]=range(Max[name]+1) options[name] = [k for k in options[name] if not k==value] print ','.join(sorted(m)) if not valid: continue names = sorted(options) ranges = [options[k] for k in names] if i==5: for k in options: print k,options[k] for p in itertools.product( *ranges ): p = dict(zip(names,p)) if p not in primes: primes.append( p )