def show_used_relations(self, clauses, both=False):
     self.current_concept_graph.clear_edges()
     rels = self.current_concept_graph.g.relations
     used = set(
         il.normalize_symbol(s)
         for s in lu.used_constants(clauses.to_formula()))
     for rel in rels:
         fmla = rel.formula
         if any(c in used and not c.name.startswith('@')
                for c in lu.used_constants(fmla)):
             self.current_concept_graph.show_relation(rel,
                                                      '+',
                                                      update=False)
             if both and not il.is_enumerated(fmla):
                 self.current_concept_graph.show_relation(rel,
                                                          '-',
                                                          update=False)
     need_update_relations = False
     for app in ilu.apps_clauses(clauses):
         if len(app.args) == 3 and il.is_numeral(app.args[0]):
             fmla = app.rep(app.args[0], il.Variable('X', app.args[1].sort),
                            il.Variable('Y', app.args[2].sort))
             concept = self.current_concept_graph.g.formula_to_concept(fmla)
             self.current_concept_graph.g.new_relation(concept)
             need_update_relations = True
             self.current_concept_graph.show_relation(concept,
                                                      '+',
                                                      update=False)
             if both:
                 self.current_concept_graph.show_relation(concept,
                                                          '-',
                                                          update=False)
     if need_update_relations:
         self.current_concept_graph.update_relations()
     self.current_concept_graph.update()
Beispiel #2
0
def sort_size_constraint(sort,size):
    if isinstance(sort,ivy_logic.UninterpretedSort):
        syms = [ivy_logic.Symbol('__'+sort.name+'$'+str(i),sort) for i in range(size)]
        v = ivy_logic.Variable('X'+sort.name,sort)
        res =  ivy_logic.Or(*[ivy_logic.Equals(v,s) for s in syms])
#        print "sort_size_constraint : {}".format(res)
        return res
    return ivy_logic.And()
Beispiel #3
0
def compile_native_symbol(arg):
    name = arg.rep
    if name in ivy_logic.sig.symbols:
        sym = ivy_logic.sig.symbols[name]
        if not isinstance(sym, ivy_logic.UnionSort):
            return sym
    if name in ivy_logic.sig.sorts:
        return ivy_logic.Variable('X', ivy_logic.sig.sorts[name])
    if ivy_logic.is_numeral_name(name):
        return ivy_logic.Symbol(name, ivy_logic.TopS)
    raise iu.IvyError(arg, '{} is not a declared symbol or type'.format(name))
Beispiel #4
0
def model_universe_facts(h,sort,upclose):
    if ivy_logic.is_interpreted_sort(sort):
        return []
    # get universe elements
    elems = h.sort_universe(sort)
    # constraint defining universe
    uc = []
    if not upclose:
        uc = [[ivy_logic._eq_lit(ivy_logic.Variable('X',c.sort),c) for c in elems]]
    # universe elements are distinct
    dc = [[ivy_logic._neq_lit(c1,c2)]
          for (c1,c2) in iu.distinct_unordered_pairs(elems)]
    return uc+dc
Beispiel #5
0
    def sorted_sort_universe(self, sort):
        elems = self.constants[sort]
        #        print "elems: {}".format(map(str,elems))
        vs = [ivy_logic.Variable(s, sort) for s in ["X", "Y"]]
        order = ivy_logic.Symbol("<", ivy_logic.RelationSort([sort, sort]))
        order_atom = atom_to_z3(order(*vs))
        z3_vs = map(term_to_z3, vs)
        #        print "order_atom: {}".format(order_atom)
        try:
            fun = z3.Function
            self.model[order.to_z3()]
            #            print "sorting..."
            elems = sorted(elems, SortOrder(z3_vs, order_atom, self.model))
        except IndexError:
            pass
#        print "elems: {}".format(map(str,elems))
        return map(constant_from_z3, elems)
