def espresso_tts(*tts): """Return a tuple of expressions optimized using Espresso.""" for f in tts: if not isinstance(f, TruthTable): raise ValueError("expected a TruthTable instance") support = frozenset.union(*[f.support for f in tts]) inputs = sorted(support) ninputs = len(inputs) noutputs = len(tts) cover = set() for i, point in enumerate(boolfunc.iter_points(inputs)): invec = [2 if point[v] else 1 for v in inputs] outvec = list() for f in tts: val = f.pcdata[i] if val == PC_ZERO: outvec.append(0) elif val == PC_ONE: outvec.append(1) elif val == PC_DC: outvec.append(2) else: raise ValueError("expected truth table entry in {0, 1, -}") cover.add((tuple(invec), tuple(outvec))) set_config(**CONFIG) cover = espresso(ninputs, noutputs, cover, intype=FTYPE|DTYPE|RTYPE) inputs = [exprvar(v.names, v.indices) for v in inputs] return _cover2exprs(inputs, noutputs, cover)
def items(): """Iterate through AND'ed items.""" for point in boolfunc.iter_points(inputs): # pylint: disable=C0103 ab = self.restrict(point).pcdata[0] cd = other.restrict(point).pcdata[0] # a & c, b | d yield ((ab & cd) & 2) | ((ab | cd) & 1)
def items(): """Iterate through XOR'ed items.""" for point in boolfunc.iter_points(inputs): # pylint: disable=C0103 ab = self.restrict(point).pcdata[0] cd = other.restrict(point).pcdata[0] # a & d | b & c, a & c | b & d a, b, c, d = ab >> 1, ab & 1, cd >> 1, cd & 1 yield ((a & d | b & c) << 1) | (a & c | b & d)
def items(): """Iterate through composed outputs.""" for point in boolfunc.iter_points(inputs): gpnt = {v: val for v, val in point.items() if v not in unmapped} gval = gfunc.restrict(gpnt) # mapped function must be completely specified assert isinstance(gval, TTConstant) fpnt = {v: val for v, val in point.items() if v in unmapped} fpnt[gvar] = int(gval) yield func.restrict(fpnt).pcdata[0]
def preprocess_cuts(cuts): """! """ ## optimised cuts dictionary with removed control wires cuts_opt = {} for node in sorted(cuts.keys()): # if node is not a input or output if not node.startswith("INPUT"): # nodes without a cut are not included in the optimised cuts if cuts[node] == 'n.a.': pass else: cuts_opt[node] = [] # for each single cut, which is not first trivial cut, or a cut of only x inputs (as this represents general functions like NAND, XNOR etc, and allows for way to many matches - these are found with structural shape hashing) for singleCut in cuts[node][1:]: #todo: make this value inputtable if len(singleCut.inputs) > 3: # find if cut contains a control wire, wireList = [] for wire in func.control_wires: wire = exprvar(wire) if wire in singleCut.inputs: wireList.append(wire) # if wire list is empty, no control wires are contained within cut, cut is written to optimised cuts as is if not wireList: cuts_opt[node].append([singleCut, {}]) # if wirelist is not empty, cut contains a control wire, several optimised cuts are written to optimised cuts dictionary else: counter = 0 for cofactor in singleCut.cofactors(sorted(wireList)): if str(cofactor) != "1" and str(cofactor) != "0": truthTable = list(boolfunc.iter_points(wireList)) permut = truthTable[counter] if [cofactor, permut] not in cuts_opt[node] and [cofactor, {}] not in cuts_opt[node]: cuts_opt[node].append([cofactor, permut]) counter = counter +1 # fixme: some cuts are still in twice after cofactoring - problem with pyeda expressions # cuts_opt = {nodeName : [[cut1 , {perm}], [cuts2, {perm2}]...]} return cuts_opt
def test_iter_points(): assert list(iter_points([a, b])) == [{ a: 0, b: 0 }, { a: 1, b: 0 }, { a: 0, b: 1 }, { a: 1, b: 1 }]
def espresso_tts(*tts): """Return a tuple of expressions optimized using Espresso. The variadic *tts* argument is a sequence of truth tables. For example:: >>> from pyeda.boolalg.bfarray import exprvars >>> from pyeda.boolalg.table import truthtable >>> X = exprvars('x', 4) >>> f1 = truthtable(X, "0000011111------") >>> f2 = truthtable(X, "0001111100------") >>> f1m, f2m = espresso_tts(f1, f2) >>> f1m.equivalent(X[3] | X[0] & X[2] | X[1] & X[2]) True >>> f2m.equivalent(X[2] | X[0] & X[1]) True """ for f in tts: if not isinstance(f, TruthTable): raise ValueError("expected a TruthTable instance") support = frozenset.union(*[f.support for f in tts]) inputs = sorted(support) ninputs = len(inputs) noutputs = len(tts) cover = set() for i, point in enumerate(boolfunc.iter_points(inputs)): invec = [2 if point[v] else 1 for v in inputs] outvec = list() for f in tts: val = f.pcdata[i] if val == PC_ZERO: outvec.append(0) elif val == PC_ONE: outvec.append(1) elif val == PC_DC: outvec.append(2) else: raise ValueError("expected truth table entry in {0, 1, -}") cover.add((tuple(invec), tuple(outvec))) set_config(**CONFIG) cover = espresso(ninputs, noutputs, cover, intype=FTYPE|DTYPE|RTYPE) inputs = [exprvar(v.names, v.indices) for v in inputs] return _cover2exprs(inputs, noutputs, cover)
def espresso_tts(*tts): """Return a tuple of expressions optimized using Espresso. The variadic *tts* argument is a sequence of truth tables. For example:: >>> from pyeda.boolalg.bfarray import exprvars >>> from pyeda.boolalg.table import truthtable >>> X = exprvars('x', 4) >>> f1 = truthtable(X, "0000011111------") >>> f2 = truthtable(X, "0001111100------") >>> f1m, f2m = espresso_tts(f1, f2) >>> f1m.equivalent(X[3] | X[0] & X[2] | X[1] & X[2]) True >>> f2m.equivalent(X[2] | X[0] & X[1]) True """ for f in tts: if not isinstance(f, TruthTable): raise ValueError("expected a TruthTable instance") support = frozenset.union(*[f.support for f in tts]) inputs = sorted(support) ninputs = len(inputs) noutputs = len(tts) cover = set() for i, point in enumerate(boolfunc.iter_points(inputs)): invec = [2 if point[v] else 1 for v in inputs] outvec = list() for f in tts: val = f.pcdata[i] if val == PC_ZERO: outvec.append(0) elif val == PC_ONE: outvec.append(1) elif val == PC_DC: outvec.append(2) else: raise ValueError("expected truth table entry in {0, 1, -}") cover.add((tuple(invec), tuple(outvec))) set_config(**CONFIG) cover = espresso(ninputs, noutputs, cover, intype=FTYPE | DTYPE | RTYPE) inputs = [exprvar(v.names, v.indices) for v in inputs] return _cover2exprs(inputs, noutputs, cover)
def expand(self, vs=None, conj=False): """Return the Shannon expansion with respect to a list of variables.""" vs = self._expect_vars(vs) if vs: outer, inner = (And, Or) if conj else (Or, And) terms = [inner(self.restrict(p), *boolfunc.point2term(p, conj)) for p in boolfunc.iter_points(vs)] if conj: terms = [term for term in terms if term is not One] else: terms = [term for term in terms if term is not Zero] return outer(*terms, simplify=False) else: return self
def calc_prep(cut, P, PVarList): """! Function calculates representative function for given cut Function converts truthtable outvector to smallest p-representative using permutation trees . runtime = O(|V|+|E|) reduced due to using only smallest path in search tree @param [in] cut as pyeda formula @param [in] P as DiGraph of permutation tree of size (len(cut.inputs)) @param [out] pRep as list containg the p-representative """ # create truthtable of cut T = expr2truthtable(cut) inputs = T.inputs # calculate the outvector of the truth table of cut outvec = list() for i, point in enumerate(boolfunc.iter_points(inputs)): #~ invec = [2 if point[v] else 1 for v in inputs] val = T.pcdata[i] if val == PC_ZERO: outvec.append(0) elif val == PC_ONE: outvec.append(1) elif val == PC_DC: outvec.append(2) # search permutation tree, to find smallest pRepresentative coefPerm = search_permut_tree(P, [nx.topological_sort(P)[0]], outvec) coefPerm = coefPerm.split("_")[1:] # find pRep from coefficent permutation and outvector of truth table pRep = [] for i in range(len(outvec)): pRep.append(outvec[int(coefPerm[i])]) for x in range(len(coefPerm)): coefPerm[x] = int(coefPerm[x]) permDict = PVarList["perm" + str(int(math.log(len(coefPerm))/math.log(2)))] permut = permDict[str(coefPerm)] return pRep, permut
def test_iter_points(): assert list(iter_points([a, b])) == [{a: 0, b: 0}, {a: 1, b: 0}, {a: 0, b: 1}, {a: 1, b: 1}]