예제 #1
0
파일: alg.py 프로젝트: ruricolist/dig
    def gen(self, deg, traces, inps):
        assert deg >= 1, deg
        assert isinstance(traces, DTraces) and traces, traces
        assert isinstance(inps, Inps), inps

        #first obtain enough traces
        initrs = [self.getInitTraces(loc, deg, traces, inps) for loc in traces]
        tasks = [(loc, rs) for loc, rs in zip(traces, initrs) if rs]

        #then solve/prove in parallel
        def wprocess(tasks, Q):
            rs = [(loc, self.infer(loc, template, uks, exprs, traces, inps))
                  for loc, (template, uks, exprs) in tasks]
            if Q is None:
                return rs
            else:
                Q.put(rs)

        wrs = Miscs.runMP('find eqts',
                          tasks,
                          wprocess,
                          chunksiz=1,
                          doMP=settings.doMP and len(tasks) >= 2)

        dinvs = DInvs()
        for loc, (eqts, newInps) in wrs:
            newInps = Gen.updateInps(newInps, inps)
            logger.debug("{}: got {} eqts, {} new inps".format(
                loc, len(eqts), len(newInps)))
            if eqts: logger.debug('\n'.join(map(str, eqts)))
            dinvs[loc] = Invs.mk(eqts)
        return dinvs
예제 #2
0
파일: alg.py 프로젝트: ruricolist/dig
    def guessCheck(self, loc, term, minV, maxV, ubMinV, ubMaxV, disproves):
        assert minV <= maxV, (minV, maxV, term)
        assert ubMinV < ubMaxV, (ubMinV, ubMaxV)
        #assert isinstance(traces, DTraces), traces
        assert isinstance(disproves, set), disproves

        if minV == maxV: return maxV
        elif maxV - minV == 1:
            if minV in disproves:
                return maxV
            inv = Inv(term <= minV)
            inv_ = DInvs.mk(loc, Invs.mk([inv]))
            _, dCexs, _ = self.prover.check(inv_, None, ubMinV, ubMaxV)

            if loc in dCexs:
                assert dCexs[loc]
                disproves.add(minV)
                return maxV
            else:
                return minV

        v = sage.all.ceil((maxV + minV) / 2.0)
        inv = Inv(term <= v)
        inv_ = DInvs.mk(loc, Invs.mk([inv]))
        _, dCexs, _ = self.prover.check(inv_, None, ubMinV, ubMaxV)

        if loc in dCexs:  #disproved
            assert dCexs[loc]
            cexs = Traces.extract(dCexs[loc],
                                  tuple(self.invdecls[loc]),
                                  useOne=False)
            minV = int(max(cexs.myeval(term)))
            disproves.add(v)
        else:
            maxV = v

        return self.guessCheck(
            loc,
            term,  #traces, inps,
            minV,
            maxV,
            ubMinV,
            ubMaxV,
            disproves)
예제 #3
0
파일: alg.py 프로젝트: ruricolist/dig
    def infer(self, loc, template, uks, exprs, dtraces, inps):
        assert isinstance(loc, str), loc
        assert sageutil.is_sage_expr(template), template
        assert isinstance(uks, list), uks
        assert isinstance(exprs, set) and exprs, exprs
        assert isinstance(dtraces, DTraces) and dtraces, dtraces
        assert isinstance(inps, Inps) and inps, inps

        vs = tuple(self.invdecls[loc])
        cache = set()
        eqts = set()  #results
        exprs = list(exprs)

        newInps = []
        curIter = 0
        while True:
            curIter += 1
            logger.debug("{}: iter {} infer using {} exprs".format(
                loc, curIter, len(exprs)))

            newEqts = Miscs.solveEqts(exprs, uks, template)
            unchecks = [eqt for eqt in newEqts if eqt not in cache]

            if not unchecks:
                logger.debug("{}: no new results -- break".format(loc))
                break

            logger.debug('{}: {} candidates:\n{}'.format(
                loc, len(newEqts), '\n'.join(map(str, newEqts))))

            logger.debug("{}: check {} unchecked ({} candidates)".format(
                loc, len(unchecks), len(newEqts)))

            dinvs = DInvs.mk(loc, Invs.mk(map(Inv, unchecks)))
            dInps, dCexs, dinvs = self.prover.checkRange(dinvs, inps=None)

            if dInps: newInps.append(dInps)
            _ = [eqts.add(inv) for inv in dinvs[loc] if not inv.isDisproved]
            _ = [
                cache.add(inv.inv) for inv in dinvs[loc]
                if inv.stat is not None
            ]

            if loc not in dCexs:
                logger.debug(
                    "{}: no disproved candidates -- break".format(loc))
                break

            cexs = Traces.extract(dCexs[loc], vs)
            exprs_ = cexs.instantiate(template, None)

            logger.debug("{}: {} new cex exprs".format(loc, len(exprs_)))
            exprs.extend(exprs_)

        return eqts, newInps