Beispiel #6
0
def apply_match(match,fmla):
    """ apply a match to a formula. 

    In effect, substitute all symbols in the match with the
    corresponding lambda terms and apply beta reduction
    """

    args = [apply_match(match,f) for f in fmla.args]
    if il.is_app(fmla):
        if fmla.rep in match:
            func = match[fmla.rep]
            return func(*args)
    elif il.is_binder(fmla):
        vs = [apply_match(match,v) for v in fmla.variables]
        return fmla.clone_binder(vs,apply_match(match,fmla.body))
    elif il.is_variable(fmla):
        return il.Variable(fmla.name,match.get(fmla.sort,fmla.sort))
    return fmla.clone(args)
Beispiel #7
0
def apply_match_alt(match, fmla):
    """ apply a match to a formula. 

    In effect, substitute all symbols in the match with the
    corresponding lambda terms and apply beta reduction
    """

    args = [apply_match_alt(match, f) for f in fmla.args]
    if il.is_app(fmla):
        func = apply_match_func(match, fmla.rep)
        if func in match:
            func = match[func]
            return func(*args)
        return func(*args)
    if il.is_variable(fmla):
        fmla = il.Variable(fmla.name, match.get(fmla.sort, fmla.sort))
        fmla = match.get(fmla, fmla)
        return fmla
    return fmla.clone(args)
Beispiel #8
0
def apply_match_alt_rec(match,fmla,env):
    args = [apply_match_alt_rec(match,f,env) for f in fmla.args]
    if il.is_app(fmla):
        if fmla.rep in match:
            return apply_fun(match_get(match,fmla.rep,env),args)
        func = apply_match_func(match,fmla.rep)
        func = match_get(match,func,env,func)
        return func(*args)
    if il.is_variable(fmla):
        if fmla in match:
            return match_get(match,fmla,env)
        fmla = il.Variable(fmla.name,apply_match_sort(match,fmla.sort))
        fmla = match_get(match,fmla,env,fmla)
        return fmla
    if il.is_binder(fmla):
        with il.BindSymbols(env,fmla.variables):
            fmla = fmla.clone_binder([apply_match_alt_rec(match,v,env) for v in fmla.variables],args[0])
        return fmla
    return fmla.clone(args)
Beispiel #9
0
def parameterize_schema(sorts,schema):
    """ Add initial parameters to all the free symbols in a schema.

    Takes a list of sorts and an ia.SchemaBody. """

    vars = make_distinct_vars(sorts,goal_conc(schema))
    match = {}
    prems = []
    for prem in goal_prems(schema):
        if isinstance(prem,ia.ConstantDecl):
            sym = prem.args[0]
            vs2 = [il.Variable('X'+str(i),y) for i,y in enumerate(sym.sort.dom)]
            sym2 = sym.resort(il.FuncConstSort(*(sorts + list(sym.sort.dom) + [sym.sort.rng])))
            match[sym] = il.Lambda(vs2,sym2(*(vars+vs2)))
            prems.append(ia.ConstantDecl(sym2))
        else:
            prems.append(prem)
    conc = apply_match(match,goal_conc(schema))
    return clone_goal(schema,prems,conc)
Beispiel #10
0
def make_distinct_vars(sorts, *asts):
    vars = [il.Variable('V' + str(i), sort) for i, sort in enumerate(sorts)]
    return lu.rename_variables_distinct_asts(vars, asts)
Beispiel #11
0
def apply_match_sym(match, sym):
    if il.is_variable(sym):
        return il.Variable(sym.name, match.get(sym.sort, sym.sort))
    return match.get(sym, sym) if isinstance(
        sym, il.UninterpretedSort) else apply_match_func(match, sym)
Beispiel #12
0
                CallAction(*([ivy_ast.Atom(self.rep, args)] + ress)))
            return ivy_ast.Tuple(*ress)
        sort = find_sort(returns[0].sort)
        res = ivy_logic.Symbol('loc:' + str(len(expr_context.local_syms)),
                               sort)
        expr_context.local_syms.append(res)
        expr_context.code.append(CallAction(ivy_ast.Atom(self.rep, args), res))
        return res()
    return (ivy_logic.Equals if self.rep == '=' else
            ivy_logic.find_polymorphic_symbol(self.rep))(*args)


