def mk_traces(self): # will be modified in preprocess tcs_all = Miscs.keys_to_str(self.tcs) tcs,_ = get_traces(tcs_all, ntcs=1,#using only 1 array ntcs_extra = 0) tcs_extra = tcs_all #refine on all tcs return tcs, tcs_extra
def preprocess(self, xinfo): """ Preprocess input data 1) transforms external functions to special arrays 1) change arr repr to value->index repr to speed up arr idx lookup 2) generate nodes """ if __debug__: assert is_dict(xinfo), xinfo evs = ExtFun.gen_extvars(xinfo=xinfo) #arrays only evs = [OrderedDict([(k,v) for k,v in ev.iteritems() if is_list(v)]) for ev in evs] evs = Miscs.keys_to_str(evs) if not is_empty(evs): #add to traces self.tcs = [merge_dict(evs + [tc]) for tc in self.tcs] self.tcs_extra = [merge_dict(evs + [tc]) for tc in self.tcs_extra] mytcs = [] for tc in self.tcs: #arrs reprent ext funs (already in new format) efs = ExtFun.gen_extfuns(tc=tc,xinfo=xinfo) #convert normal arr format to new format arrs = [(k, Miscs.getListIdxs(v)) for k,v in tc.items()] arrs = OrderedDict(arrs) d = merge_dict(efs + [arrs]) mytcs.append(d) self.tcs = mytcs self.trees = [Tree({'root':k, 'children': [None] * len(c.values()[0][0]), 'commute': ExtFun(k).is_commute()}) for k,c in self.tcs[0].items()] self.xinfo = xinfo
def compute_traces(aname, acontents, ainfo, tsinfo): vi = Miscs.travel(acontents) vals = Miscs.getVals(vi) idxs = Miscs.getIdxs(vi) aname = str(aname) newvars = [var(aname + '_' + list_str(idx, '_')) for idx in idxs] if aname not in tsinfo: tsinfo[aname] = newvars else: assert tsinfo[aname] == newvars dVals = dict(zip(newvars,vals)) #{A_0_0_1:'w'} for nv,idx in zip(newvars,idxs): if nv not in ainfo: idx_ = zip([var('{}{}'.format(aname,li)) for li in srange(len(idx))],idx) ainfo[nv]={'name':aname, 'idx_':idx_} return dVals
def a_solve(pivot, solve_for, tcs): """ pivot = 'A' solve_for_arr = 'B' 0: A_0 - 7*B_0 == 0 1: A_1 - 7*B_2 - 3 == 0 2: A_2 - 7*B_4 - 6 == 0 Hypothesizes B_coef = c0A_i0 + c1A_i1 + ... + cnA_in + c(n+1) B_i0 = c0A_i0 + c1A_i1 + ... + cnA_in + c(n+1) B_i1 = c0A_i0 + c1A_i1 + ... + cnA_in + c(n+1) """ logger.debug("a_solve: Assume '%s' is pivot"%pivot) logger.debug("solve '%s' with respect to pivot with |tcs|=%d"%(solve_for,len(tcs))) _getIdxs = lambda a,d: [k for k in d[a] if not 'coef' in str(k)] mytcs = [dict(tc[pivot].items() + tc[solve_for].items()) for tc in tcs] idxs_ = _getIdxs(pivot,tcs[0]) pivot_idxs_n_const = [SR(1)] + idxs_ solve_for_keys= tcs[0][solve_for].keys() rs = [Miscs.solve_eqts_(ts=pivot_idxs_n_const,rv=k,ds=mytcs) for k in solve_for_keys] rs = Miscs.keys_to_str(rs) #so that the keys are string try: sol = merge_dict(rs) sol = (solve_for, sol) return sol except Exception: return None
def modify_arr_eqts(ps, ainfo): """ Shortcut to modify/format eqts """ ps_old = set(map(str,ps)) ps = [Miscs.elim_denom(p) for p in ps] #Eliminating denominators if exist ps = FlatArray.modify_signs(ps) if set(map(str,ps)) != ps_old: logger.warn('Some rels were modifed\n{}'.format(list_str(ps,'\n'))) return ps
def rfilter(self, tcs, do_parallel=True): if is_empty(self.ps) or is_empty(tcs): logger.debug('rfilter skips (|ps|={}, |tcs|={})'.format( len(self.ps), len(tcs))) return None logger.debug('rfilter(|ps|={}, |tcs|={})'.format( len(self.ps), len(tcs))) if not isinstance(self.ps[0], InvExp): from dig_miscs import Miscs tcs = Miscs.keys_to_str(tcs) def wprocess(tasks, Q): rs = [p for p in tasks if all(p.seval(tc) for tc in tcs)] if Q is None: #no multiprocessing return rs else: Q.put(rs) tasks = self.ps if do_parallel: from vu_common import get_workloads from multiprocessing import (Process, Queue, current_process, cpu_count) Q = Queue() workloads = get_workloads(tasks, max_nprocesses=cpu_count(), chunksiz=2) logger.debug("workloads 'refine' {}: {}".format( len(workloads), map(len, workloads))) workers = [ Process(target=wprocess, args=(wl, Q)) for wl in workloads ] for w in workers: w.start() wrs = [] for _ in workers: wrs.extend(Q.get()) else: wrs = wprocess(tasks, Q=None) self.ps = wrs Refine.print_diff('rfilter', len(tasks), len(self.ps))
def rfilter(self,tcs,do_parallel=True): if is_empty(self.ps) or is_empty(tcs): logger.debug('rfilter skips (|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) return None logger.debug('rfilter(|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) if not isinstance(self.ps[0],InvExp): from dig_miscs import Miscs tcs = Miscs.keys_to_str(tcs) def wprocess(tasks,Q): rs = [p for p in tasks if all(p.seval(tc) for tc in tcs)] if Q is None: #no multiprocessing return rs else: Q.put(rs) tasks = self.ps if do_parallel: from vu_common import get_workloads from multiprocessing import (Process, Queue, current_process, cpu_count) Q=Queue() workloads = get_workloads(tasks, max_nprocesses=cpu_count(), chunksiz=2) logger.debug("workloads 'refine' {}: {}" .format(len(workloads),map(len,workloads))) workers = [Process(target=wprocess,args=(wl,Q)) for wl in workloads] for w in workers: w.start() wrs = [] for _ in workers: wrs.extend(Q.get()) else: wrs = wprocess(tasks,Q=None) self.ps = wrs Refine.print_diff('rfilter', len(tasks), len(self.ps))
def solve(self): # mpp fixed ts = [t for t in self.terms if t != 1] tcs = Miscs.keys_to_str(self.tcs) if self.subset_siz is None: subset_siz = len(ts) else: subset_siz = self.subset_siz blacklist = [] if self.xinfo['Input']: blacklist = self.xinfo['Input'] if (self.xinfo['Output'] and len(self.xinfo['Output']) > len(self.xinfo['Input'])): blacklist = self.xinfo['Output'] ts_common = gen_terms_fixed_coefs(ts, subset_siz=subset_siz, blacklist=blacklist, is_mpp=True) if self.mpp_opt == IeqMPP.opt_max_then_min: def wprocess(is_max_plus, Q): Q.put(IeqMPPFixed.build_poly(ts_common, tcs, is_max_plus)) Q = mp.Queue() workers = [ mp.Process(target=wprocess, args=(is_max_plus, Q)) for is_max_plus in [True, False] ] for w in workers: w.start() rs = [] for _ in workers: rs.extend(Q.get()) else: is_max_plus = self.mpp_opt == IeqMPP.opt_max_plus rs = IeqMPPFixed.build_poly(ts_common, tcs, is_max_plus) self.sols = map(InvMPP, rs)
def solve(self): #mpp fixed ts = [t for t in self.terms if t != 1] tcs = Miscs.keys_to_str(self.tcs) if self.subset_siz is None: subset_siz = len(ts) else: subset_siz = self.subset_siz blacklist = None if self.xinfo['Input']: blacklist = self.xinfo['Input'] if (self.xinfo['Output'] and len(self.xinfo['Output']) > len(self.xinfo['Input'])): blacklist = self.xinfo['Output'] ts_common = gen_terms_fixed_coefs(ts,subset_siz=subset_siz, blacklist=blacklist, is_mpp=True) if self.mpp_opt == IeqMPP.opt_max_then_min: def worker(Q,is_max_plus): Q.put(IeqMPPFixed.build_poly(ts_common,tcs,is_max_plus)) Q = mp.Queue() workers = [mp.Process(target=worker,args=(Q,is_max_plus)) for is_max_plus in [True,False]] for w in workers: w.start() rs = [] for _ in workers: rs.extend(Q.get()) else: is_max_plus = self.mpp_opt == IeqMPP.opt_max_plus rs = IeqMPPFixed.build_poly(ts_common, tcs, is_max_plus) self.sols = map(InvMPP, rs)
def eval_lambda(f, idx_info, tc): """ Evaluate array expression p, e.g. p: A[i,j,k]=B[2i+3j+k] if idx_info is specified then only test p on the idxs from idx_info Assumes: the first array in lambda is the pivot lambda A,B,i,j,k: ... => i,j,k belong to A inv = 'lambda B,C,D,i,j: B[i][j]=C[D[2i+3]]' returns true if inv is true on tc Examples: sage: var('a,b,c,i,j') (a, b, c, i, j) sage: InvArray.eval_lambda('lambda a,b,c,i,j: a[i][j]==2*b[i]+c[j]', None, {'a':[[4,-5],[20,11]],'b':[1,9],'c':[2,-7]}) True sage: InvArray.eval_lambda('lambda c,a,b,xor,i: c[i] == xor(a[i],b[i])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 334, 79, 281]}) False sage: InvArray.eval_lambda('lambda c,a,b,xor,i1: c[i1] == xor(a[i1],b[i1])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 134, 79, 241]}) True sage: InvArray.eval_lambda('lambda rvu, t, rvu1, rvu0: (rvu[rvu0][rvu1]) + (-t[4*rvu0 + rvu1]) == 0', None, {'t': [28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], 'rvu': [[28, 131, 11, 85], [133, 46, 179, 20], [227, 148, 225, 197], [38, 221, 221, 126]]}) True #The following illustrate the use of idxVals, #i.e. p is only true under certain array rages sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', None, tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]}) False sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', idx_info = [{'st0': 0, 'st1': 0}, {'st0': 0, 'st1': 1}, {'st0': 2, 'st1': 2}, {'st0': 2, 'st1': 3}, {'st0': 3, 'st1': 0}, {'st0': 3, 'st1': 1}, {'st0': 3, 'st1': 2}, {'st0': 3, 'st1': 3}, {'st0': 0, 'st1': 2}, {'st0': 0, 'st1': 3}, {'st0': 1, 'st1': 0}, {'st0': 1, 'st1': 1}, {'st0': 1, 'st1': 2}, {'st0': 1, 'st1': 3}, {'st0': 2, 'st1': 0}, {'st0': 2, 'st1': 1}], tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]}) True """ """ Note: sage_eval vs eval sage_eval works on str of the format 'lambda x,y: 2*x+y' whereas eval works on str of the format 2*x+y directly (no lambda) Also, the result of sage_eval can apply on dicts whose keys are str e.g. f(**{'x':2,'y':3}) whereas the result of eval applies on dict whose keys are variables e.g. f(**{x:2,y:3}) """ if __debug__: assert is_str(f) and 'lambda' in f, f assert (idx_info is None or is_list(idx_info) and all(is_dict(v) for v in idx_info)), indx_info assert is_dict(tc), tc assert all(is_str(k) for k in tc), tc.keys() f = sage_eval(f) vs = f.func_code.co_varnames arrs = [v for v in vs if v in tc] #A,B extfuns = [v for v in vs if v in ExtFun.efdict] idxStr = [v for v in vs if v not in arrs + extfuns] #i,j,k d_tc = dict([(v, tc[v]) for v in arrs]) d_extfun = dict([(v, ExtFun(v).get_fun()) for v in extfuns]) d_ = merge_dict([d_tc, d_extfun]) if idx_info is None: #obtain idxsVals from the pivot array pivotContents = tc[arrs[0]] idxVals = [idx for idx, _ in Miscs.travel(pivotContents)] idx_info = [dict(zip(idxStr, idxV)) for idxV in idxVals] ds = [merge_dict([d_, idx_info_]) for idx_info_ in idx_info] try: return all(f(**d) for d in ds) except IndexError: return False except TypeError: return False except NameError as msg: logger.warn(msg) return False
def eval_lambda(f, idx_info, tc): """ Evaluate array expression p, e.g. p: A[i,j,k]=B[2i+3j+k] if idx_info is specified then only test p on the idxs from idx_info Assumes: the first array in lambda is the pivot lambda A,B,i,j,k: ... => i,j,k belong to A inv = 'lambda B,C,D,i,j: B[i][j]=C[D[2i+3]]' returns true if inv is true on tc Examples: sage: var('a,b,c,i,j') (a, b, c, i, j) sage: InvArray.eval_lambda('lambda a,b,c,i,j: a[i][j]==2*b[i]+c[j]', None, {'a':[[4,-5],[20,11]],'b':[1,9],'c':[2,-7]}) True sage: InvArray.eval_lambda('lambda c,a,b,xor,i: c[i] == xor(a[i],b[i])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 334, 79, 281]}) False sage: InvArray.eval_lambda('lambda c,a,b,xor,i1: c[i1] == xor(a[i1],b[i1])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 134, 79, 241]}) True sage: InvArray.eval_lambda('lambda rvu, t, rvu1, rvu0: (rvu[rvu0][rvu1]) + (-t[4*rvu0 + rvu1]) == 0', None, {'t': [28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], 'rvu': [[28, 131, 11, 85], [133, 46, 179, 20], [227, 148, 225, 197], [38, 221, 221, 126]]}) True #The following illustrate the use of idxVals, #i.e. p is only true under certain array rages sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', None, tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]}) False sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', idx_info = [{'st0': 0, 'st1': 0}, {'st0': 0, 'st1': 1}, {'st0': 2, 'st1': 2}, {'st0': 2, 'st1': 3}, {'st0': 3, 'st1': 0}, {'st0': 3, 'st1': 1}, {'st0': 3, 'st1': 2}, {'st0': 3, 'st1': 3}, {'st0': 0, 'st1': 2}, {'st0': 0, 'st1': 3}, {'st0': 1, 'st1': 0}, {'st0': 1, 'st1': 1}, {'st0': 1, 'st1': 2}, {'st0': 1, 'st1': 3}, {'st0': 2, 'st1': 0}, {'st0': 2, 'st1': 1}], tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]}) True """ """ Note: sage_eval vs eval sage_eval works on str of the format 'lambda x,y: 2*x+y' whereas eval works on str of the format 2*x+y directly (no lambda) Also, the result of sage_eval can apply on dicts whose keys are str e.g. f(**{'x':2,'y':3}) whereas the result of eval applies on dict whose keys are variables e.g. f(**{x:2,y:3}) """ if __debug__: assert is_str(f) and 'lambda' in f, f assert (idx_info is None or is_list(idx_info) and all(is_dict(v) for v in idx_info)), indx_info assert is_dict(tc), tc assert all(is_str(k) for k in tc), tc.keys() f = sage_eval(f) vs = f.func_code.co_varnames arrs = [v for v in vs if v in tc] #A,B extfuns = [v for v in vs if v in ExtFun.efdict] idxStr = [v for v in vs if v not in arrs+extfuns] #i,j,k d_tc = dict([(v,tc[v]) for v in arrs]) d_extfun= dict([(v,ExtFun(v).get_fun()) for v in extfuns]) d_ = merge_dict([d_tc,d_extfun]) if idx_info is None: #obtain idxsVals from the pivot array pivotContents = tc[arrs[0]] idxVals = [idx for idx,_ in Miscs.travel(pivotContents)] idx_info = [dict(zip(idxStr,idxV)) for idxV in idxVals] ds = [merge_dict([d_, idx_info_]) for idx_info_ in idx_info] try: return all(f(**d) for d in ds) except IndexError: return False except TypeError: return False except NameError as msg: logger.warn(msg) return False
def extractIdxInfo(pivot,psInfo): ps = [p[pivot] for p in psInfo] ps = Miscs.keys_to_str([p for p in ps]) ps = [dict([(k,c) for k,c in p.iteritems() if k != 'coef']) for p in ps] return ps
def rfilter_old(self, tcs): """ Returns the subset of ps that satisfies all testcases tcs Examples: sage: logger.set_level(VLog.DEBUG) sage: var('y z') (y, z) sage: rf = Refine(map(InvIeq,[x^2 >= 0 , x-y >= 7]));rf.rfilter([{x:1,y:0}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=2, |tcs|=1) refine:Debug:rfilter (before 2, after 1, diff 1) [x^2 >= 0] sage: rf = Refine(map(InvIeq,[2*x -y >= 0])); rf.rfilter([{y: 14, x: 7}, {y: 13, x: 7}, {y: 6, x: 4}, {y: 1, x: 1}, {y: 2, x: 1}, {y: 5, x: 100}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=1, |tcs|=6) [2*x - y >= 0] sage: rf = Refine(map(InvIeq,[2*x -y >= 0])); rf.rfilter([{y: 14, x: 7}, {y: 13, x: 7}, {y: 6, x: 4}, {y: 1, x: 1}, {y: 2, x: 1}, {y: 25, x: 9}, {y:25 , x*y: 15, x: 9}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=1, |tcs|=7) refine:Debug:rfilter (before 1, after 0, diff 1) [] ** This is by design sage: rf = Refine(map(InvIeq,[x^3 >= 0 , x-y >= 7])); rf.rfilter([{z:1}]) refine:Debug:rfilter(|ps|=2, |tcs|=1) refine:Debug:rfilter (before 2, after 0, diff 2) sage: assert(rf.ps == []) sage: rf = Refine(map(InvMPP,[('lambda x: x>=10',''), ('lambda x,y: max(x,y)>12',''), ('lambda x: x>=10','')])); rf.rfilter([{x:20,y:0},{x:9,y:13}]); sorted(rf.ps,key=str) refine:Debug:vset (before 3, after 2, diff 1) refine:Debug:rfilter(|ps|=2, |tcs|=2) refine:Debug:rfilter (before 2, after 1, diff 1) ['lambda x,y: max(x,y)>12'] sage: rf = Refine(map(InvMPP,[('lambda x: x>=10', ''), ('lambda x,y: max(x,y)>12','')])); rf.rfilter([{x:20,y:0}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=2, |tcs|=1) ['lambda x: x>=10', 'lambda x,y: max(x,y)>12'] sage: rf = Refine(map(InvMPP,[('lambda x: x>=10',''), ('lambda x,y: max(x,y)>12','')])); rf.rfilter([]); sorted(rf.ps,key=str) refine:Debug:rfilter skips (|ps|=2, |tcs|=0) ['lambda x: x>=10', 'lambda x,y: max(x,y)>12'] """ if is_empty(self.ps) or is_empty(tcs): logger.debug('rfilter skips (|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) return logger.debug('rfilter(|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) if not isinstance(self.ps[0],InvExp): from dig_miscs import Miscs tcs = Miscs.keys_to_str(tcs) old_len = len(self.ps) self.ps = [p for p in self.ps if all(p.seval(tc) for tc in tcs)] Refine.print_diff('rfilter', old_len, len(self.ps))
def solve(self): #eqt sols = Miscs.solve_eqts(ts=self.terms, rv=0, ds=self.tcs) self.sols = map(InvEqt, sols)
def rfilter_old(self, tcs): """ Returns the subset of ps that satisfies all testcases tcs Examples: sage: logger.set_level(VLog.DEBUG) sage: var('y z') (y, z) sage: rf = Refine(map(InvIeq,[x^2 >= 0 , x-y >= 7]));rf.rfilter([{x:1,y:0}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=2, |tcs|=1) refine:Debug:rfilter (before 2, after 1, diff 1) [x^2 >= 0] sage: rf = Refine(map(InvIeq,[2*x -y >= 0])); rf.rfilter([{y: 14, x: 7}, {y: 13, x: 7}, {y: 6, x: 4}, {y: 1, x: 1}, {y: 2, x: 1}, {y: 5, x: 100}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=1, |tcs|=6) [2*x - y >= 0] sage: rf = Refine(map(InvIeq,[2*x -y >= 0])); rf.rfilter([{y: 14, x: 7}, {y: 13, x: 7}, {y: 6, x: 4}, {y: 1, x: 1}, {y: 2, x: 1}, {y: 25, x: 9}, {y:25 , x*y: 15, x: 9}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=1, |tcs|=7) refine:Debug:rfilter (before 1, after 0, diff 1) [] ** This is by design sage: rf = Refine(map(InvIeq,[x^3 >= 0 , x-y >= 7])); rf.rfilter([{z:1}]) refine:Debug:rfilter(|ps|=2, |tcs|=1) refine:Debug:rfilter (before 2, after 0, diff 2) sage: assert(rf.ps == []) sage: rf = Refine(map(InvMPP,[('lambda x: x>=10',''), ('lambda x,y: max(x,y)>12',''), ('lambda x: x>=10','')])); rf.rfilter([{x:20,y:0},{x:9,y:13}]); sorted(rf.ps,key=str) refine:Debug:vset (before 3, after 2, diff 1) refine:Debug:rfilter(|ps|=2, |tcs|=2) refine:Debug:rfilter (before 2, after 1, diff 1) ['lambda x,y: max(x,y)>12'] sage: rf = Refine(map(InvMPP,[('lambda x: x>=10', ''), ('lambda x,y: max(x,y)>12','')])); rf.rfilter([{x:20,y:0}]); sorted(rf.ps,key=str) refine:Debug:rfilter(|ps|=2, |tcs|=1) ['lambda x: x>=10', 'lambda x,y: max(x,y)>12'] sage: rf = Refine(map(InvMPP,[('lambda x: x>=10',''), ('lambda x,y: max(x,y)>12','')])); rf.rfilter([]); sorted(rf.ps,key=str) refine:Debug:rfilter skips (|ps|=2, |tcs|=0) ['lambda x: x>=10', 'lambda x,y: max(x,y)>12'] """ if is_empty(self.ps) or is_empty(tcs): logger.debug('rfilter skips (|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) return None logger.debug('rfilter(|ps|={}, |tcs|={})' .format(len(self.ps), len(tcs))) if not isinstance(self.ps[0],InvExp): from dig_miscs import Miscs tcs = Miscs.keys_to_str(tcs) old_len = len(self.ps) self.ps = [p for p in self.ps if all(p.seval(tc) for tc in tcs)] Refine.print_diff('rfilter', old_len, len(self.ps))