def test(cls, axioms, ntests: int, merge_se: bool, typs_d: dict, lang_cls): assert isinstance(axioms, list) and axioms assert isinstance(ntests, int) and ntests > 0, ntests assert isinstance(typs_d, dict), typs_d iaxioms = [] test_funs = [] for i, axiom in enumerate(axioms): axioms_, test_funs_ = axiom.gen_test_funs(i, merge_se, typs_d, ntests, lang_cls) iaxioms.extend(axioms_) test_funs.extend(test_funs_) logger.info("{} instantiated candidates".format(len(iaxioms))) logger.detail("\n" + Term.str_of_terms(iaxioms)) logger.info("test against random inputs") code = lang_cls.mk_fun_main(test_funs) stats = lang_cls.myrun(code) #CM.pause() assert len(iaxioms) == len(stats) axioms = [axiom for axiom, stat in zip(iaxioms, stats) if stat] logger.info("{} candidate(s)".format(len(axioms))) if axioms: logger.debug("\n" + Term.str_of_terms(axioms)) return axioms
def gen_const_eqts(cls, terms): #axioms of the form x = fun(...,x) #don't consider x = fun(x,y,z) too_simple = lambda _, rhs: \ (isinstance(rhs, Fun) and all(isinstance(c, Arg) for c in rhs.children)) filters = [too_simple] ceqts = [] for rhs in terms: #don't consider axiom of the form ? = void_fun if rhs.outp_typ: lhs = Arg.mk(rhs.outp_typ) children = (lhs, rhs) if any(f(lhs,rhs) for f in filters): continue eqt = cls.eq(children) ceqts.append(eqt) logger.info("{} const eqts".format(len(ceqts))) if ceqts: logger.debug("\n" + Term.str_of_terms(ceqts)) #CM.pause() return ceqts
def gen_eqts(cls, terms, ignores:set, max_nfuns:int): """ Enumerate eqts of the form x = y[...] where x, y are terms """ assert all(isinstance(t, Term) for t in terms), terms assert isinstance(ignores, set), ignores assert isinstance(max_nfuns, int) and max_nfuns > 0, max_nfuns tfilters = cls.mk_term_filters(ignores, max_nfuns) cache = dict() my_gen_trees_all = lambda ts: cls.gen_trees_all(ts, tfilters, cache) eterms = my_gen_trees_all(terms) logger.info("{} enumerated terms".format(len(eterms))) logger.debug("\n" + Term.str_of_terms(eterms)) ceqts = cls.gen_const_eqts(eterms) teqts = cls.gen_term_eqts(terms, eterms, my_gen_trees_all) return ceqts + teqts
def gen_term_eqts(cls, terms, eterms, my_gen_trees_all): assert isinstance(terms, list) and terms assert isinstance(eterms, list) and eterms assert callable(my_gen_trees_all) #axioms of the form fun1(..) = fun2(..) incompat = lambda lhs, rhs: lhs.outp_typ != rhs.outp_typ same_sig = lambda lhs, rhs: lhs.same_sig(rhs) impure = lambda lhs, rhs: not rhs.is_pure and not rhs.is_pure filters = [incompat, same_sig, impure] teqts = [] scache = set() for i, lhs in enumerate(eterms): rhss = my_gen_trees_all(terms[:i] + terms[i+1:]) for rhs in rhss: children = (lhs, rhs) assert isinstance(lhs, Fun) assert isinstance(rhs, Fun) children_r = (rhs, lhs) if children in scache or children_r in scache: continue scache.add(children) if any(f(lhs,rhs) for f in filters): continue assert lhs != rhs eqt = cls.eq(children) teqts.append(eqt) logger.info("{} term eqts".format(len(teqts))) if teqts: logger.debug("\n" + Term.str_of_terms(teqts)) #CM.pause() return teqts
def search(self, seed: (float, int), ntests: int, max_nfuns: int, merge_se: bool, typs_d: dict, lang: str): assert isinstance(seed, (float, int)), seed assert isinstance(ntests, int) and ntests > 0, ntests assert isinstance(typs_d, dict), typs_d assert isinstance(lang, str), lang random.seed(seed) logger.info("seed: {}".format(seed)) lang_cls = Infer.clses[lang.lower()] axioms = self.terms logger.info("{} terms".format(len(axioms))) logger.detail("\n" + Term.str_of_terms(axioms)) logger.info("test for exceptions") test_funs = [] for i, axiom in enumerate(axioms): test_funs_ = axiom.gen_test_funs_soft(i, merge_se, typs_d, ntests, lang_cls) test_funs.append(test_funs_) code = lang_cls.mk_fun_main(test_funs) stats = lang_cls.myrun(code) ignores = set( [axiom for axiom, stat in zip(axioms, stats) if not stat]) logger.info("{}/{} ignores".format(len(ignores), len(axioms))) if ignores: logger.detail("\n" + Term.str_of_terms(ignores)) axioms = EqFun.gen_eqts(axioms, ignores, max_nfuns) assert axioms logger.info("{} eqt templates".format(len(axioms))) logger.detail("\n" + Term.str_of_terms(axioms)) part_siz = 50 axioms = list(set(axioms)) #shuffle axioms axioms_parts = [ axioms[i:i + part_siz] for i in range(0, len(axioms), part_siz) ] taxioms = [] for i, ps in enumerate(axioms_parts): logger.info("{}/{}. testing {} eqt templates".format( i + 1, len(axioms_parts), len(ps))) axioms_ = self.test(ps, ntests, merge_se, typs_d, lang_cls) taxioms.extend(axioms_) axioms = sorted(taxioms, key=lambda a: (len(a.funs), len(a.nodes))) if not axioms: return logger.info("{} candidates(s) total".format(len(axioms))) #some final simplifications #done after testings, which return likely candidates axioms = self.prune(axioms, pure_imply=True) logger.info("after 1st pruning {} candidate(s)".format(len(axioms))) if not axioms: return logger.detail("\n" + Term.str_of_terms(axioms)) axioms = self.prune(axioms, pure_imply=False) logger.info("after 2nd pruning, {} candidate(s)".format(len(axioms))) if not axioms: return logger.info("\n" + Term.str_of_terms(axioms))