ivy_ast.App.cmpl = ivy_ast.Atom.cmpl = compile_app

ivy_ast.Variable.cmpl = lambda self: ivy_logic.Variable(
    self.rep,
    ivy_logic.find_sort(self.sort)
    if isinstance(self.sort, str) else self.sort)

ivy_ast.ConstantSort.cmpl = lambda self: ivy_logic.ConstantSort(self.rep)

ivy_ast.EnumeratedSort.cmpl = lambda self: ivy_logic.EnumeratedSort(
    self.name, self.extension)

SymbolList.cmpl = lambda self: self.clone(
    [find_symbol(s) for s in self.symbols])


def cquant(q):
    return ivy_logic.ForAll if isinstance(q,
                                          ivy_ast.Forall) else ivy_logic.Exists
Beispiel #13
0
def clauses_model_to_diagram(clauses1,
                             ignore=None,
                             implied=None,
                             model=None,
                             axioms=None,
                             weaken=True):
    """ Return a diagram of a model of clauses1 or None.  The function "ignore", if
    provided, returns true for symbols that should be ignored in the
    diagram.
    """
    print "clauses_model_to_diagram clauses1 = {}".format(clauses1)
    if axioms == None:
        axioms = true_clauses
    h = model_if_none(and_clauses(clauses1, axioms), implied, model)
    ignore = ignore if ignore != None else lambda x: False
    res = model_facts(h, (lambda x: False), clauses1,
                      upclose=True)  # why not pass axioms?
    print "clauses_model_to_diagram res = {}".format(res)
    # find representative elements
    # find representatives of universe elements
    reps = dict()
    for c in used_constants_clauses(clauses1):
        #        print "constant: {}".format(c)
        mc = get_model_constant(h.model, ivy_logic.Constant(c))
        #        print "value: {}".format(mc)
        if mc.rep not in reps or reps[
                mc.rep].rep.is_skolem() and not c.is_skolem():
            reps[mc.rep] = ivy_logic.Constant(c)
    for s in h.sorts():
        for e in h.sort_universe(s):
            if e.rep not in reps:
                reps[e.rep] = e.rep.skolem()()
    print "clauses_model_to_diagram reps = {}".format(reps)
    # filter out clauses using universe elements without reps
    #    res = [cls for cls in res if all(c in reps for c in used_constants_clause(cls))]
    # replace universe elements with their reps
    print "clauses_model_to_diagram res = {}".format(res)
    res = substitute_constants_clauses(res, reps)
    # filter defined skolems
    # this caused a bug in the leader example. the generated diagram did not satisfy clauses1
    res.fmlas = [
        f for f in res.fmlas
        if not any((x.is_skolem() and x in clauses1.defidx)
                   for x in used_symbols_ast(f))
    ]
    print "clauses_model_to_diagram res = {}".format(res)
    uc = Clauses([[
        ivy_logic._eq_lit(ivy_logic.Variable('X', c.get_sort()), reps[c.rep])
        for c in h.sort_universe(s)
    ] for s in h.sorts()])
    print "clauses_model_to_diagram uc = {}".format(uc)

    #    uc = true_clauses()
    if weaken:
        res = unsat_core(res, and_clauses(uc, axioms),
                         clauses1)  # implied not used here
    print "clauses_model_to_diagram res = {}".format(res)

    #    print "foo = {}".format(unsat_core(and_clauses(uc,axioms),true_clauses(),clauses1))

    # filter out non-rep skolems
    repset = set(c.rep for e, c in reps.iteritems())
    print "clauses_model_to_diagram repset = {}".format(repset)
    ign = lambda x, ignore=ignore: (ignore(x) and not x in repset)
    res = Clauses([
        cl for cl in res.fmlas
        if not any(ign(c) for c in used_symbols_ast(cl))
    ])
    print "clauses_model_to_diagram res = {}".format(res)
    return res
