def swap_variables(self, cur_vars, new_vars): assert len(cur_vars) == len(new_vars) num_vars = len(cur_vars) next_var_array = pycudd.DdArray(num_vars) curr_var_array = pycudd.DdArray(num_vars) for i in range(num_vars): curr_var_array.Push(cudd.IthVar(cur_vars[i])) next_var_array.Push(cudd.IthVar(new_vars[i])) b = BDD() b._cudd_bdd = self._cudd_bdd.SwapVariables(next_var_array, curr_var_array, num_vars) return b
def _DDArrayFromList(self, elements): # We have to do this silly type conversion because we're using a very loosely-wrapped C library dd_array = pycudd.DdArray(len(elements)) for idx, el in enumerate(elements): dd_array[idx] = el return dd_array
def get_one_minterm(self, vars): b = BDD() num_vars = len(vars) var_array = pycudd.DdArray(num_vars) for i in range(num_vars): var_array.Push(cudd.IthVar(vars[i])) b._cudd_bdd = self._cudd_bdd.PickOneMinterm(var_array, num_vars) return b
def prime_latches_in_bdd(states_bdd): latch_bdds = get_all_latches_as_bdds() num_latches = len(latch_bdds) #: :type: DdArray next_var_array = pycudd.DdArray(num_latches) curr_var_array = pycudd.DdArray(num_latches) for l_bdd in latch_bdds: #: :type: DdNode l_bdd = l_bdd curr_var_array.Push(l_bdd) lit = l_bdd.NodeReadIndex() primed_l_bdd = get_primed_variable_as_bdd(lit) next_var_array.Push(primed_l_bdd) primed_states_bdd = states_bdd.SwapVariables(curr_var_array, next_var_array, num_latches) return primed_states_bdd
def get_all_vars_array(self): # NOTE: This way of building the var_array does not look # robust. There might be an issue if variables are # added and the order of enumeration of the dictionary # changes and we rely on this order outside of this class. with LockDdManager(self.ddmanager): var_array = pycudd.DdArray(len(self.idx2var)) for i, node_idx in enumerate(self.idx2var): var_array[i] = self.ddmanager[node_idx] return var_array
def get_free_cube(self): num = len(self.var_ord.values()) - len(self.vis_indices) vs = pycudd.DdArray(num) phase = pycudd.IntArray(num) k = 0 for i in self.var_ord.values(): if i not in self.vis_indices: vs[k] = mgr.IthVar(i) phase[k] = 1 k += 1 return self.mgr.ComputeCube(vs, phase, num)
def compose(self, cur_vars, new_funs): assert len(cur_vars) == len(new_funs) fun_array = pycudd.DdArray(next_free_var) for i in range(next_free_var): if i in cur_vars: fun_array.Push(new_funs[cur_vars.index(i)]._cudd_bdd) else: fun_array.Push(cudd.IthVar(i)) b = BDD() b._cudd_bdd = self._cudd_bdd.VectorCompose(fun_array) return b
def _loadFromFile(self, filename): """ Load in a strategy BDD from a file produced by a synthesizer, such as JTLV or Slugs. """ # Clear any existing states self.states.clearStates() a = pycudd.DdArray(1) # Load in the actual BDD itself # Note: We are using an ADD loader because the BDD loader # would expect us to have a reduced BDD with only one leaf node self.mgr.AddArrayLoad(pycudd.DDDMP_ROOT_MATCHLIST, None, pycudd.DDDMP_VAR_MATCHIDS, None, None, None, pycudd.DDDMP_MODE_TEXT, filename, None, a) # Convert from a binary (0/1) ADD to a BDD self.strategy = self.mgr.addBddPattern(a[0]) # Load in meta-data with open(filename, 'r') as f: # Seek forward to the max goal ID notation line = "" while not line.startswith("# Num goals:"): line = f.readline() self.num_goals = int(line.split(":")[1]) # Seek forward to the start of the variable definition section while not line.startswith("# Variable names:"): line = f.readline() # Parse the variable definitions for line in f: m = re.match(r"^#\s*(?P<num>\d+)\s*:\s*(?P<name>\w+'?)", line) # We will stop parsing as soon as we encounter an invalid line # Note: This includes empty lines! if m is None: break varname = m.group("name") varnum = int(m.group("num")) #### TEMPORARY HACK: REMOVE ME AFTER OTHER COMPONENTS ARE UPDATED!!! # Rewrite proposition names to make the old bitvector system work # with the new one varname = re.sub(r"^bit(\d+)('?)$", r'region_b\1\2', varname) ################################################################# if varname == "strat_type": self.strat_type_var = self.mgr.IthVar(varnum) else: self.BDD_to_var_name[self.mgr.IthVar(varnum)] = varname self.var_name_to_BDD[varname] = self.mgr.IthVar(varnum) # TODO: check for consecutivity # Create a Domain for jx to help with conversion to/from bitvectors self.jx_domain = strategy.Domain("_jx", value_mapping=range(self.num_goals), endianness=strategy.Domain.B0_IS_LSB)
def expr_as_bdd(self, e): sys.stdout.flush() typ = e[0] if typ == VAR: name = e[1] if self.bdd_map.has_key(name): return self.bdd_map[name] # a pre-computed formula else: return mgr.IthVar(self.var_order[name]) elif typ == id: raise BddError("How to convert id?") elif typ == NOT: return ~(self.expr_as_bdd(e[1][0])) elif typ == AND: bdds = [self.expr_as_bdd(s) for s in e[1]] res = self.mgr.ReadOne() for bdd in bdds: res &= bdd return res elif typ == OR: bdds = [self.expr_as_bdd(s) for s in e[1]] res = self.mgr.ReadLogicZero() for bdd in bdds: res |= bdd return res elif typ == EXISTS: vs, es = e[1], e[2] bdd = self.expr_as_bdd(es) intarr = pycudd.IntArray(len(vs)) for (i, v) in enumerate(vs): intarr[i] = self.var_order[v] cube = self.mgr.IndicesToCube(intarr, len(vs)) print "%s: exists over %d vars..." % (cur_time(), len(vs)) sys.stdout.flush() return bdd.ExistAbstract(cube) elif typ == SUB: from_vs, to_vs, es = e[1], e[2], e[3] bdd = self.expr_as_bdd(es) assert len(from_vs) == len(to_vs) from_arr = pycudd.DdArray(len(from_vs)) for (i, v) in enumerate(from_vs): from_arr[i] = self.mgr.IthVar(self.var_order[v]) to_arr = pycudd.DdArray(len(to_vs)) for (i, v) in enumerate(to_vs): to_arr[i] = self.mgr.IthVar(self.var_order[v]) # XXX: does swap really works in our case??? return bdd.SwapVariables(from_arr, to_arr, len(from_vs)) elif typ == LET: name, snd = e[1] print "%s: bdd %s" % (cur_time(), name) bdd = self.expr_as_bdd(snd) if name == "R": # put just True if you want to debug #print "Enumerating the values..." #bdd.PrintMinterm() bdd.PrintDebug(len(self.var_order), 1) # takes ages on mid-sized bdds #print "%s: saving %s" % (cur_time(), name) #bdd.PrintMinterm() # this can be quite slow # rev_order = {} # for k, v in self.var_order.items(): # rev_order[v] = k # # if name == "R": # f = open('R.sat', 'w+') # else: # f = sys.stdout # # pycudd.set_iter_meth(0) # over the cubes # for cube in bdd: # f.write("(and ") # for i, val in enumerate(cube): # if val == 1: # f.write(rev_order[i] + " ") # elif val == 0: # f.write("!" + rev_order[i] + " ") # # f.write(")\n") # # if f != sys.stdout: # f.close() return (name, bdd) else: raise BddError("Unknown expr met: " + str(typ))
smv_vars = mk_smv_vars(used_vars) write_smv_template(used_vars, smv_vars) mgr = pycudd.DdManager() mgr.SetDefault() print "%s: parsing again + constructing BDDs..." % cur_time() bdder = Bdder(mgr, var_order) parser = Parser(bdder.let_to_bdd) parser.parse_forms(filename) print "%s: saving BDDs..." % cur_time() # TODO: plumbing code, extract into a separate function DDDMP_MODE_TEXT = ord('A') # undefined in pycudd DDDMP_VAR_MATCHNAMES = 3 # undefined in pycudd dds = pycudd.DdArray(1) dds[0] = bdder.bdd_map["R"] dd_names = pycudd.StringArray(1) dd_names[0] = "TRANS" var_names = pycudd.StringArray(len(used_vars)) dd_filename, _ = os.path.splitext(os.path.basename(filename)) for i, n in enumerate(used_vars): if smv_vars.has_key(n): var_names[i] = smv_vars[n] else: var_names[i] = None dds.ArrayStore(dd_filename, dd_names, var_names, None, DDDMP_MODE_TEXT, DDDMP_VAR_MATCHNAMES, dd_filename + ".ddd", None) print "%s: finished" % cur_time()
#!/usr/bin/python -i # This example shows how to use the BREL interface # ###################################### ### ### NOTE: THIS IS STILL IN BETA ### ###################################### import pycudd m = pycudd.DdManager() m.SetDefault() # Note how the DdArrays are created and initialised ips = pycudd.DdArray(2) ops = pycudd.DdArray(2) a = m.IthVar(0) b = m.IthVar(1) c = m.IthVar(2) d = m.IthVar(3) ips.Push(a) ips.Push(b) ops.Push(c) ops.Push(d) # # Create a relation -- this maps 00 -> 00, 11; 11 -> 01, 10; 01 -> --; 10 -> -- # rel = (~a & ~b & ((~c & ~d) | (c & d))) | (a & b & ((~c & d) | (c & ~d))) rel |= (~a & b)