예제 #4
0
파일: alg.py 프로젝트: ruricolist/dig
    def naive(self, loc, term, minV, maxV, ubMinV, ubMaxV, disproves):
        assert minV <= maxV, (minV, maxV, term)
        assert ubMinV < ubMaxV, (ubMinV, ubMaxV)
        #assert isinstance(traces, DTraces), traces
        assert isinstance(disproves, set), disproves

        for v in range(minV - 1, maxV + 1):
            inv = Inv(term <= v)
            inv_ = DInvs.mk(loc, Invs.mk([inv]))
            _, dCexs, _ = self.prover.check(inv_, None, ubMinV, ubMaxV)
            if loc in dCexs:  #disproved
                assert dCexs[loc]
                cexs = Traces.extract(dCexs[loc],
                                      tuple(self.invdecls[loc]),
                                      useOne=False)
                minV = int(max(cexs.myeval(term)))
                disproves.add(v)
            else:
                return v
예제 #5
0
파일: alg.py 프로젝트: ruricolist/dig
    def gen(self, deg, traces, inps):
        assert deg >= 1, deg
        assert isinstance(traces, DTraces), traces
        assert isinstance(inps, Inps), inps

        assert isinstance(traces, DTraces) and traces, traces
        assert isinstance(inps, Inps), inps

        mymaxv = 10
        maxV = mymaxv
        minV = -1 * maxV

        #without these restrictions, klee takes a long time to run
        ubmaxV = maxV * 2
        ubminV = -1 * ubmaxV

        locs = traces.keys()
        vss = [[sage.all.var(k) for k in self.invdecls[loc]] for loc in locs]
        mydeg = 2
        if mydeg > 2:
            logger.warn("not Oct invs (deg {}). Might be slow".format(deg))
        termss = [Miscs.getTermsFixedCoefs(vs, mydeg) for vs in vss]
        logger.info(
            "{} locs: check upperbounds for {} terms (range {})".format(
                len(locs), sum(map(len, termss)), mymaxv))

        refs = {
            loc: {Inv(t <= maxV): t
                  for t in terms}
            for loc, terms in zip(locs, termss)
        }
        ieqs = DInvs((loc, Invs.mk(refs[loc].keys())) for loc in refs)
        myinps = None
        cInps, cTraces, ieqs = self.prover.check(ieqs, myinps, ubminV, ubmaxV)
        if cInps:
            newInps = Gen.updateInps(cInps, inps)
            _ = self.getTracesAndUpdate(newInps, traces)

        ieqs = ieqs.removeDisproved()
        tasks = [(loc, refs[loc][ieq]) for loc in ieqs for ieq in ieqs[loc]]

        logger.debug("{} locs: compute upperbounds for {} terms".format(
            len(locs), len(tasks)))

        def _f(loc, term):
            vs = traces[loc].myeval(term)
            try:
                mminV = int(max(minV, max(v for v in vs if v < maxV)))
            except ValueError:
                mminV = minV

            logger.debug(
                "{}: compute ub for '{}', start w/ min {}, maxV {})".format(
                    loc, term, mminV, maxV))

            disproves = set()
            boundV = self.guessCheck(
                loc,
                term,  #traces, inps, 
                mminV,
                maxV,
                ubminV,
                ubmaxV,
                disproves)
            if boundV not in disproves and boundV not in {maxV, minV}:
                inv = Inv(term <= boundV)
                logger.detail("got {}".format(inv))
                return inv
            else:
                return None

        def wprocess(tasks, Q):
            rs = [(loc, _f(loc, term)) for loc, term in tasks]
            if Q is None:
                return rs
            else:
                Q.put(rs)

        doMP = settings.doMP and len(tasks) >= 2
        wrs = Miscs.runMP('guesscheck', tasks, wprocess, chunksiz=1, doMP=doMP)
        rs = [(loc, inv) for loc, inv in wrs if inv]
        dinvs = DInvs()
        for loc, inv in rs:
            if loc not in dinvs: dinvs[loc] = Invs()
            dinvs[loc].add(inv)
        return dinvs