Beispiel #14
0
def loop_action(action, mod):
    subst = dict((p, ivy_logic.Variable('Y' + p.name, p.sort))
                 for p in action.formal_params)
    action = lu.substitute_constants_ast(action, subst)
    ia.type_check_action(action, mod)  # make sure all is legal
    return action
Beispiel #15
0
def to_aiger(mod,ext_act):

    erf = il.Symbol('err_flag',il.find_sort('bool'))
    errconds = []
    add_err_flag_mod(mod,erf,errconds)

    # we use a special state variable __init to indicate the initial state

    ext_acts = [mod.actions[x] for x in sorted(mod.public_actions)]
    ext_act = ia.EnvAction(*ext_acts)

    init_var = il.Symbol('__init',il.find_sort('bool')) 
    init = add_err_flag(ia.Sequence(*([a for n,a in mod.initializers]+[ia.AssignAction(init_var,il.And())])),erf,errconds)
    action = ia.Sequence(ia.AssignAction(erf,il.Or()),ia.IfAction(init_var,ext_act,init))
    
    # get the invariant to be proved, replacing free variables with
    # skolems. First, we apply any proof tactics.

    pc = ivy_proof.ProofChecker(mod.axioms,mod.definitions,mod.schemata)
    pmap = dict((lf.id,p) for lf,p in mod.proofs)
    conjs = []
    for lf in mod.labeled_conjs:
        if lf.id in pmap:
            proof = pmap[lf.id]
            subgoals = pc.admit_proposition(lf,proof)
            conjs.extend(subgoals)
        else:
            conjs.append(lf)

    invariant = il.And(*[il.drop_universals(lf.formula) for lf in conjs])
#    iu.dbg('invariant')
    skolemizer = lambda v: ilu.var_to_skolem('__',il.Variable(v.rep,v.sort))
    vs = ilu.used_variables_in_order_ast(invariant)
    sksubs = dict((v.rep,skolemizer(v)) for v in vs)
    invariant = ilu.substitute_ast(invariant,sksubs)
    invar_syms = ilu.used_symbols_ast(invariant)
    
    # compute the transition relation

    stvars,trans,error = action.update(mod,None)
    

#    print 'action : {}'.format(action)
#    print 'annotation: {}'.format(trans.annot)
    annot = trans.annot
#    match_annotation(action,annot,MatchHandler())
    
    indhyps = [il.close_formula(il.Implies(init_var,lf.formula)) for lf in mod.labeled_conjs]
#    trans = ilu.and_clauses(trans,indhyps)

    # save the original symbols for trace
    orig_syms = ilu.used_symbols_clauses(trans)
    orig_syms.update(ilu.used_symbols_ast(invariant))
                     
    # TODO: get the axioms (or maybe only the ground ones?)

    # axioms = mod.background_theory()

    # rn = dict((sym,tr.new(sym)) for sym in stvars)
    # next_axioms = ilu.rename_clauses(axioms,rn)
    # return ilu.and_clauses(axioms,next_axioms)

    funs = set()
    for df in trans.defs:
        funs.update(ilu.used_symbols_ast(df.args[1]))
    for fmla in trans.fmlas:
        funs.update(ilu.used_symbols_ast(fmla))
