def get_implementations_f_r(self, f, r): f1, f2 = f r1, r2 = r _, pack, _ = self._get_product() m1s = self.dp1.get_implementations_f_r(f1, r1) m2s = self.dp2.get_implementations_f_r(f2, r2) options = set() if do_extra_checks(): for m1 in m1s: self.M1.belongs(m1) try: for m2 in m2s: self.M2.belongs(m2) except NotBelongs as e: msg = ' Invalid result from dp2' raise_wrapped(NotBelongs, e, msg, dp2=self.dp2.repr_long()) for m1 in m1s: for m2 in m2s: m = pack(m1, m2) options.add(m) if do_extra_checks(): for _ in options: self.I.belongs(_) return options
def get_implementations_f_r(self, f, r): """ Returns a nonempty set of elements of self.M. Might raise NotFeasible() """ res = set() es = [] ms = None for j, dp in enumerate(self.dps): try: ms = dp.get_implementations_f_r(f, r) # print('%s: dp.get_implementations_f_r(f, r) = %s ' % (j, ms)) for m in ms: if do_extra_checks(): Mj = dp.get_imp_space() try: Mj.belongs(m) except NotBelongs: raise ValueError(dp) res.add(self.M.pack(j, m)) except NotFeasible as e: es.append(e) if not ms: # no one was feasible msg = 'None was feasible' msg += '\n\n' + '\n\n'.join(str(e) for e in es) raise_desc(NotFeasible, msg, f=f, r=r, self=self) if do_extra_checks(): for _ in res: self.M.belongs(_) return res
def __init__(self, R, value): if do_extra_checks(): R.belongs(value) Map.__init__(self, R, R) self.value = value self.R = R
def __init__(self, F, value): if do_extra_checks(): F.belongs(value) Map.__init__(self, F, F) self.value = value self.F = F
def solve_f_iterate(dp0, f1, R, S, trace): """ Returns the next iteration si \in UR Min ( h(f1, r20) \cup !r20 ) """ UR = UpperSets(R) if do_extra_checks(): UR.belongs(S) R2 = R[1] converged = set() # subset of solutions for which they converged nextit = set() # find the set of all r2s for ra in S.minimals: hr = dp0.solve_trace((f1, ra[1]), trace) for rb in hr.minimals: valid = R.leq(ra, rb) if valid: nextit.add(rb) feasible = R2.leq(rb[1], ra[1]) if feasible: converged.add(rb) nextit = R.Us(poset_minima(nextit, R.leq)) converged = R.Us(poset_minima(converged, R.leq)) return nextit, converged
def solve_r_iterate(dp0, r1, F, S, trace): LF = LowerSets(F) if do_extra_checks(): LF.belongs(S) F2 = F[1] converged = set() # subset of solutions for which they converged nextit = set() # find the set of all r2s for fa in S.maximals: hr = dp0.solve_r_trace((r1, fa[1]), trace) for fb in hr.maximals: # valid = R.leq(ra, rb) # ra <= rb valid = F.leq(fb, fa) # fb <= fa if valid: nextit.add(fb) feasible = F2.leq(fa[1], fb[1]) if feasible: converged.add(fb) nextit = F.Ls(poset_maxima(nextit, F.leq)) converged = F.Ls(poset_maxima(converged, F.leq)) return nextit, converged
def evaluate(self, i): if do_extra_checks(): self.I.belongs(i) f = i rs = self.solve(f) fs = LowerSet(set([f]), self.F) return fs, rs
def _unpack_m(self, m): if do_extra_checks(): self.M.belongs(m) from mcdp_dp.dp_series import get_product_compact _, _, unpack = get_product_compact(self.M0, self.F2, self.R2) m0, f2, r2 = unpack(m) return m0, f2, r2
def solve_trace(self, func, trace): if func in self._solve_cache: # trace.log('using cache for %s' % str(func)) return trace.result(self._solve_cache[func]) trace.values(type='series') with trace.child('dp1') as t: u1 = self.dp1.solve_trace(func, t) if do_extra_checks(): R1 = self.dp1.get_res_space() tr1 = UpperSets(R1) tr1.belongs(u1) mcdp_dev_warning('rewrite this keeping structure') mins = set([]) for u in u1.minimals: with trace.child('dp2') as t: v = self.dp2.solve_trace(u, t) mins.update(v.minimals) R = self.get_res_space() minimals = poset_minima(mins, R.leq) us = UpperSet(minimals, R) self._solve_cache[func] = us return trace.result(us)
def check_leq(self, a, b): if do_extra_checks(): self.belongs(a) self.belongs(b) if not self._leq(a, b): msg = '%s ≰ %s' % (a, b) raise NotLeq(msg)
def format(self, x): if do_extra_checks(): self.belongs(x) if x == self.top: return self.top.__repr__() else: # TODO: add parameter if x == int(x): return '%d' % int(x) else: if x == finfo.tiny: return 'tiny' if x == finfo.eps: return 'eps' if x == finfo.max: return 'max' # s = '%.5f' % x # s = '%.10f' % x s = '%f' % x # remove trailing 0s s = s.rstrip('0') return s
def __init__(self, P): self.P = P if do_extra_checks(): top = self.get_top() bot = self.get_bottom() self.belongs(top) self.belongs(bot) assert self.leq(bot, top) assert not self.leq(top, bot) # unless empty
def Us(self, elements): elements = list(elements) if do_extra_checks(): for e in elements: self.belongs(e) # XXX n^2 from mcdp_posets import check_minimal check_minimal(elements, poset=self) from mcdp_posets import UpperSet return UpperSet(elements, self)
def __init__(self, elements, S): N = Nat() if do_extra_checks(): for e, howmany in elements.items(): S.belongs(e) N.belongs(howmany) self._elements = frozendict2(elements) self._S = S
def get_implementations_f_r(self, f, r): # print('%s get_implementaion(%s, %s)' % (id(self), f, r)) f1 = f _, pack, _ = self._get_product() R2 = self.dp2.get_res_space() res = set() # First let's solve again for r1 r1s = self.dp1.solve(f) for r1 in r1s.minimals: m1s = self.dp1.get_implementations_f_r(f1, r1) if do_extra_checks(): try: for m1 in m1s: self.M1.belongs(m1) except NotBelongs as e: msg = 'Invalid result from dp1 (%s)' % type(self.dp1) raise_wrapped(DPInternalError, e, msg, M1=self.M1, m1=m1, dp1=self.dp1.repr_long()) assert m1s, (self.dp1, f1, r1) f2 = r1 r2s = self.dp2.solve(f2) for r2 in r2s.minimals: if not R2.leq(r2, r): continue m2s = self.dp2.get_implementations_f_r(f2, r2) for m1 in m1s: for m2 in m2s: m = pack(m1, m2) res.add(m) if not res: msg = 'The (f,r) pair was not feasible.' raise_desc(NotFeasible, msg, f=f, r=r, self=self) if do_extra_checks(): M = self.get_imp_space() for _ in res: M.belongs(_) assert res return res
def is_feasible(self, f, i, r): if do_extra_checks(): self.F.belongs(f) self.I.belongs(i) self.R.belongs(r) try: self.check_feasible(f, i, r) except NotFeasible: return False else: return True
def __call__(self, x): if do_extra_checks(): D = self.get_domain() try: D.belongs(x) except NotBelongs as e: msg = 'Point does not belong to domain.' raise_wrapped(NotBelongs, e, msg, map=self, x=x, domain=D) y = self._call(x) if do_extra_checks(): C = self.get_codomain() try: C.belongs(y) except NotBelongs as e: msg = 'Point does not belong to codomain.' raise_wrapped(NotBelongs, e, msg, map=self, y=y, codomain=C) return y
def eval_constant_lowersetfromcollection(op, context): x = eval_constant(op.value, context) v = x.value u = x.unit S = u.S maximals = poset_minima(v.elements, S.leq) value = LowerSet(maximals, S) unit = LowerSets(S) if do_extra_checks(): unit.belongs(value) vu = ValueWithUnits(value, unit) return vu
def check_feasible(self, f, m, r): if do_extra_checks(): self.F.belongs(f) self.M.belongs(m) self.R.belongs(r) lf, ur = self.evaluate(m) try: lf.belongs(f) ur.belongs(r) except NotBelongs: msg = 'check_feasible failed.' raise_desc(NotFeasible, msg, f=f, m=m, r=r, lf=lf, ur=ur)
def get_top(self): if isinstance(self.S, FiniteCollectionAsSpace): res = FiniteCollection(elements=self.S.elements, S=self.S) if do_extra_checks(): self.belongs(res) return res mcdp_dev_warning('Maybe should use a TooMuchComputation error.') msg = 'Cannot enumerate the elements of this space.' raise_desc(NotBounded, msg, space=self.S)
def solveU(self, ufunc): if do_extra_checks(): UF = UpperSets(self.get_fun_space()) UF.belongs(ufunc) res = set([]) for m in ufunc.minimals: u = self.solve(m) res.update(u.minimals) ressp = self.get_res_space() minima = poset_minima(res, ressp.leq) return ressp.Us(minima)
def solve_all(self, f1, trace): """ Returns an upperset in UR. You want to project it to R1 to use as the output. """ dp0 = self.dp1 R = dp0.get_res_space() R1 = R[0] UR = UpperSets(R) # we consider a set of iterates # we start from the bottom trace.log('Iterating in UR = %s' % UR.__str__()) s0 = R.Us(R.get_minimal_elements()) S = [KleeneIteration(s=s0, s_converged=R.Us(set()), r=upperset_project(s0, 0), r_converged=R1.Us(set()))] for i in range(1, 1000000): # XXX with trace.iteration(i) as t: si_prev = S[-1].s si_next, converged = solve_f_iterate(dp0, f1, R, si_prev, t) iteration = KleeneIteration(s=si_next, s_converged=converged, r=upperset_project(si_next, 0), r_converged=upperset_project(converged, 0)) S.append(iteration) t.log('R = %s' % UR.format(si_next)) if do_extra_checks(): try: UR.check_leq(si_prev, si_next) except NotLeq as e: msg = 'Loop iteration invariant not satisfied.' raise_wrapped(Exception, e, msg, si_prev=si_prev, si_next=si_next, dp=self.dp1) t.values(state=S[-1]) if UR.leq(si_next, si_prev): t.log('Breaking because converged (iteration %s) ' % i) #t.log(' solution is %s' % (UR.format(sip))) # todo: add reason why interrupted break trace.values(type='loop2', UR=UR, R=R, dp=self, iterations=S) res_all = S[-1].s res_r1 = upperset_project(res_all, 0) result = dict(res_all=res_all, res_r1=res_r1) return result
def solve_r_all(self, r1, trace): """ Returns an upperset in UR. You want to project it to R1 to use as the output. """ dp0 = self.dp1 F = dp0.get_fun_space() F1 = F[0] LF = LowerSets(F) # we consider a set of iterates # we start from the bottom trace.log('Iterating in LF = %s' % LF.__str__()) s0 = F.Ls(F.get_maximal_elements()) S = [KleeneIteration(s=s0, s_converged=F.Ls(set()), r=lowerset_project(s0, 0), r_converged=F1.Ls(set()))] for i in range(1, 1000000): # XXX with trace.iteration(i) as t: si_prev = S[-1].s si_next, converged = solve_r_iterate(dp0, r1, F, si_prev, t) iteration = KleeneIteration(s=si_next, s_converged=converged, r=lowerset_project(si_next, 0), r_converged=lowerset_project(converged, 0)) S.append(iteration) t.log('si_next = %s' % LF.format(si_next)) if do_extra_checks(): try: LF.check_leq(si_prev, si_next) except NotLeq as e: msg = 'Loop iteration invariant not satisfied.' raise_wrapped(Exception, e, msg, si_prev=si_prev, si_next=si_next, dp=self.dp1) t.values(state=S[-1]) if LF.leq(si_next, si_prev): t.log('Breaking because converged (iteration %s) ' % i) break trace.values(type='loop2r', LF=LF, F=F, dp=self, iterations=S) res_all = S[-1].s res_f1 = lowerset_project(res_all, 0) result = dict(res_all=res_all, res_f1=res_f1) return result
def __init__(self, universe, relations): check_isinstance(universe, set) FiniteCollectionAsSpace.__init__(self, universe) closure = transitive_closure(relations) # relations contains all closures, but not the cycles self.relations = frozenset(closure) self._find_top() self._find_bottom() if do_extra_checks(): for a, b in self.relations: assert a in universe assert b in universe
def leq(self, a, b): assert isinstance(a, tuple), (self, a) assert isinstance(b, tuple), (self, b) assert len(a) == len(self.subs), (self, a) assert len(b) == len(self.subs), (self, b) if do_extra_checks(): self.belongs(a) self.belongs(b) for sub, x, y in zip(self.subs, a, b): if not sub.leq(x, y): return False return True
def check_unfeasible(self, f, i, r): if do_extra_checks(): self.F.belongs(f) self.I.belongs(i) self.R.belongs(r) lf, ur = self.evaluate(i) try: lf.belongs(f) ur.belongs(r) except NotBelongs: pass else: msg = 'check_feasible failed.' raise_desc(NotFeasible, msg, f=f, i=i, r=r, lf=lf, ur=ur)
def __init__(self, elements, S): self.elements = frozenset(elements) self.S = S if do_extra_checks(): # XXX problems = [] for m in elements: try: self.S.belongs(m) except NotBelongs as e: problems.append(e) if problems: msg = "Cannot create finite collection:\n" msg += "\n".join(str(p) for p in problems) raise NotBelongs(msg)
def upperset_project_map(ur, f): """ Projects the upper set through the given map. """ check_isinstance(ur, UpperSet) check_isinstance(f, Map) from .types_universe import get_types_universe tu = get_types_universe() if do_extra_checks(): tu.check_equal(ur.P, f.get_domain()) Q = f.get_codomain() assert isinstance(Q, Poset) minimals = set() for m in ur.minimals: mi = f(m) minimals.add(mi) minimals = poset_minima(minimals, leq=Q.leq) return UpperSet(minimals, P=Q)
def check_leq(self, a, b): if do_extra_checks(): self.belongs(a) self.belongs(b) if a == b: return True if False: if a == self.bot: return True if b == self.top: return True if b == self.bot: raise NotLeq('b = my ⊥') if a == self.top: raise NotLeq('a = my ⊤') self.my_leq_(a, b)
def solve(self, f): if do_extra_checks(): F = self.get_fun_space() F.belongs(f) f1, f2 = f r1 = self.dp1.solve(f1) r2 = self.dp2.solve(f2) R = self.get_res_space() s = [] for m1, m2 in itertools.product(r1.minimals, r2.minimals): s.append((m1, m2)) res = R.Us(set(s)) return res