#   funs = ilu.used_symbols_clauses(trans)
    funs.update(ilu.used_symbols_ast(invariant))
    funs = set(sym for sym in funs if  il.is_function_sort(sym.sort))
    iu.dbg('[str(fun) for fun in funs]')

    # Propositionally abstract

    # step 1: get rid of definitions of non-finite symbols by turning
    # them into constraints

    new_defs = []
    new_fmlas = []
    for df in trans.defs:
        if len(df.args[0].args) == 0 and is_finite_sort(df.args[0].sort):
            new_defs.append(df)
        else:
            fmla = df.to_constraint()
            new_fmlas.append(fmla)
    trans = ilu.Clauses(new_fmlas+trans.fmlas,new_defs)

    # step 2: get rid of ite's over non-finite sorts, by introducing constraints

    cnsts = []
    new_defs = [elim_ite(df,cnsts) for df in trans.defs]
    new_fmlas = [elim_ite(fmla,cnsts) for fmla in trans.fmlas]
    trans = ilu.Clauses(new_fmlas+cnsts,new_defs)
    
    # step 3: eliminate quantfiers using finite instantiations

    from_asserts = il.And(*[il.Equals(x,x) for x in ilu.used_symbols_ast(il.And(*errconds)) if
                            tr.is_skolem(x) and not il.is_function_sort(x.sort)])
    iu.dbg('from_asserts')
    invar_syms.update(ilu.used_symbols_ast(from_asserts))
    sort_constants = mine_constants(mod,trans,il.And(invariant,from_asserts))
    sort_constants2 = mine_constants2(mod,trans,invariant)
    print '\ninstantiations:'
    trans,invariant = Qelim(sort_constants,sort_constants2)(trans,invariant,indhyps)
    
    
#    print 'after qe:'
#    print 'trans: {}'.format(trans)
#    print 'invariant: {}'.format(invariant)

    # step 4: instantiate the axioms using patterns

    # We have to condition both the transition relation and the
    # invariant on the axioms, so we define a boolean symbol '__axioms'
    # to represent the axioms.

    axs = instantiate_axioms(mod,stvars,trans,invariant,sort_constants,funs)
    ax_conj = il.And(*axs)
    ax_var = il.Symbol('__axioms',ax_conj.sort)
    ax_def = il.Definition(ax_var,ax_conj)
    invariant = il.Implies(ax_var,invariant)
    trans = ilu.Clauses(trans.fmlas+[ax_var],trans.defs+[ax_def])
    
    # step 5: eliminate all non-propositional atoms by replacing with fresh booleans
    # An atom with next-state symbols is converted to a next-state symbol if possible

    stvarset = set(stvars)
    prop_abs = dict()  # map from atoms to proposition variables
    global prop_abs_ctr  # sigh -- python lameness
    prop_abs_ctr = 0   # counter for fresh symbols
    new_stvars = []    # list of fresh symbols

    # get the propositional abstraction of an atom
    def new_prop(expr):
        res = prop_abs.get(expr,None)
        if res is None:
            prev = prev_expr(stvarset,expr,sort_constants)
            if prev is not None:
#                print 'stvar: old: {} new: {}'.format(prev,expr)
                pva = new_prop(prev)
                res = tr.new(pva)
                new_stvars.append(pva)
                prop_abs[expr] = res  # prevent adding this again to new_stvars
            else:
                global prop_abs_ctr
                res = il.Symbol('__abs[{}]'.format(prop_abs_ctr),expr.sort)
#                print '{} = {}'.format(res,expr)
                prop_abs[expr] = res
                prop_abs_ctr += 1
        return res

    # propositionally abstract an expression
    global mk_prop_fmlas
    mk_prop_fmlas = []
    def mk_prop_abs(expr):
        if il.is_quantifier(expr) or len(expr.args) > 0 and any(not is_finite_sort(a.sort) for a in expr.args):
            return new_prop(expr)
        return expr.clone(map(mk_prop_abs,expr.args))

    
    # apply propositional abstraction to the transition relation
    new_defs = map(mk_prop_abs,trans.defs)
    new_fmlas = [mk_prop_abs(il.close_formula(fmla)) for fmla in trans.fmlas]

    # find any immutable abstract variables, and give them a next definition

    def my_is_skolem(x):
        res = tr.is_skolem(x) and x not in invar_syms
        return res    
    def is_immutable_expr(expr):
        res = not any(my_is_skolem(sym) or tr.is_new(sym) or sym in stvarset for sym in ilu.used_symbols_ast(expr))
        return res
    for expr,v in prop_abs.iteritems():
        if is_immutable_expr(expr):
            new_stvars.append(v)
            print 'new state: {}'.format(expr)
            new_defs.append(il.Definition(tr.new(v),v))

    trans = ilu.Clauses(new_fmlas+mk_prop_fmlas,new_defs)

    # apply propositional abstraction to the invariant
    invariant = mk_prop_abs(invariant)

    # create next-state symbols for atoms in the invariant (is this needed?)
    rn = dict((sym,tr.new(sym)) for sym in stvars)
    mk_prop_abs(ilu.rename_ast(invariant,rn))  # this is to pick up state variables from invariant

    # update the state variables by removing the non-finite ones and adding the fresh state booleans
    stvars = [sym for sym in stvars if is_finite_sort(sym.sort)] + new_stvars

#    iu.dbg('trans')
#    iu.dbg('stvars')
#    iu.dbg('invariant')
#    exit(0)

    # For each state var, create a variable that corresponds to the input of its latch
    # Also, havoc all the state bits except the init flag at the initial time. This
    # is needed because in aiger, all latches start at 0!

    def fix(v):
        return v.prefix('nondet')
    def curval(v):
        return v.prefix('curval')
    def initchoice(v):
        return v.prefix('initchoice')
    stvars_fix_map = dict((tr.new(v),fix(v)) for v in stvars)
    stvars_fix_map.update((v,curval(v)) for v in stvars if v != init_var)
    trans = ilu.rename_clauses(trans,stvars_fix_map)
#    iu.dbg('trans')
    new_defs = trans.defs + [il.Definition(ilu.sym_inst(tr.new(v)),ilu.sym_inst(fix(v))) for v in stvars]
    new_defs.extend(il.Definition(curval(v),il.Ite(init_var,v,initchoice(v))) for v in stvars if  v != init_var)
    trans = ilu.Clauses(trans.fmlas,new_defs)
    
    # Turn the transition constraint into a definition
    
    cnst_var = il.Symbol('__cnst',il.find_sort('bool'))
    new_defs = list(trans.defs)
    new_defs.append(il.Definition(tr.new(cnst_var),fix(cnst_var)))
    new_defs.append(il.Definition(fix(cnst_var),il.Or(cnst_var,il.Not(il.And(*trans.fmlas)))))
    stvars.append(cnst_var)
    trans = ilu.Clauses([],new_defs)
    
    # Input are all the non-defined symbols. Output indicates invariant is false.

#    iu.dbg('trans')
    def_set = set(df.defines() for df in trans.defs)
    def_set.update(stvars)
#    iu.dbg('def_set')
    used = ilu.used_symbols_clauses(trans)
    used.update(ilu.symbols_ast(invariant))
    inputs = [sym for sym in used if
              sym not in def_set and not il.is_interpreted_symbol(sym)]
    fail = il.Symbol('__fail',il.find_sort('bool'))
    outputs = [fail]
    

#    iu.dbg('trans')
    
    # make an aiger

    aiger = Encoder(inputs,stvars,outputs)
    comb_defs = [df for df in trans.defs if not tr.is_new(df.defines())]

    invar_fail = il.Symbol('invar__fail',il.find_sort('bool'))  # make a name for invariant fail cond
    comb_defs.append(il.Definition(invar_fail,il.Not(invariant)))

    aiger.deflist(comb_defs)
    for df in trans.defs:
        if tr.is_new(df.defines()):
            aiger.set(tr.new_of(df.defines()),aiger.eval(df.args[1]))
    miter = il.And(init_var,il.Not(cnst_var),il.Or(invar_fail,il.And(fix(erf),il.Not(fix(cnst_var)))))
    aiger.set(fail,aiger.eval(miter))

#    aiger.sub.debug()

    # make a decoder for the abstract propositions

    decoder = dict((y,x) for x,y in prop_abs.iteritems())
    for sym in aiger.inputs + aiger.latches:
        if sym not in decoder and sym in orig_syms:
            decoder[sym] = sym

    cnsts = set(sym for syms in sort_constants.values() for sym in syms)
    return aiger,decoder,annot,cnsts,action,stvarset