def fun_scenario6(): """ Scenario 6 ---------- ERLANG CODE -spec f6(any()) -> any(). f6(X) when is_function(X, 1) -> f6(X(42)); f6(X) when X =/= 42 -> X. TRACE (with 3 fun applications) is_fun(f, 1) t1 = f(42) t2 = t1(42) t3 = t2(42) """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() f, t1, t2 = Consts('f, t1, t2', T) slv.add([ # 1st step. T.is_fun(f), arity( T.fval(f) ) == 1, fmap( T.fval(f) )[ L.cons(T.int(42), L.nil) ] == t1, # 2nd step. T.is_fun(t1), arity( T.fval(t1) ) == 1, fmap( T.fval(t1) )[ L.cons(T.int(42), L.nil) ] == t2, # 3rd step. T.is_fun(t2), arity( T.fval(t2) ) == 1, fmap( T.fval(t2) )[ L.cons(T.int(42), L.nil) ] == T.int(42), ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) f_sol = encoder.encode(m[f]) # Create the result t2_exp = cc.mk_fun(1, [ cc.mk_fun_entry([cc.mk_int(42)], cc.mk_int(42)) ], cc.mk_int(42)) t1_exp = cc.mk_fun(1, [ cc.mk_fun_entry([cc.mk_int(42)], t2_exp) ], t2_exp) f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([cc.mk_int(42)], t1_exp) ], t1_exp) compare_solutions(f_exp, f_sol)
def fun_scenario4(): """ Scenario 4 ---------- ERLANG CODE -spec f4(fun((integer()) -> integer()), integer(), integer()) -> ok. f4(F, X, Y) -> Z = F(X), case Z(Y) of 42 -> error(bug); _ -> ok end. TRACE is_int(x) is_int(y) is_fun(f, 1) t1 = f(x) t1(y) = 42 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() x, y, f, t1 = Consts('x, y, f, t1', T) slv.add([ T.is_int(x), T.is_int(y), T.is_fun(f), arity( T.fval(f) ) == 1, fmap( T.fval(f) )[ L.cons(x, L.nil) ] == t1, T.is_fun(t1), arity( T.fval(t1) ) == 1, fmap( T.fval(t1) )[ L.cons(y, L.nil) ] == T.int(42), ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) x_sol, y_sol, f_sol = [encoder.encode(m[v]) for v in [x, y, f]] # Create the result t1_exp = cc.mk_fun(1, [ cc.mk_fun_entry([y_sol], cc.mk_int(42)) ], cc.mk_int(42)) f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([x_sol], t1_exp) ], t1_exp) compare_solutions(f_exp, f_sol)
def fun_scenario7(): """ Scenario 7 ---------- ERLANG CODE -spec f7(fun((integer(), integer()) -> integer()), [integer()]) -> integer(). f7(F, L) when is_function(F, 2) -> case lists:foldl(F, 0, L) of 42 -> error(bug); R -> R end. TRACE is_fun(f, 2) is_lst(l) l = [h1 | l1] t1 = f(h1, 0) l1 = [h2 | l2] l2 = [] f(h2, t1) = 42 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() f, l, h1, l1, h2, l2, t1, t2 = Consts('f, l, h1, l1, h2, l2, t1, t2', T) slv.add([ # Init T.is_fun(f), arity( T.fval(f) ) == 2, T.is_lst(l), # 1st element L.is_cons( T.lval(l) ), h1 == L.hd( T.lval(l) ), T.is_int(h1), l1 == T.lst( L.tl( T.lval(l) ) ), t1 == fmap( T.fval(f) )[ L.cons(h1, L.cons(T.int(0), L.nil)) ], T.is_int(t1), # 2nd element L.is_cons( T.lval(l1) ), h2 == L.hd( T.lval(l1) ), T.is_int(h2), l2 == T.lst( L.tl( T.lval(l1) ) ), t2 == fmap( T.fval(f) )[ L.cons(h2, L.cons(t1, L.nil)) ], # Result L.is_nil( T.lval(l2) ), t2 == T.int(42) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) l_sol, f_sol = [encoder.encode(m[v]) for v in [l, f]] # Create the result f_exp = cc.mk_fun(2, [ cc.mk_fun_entry([l_sol.subterms[1], cc.mk_int(4)], cc.mk_int(42)), cc.mk_fun_entry([l_sol.subterms[0], cc.mk_int(0)], cc.mk_int(4)) ], cc.mk_int(42)) compare_solutions(f_exp, f_sol)
def fun_scenario7(): """ Scenario 7 ---------- ERLANG CODE -spec f7(fun((integer(), integer()) -> integer()), [integer()]) -> integer(). f7(F, L) when is_function(F, 2) -> case lists:foldl(F, 0, L) of 42 -> error(bug); R -> R end. TRACE is_fun(f, 2) is_lst(l) l = [h1 | l1] t1 = f(h1, 0) l1 = [h2 | l2] l2 = [] f(h2, t1) = 42 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() f, l, h1, l1, h2, l2, t1, t2 = Consts('f, l, h1, l1, h2, l2, t1, t2', T) slv.add([ # Init T.is_fun(f), arity( T.fval(f) ) == 2, T.is_lst(l), # 1st element L.is_cons( T.lval(l) ), h1 == L.hd( T.lval(l) ), T.is_int(h1), l1 == T.lst( L.tl( T.lval(l) ) ), t1 == fmap( T.fval(f) )[ L.cons(h1, L.cons(T.int(0), L.nil)) ], T.is_int(t1), # 2nd element L.is_cons( T.lval(l1) ), h2 == L.hd( T.lval(l1) ), T.is_int(h2), l2 == T.lst( L.tl( T.lval(l1) ) ), t2 == fmap( T.fval(f) )[ L.cons(h2, L.cons(t1, L.nil)) ], # Result L.is_nil( T.lval(l2) ), t2 == T.int(42) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) l_sol, f_sol = [encoder.encode(m[v]) for v in [l, f]] # Create the result f_exp = cc.mk_fun(2, [ cc.mk_fun_entry([l_sol.subterms[0], cc.mk_int(0)], cc.mk_int(4)), cc.mk_fun_entry([l_sol.subterms[1], cc.mk_int(4)], cc.mk_int(42)) ], cc.mk_int(4)) compare_solutions(f_exp, f_sol)
def fun_scenario3(): """ Scenario 3 ---------- ERLANG CODE -spec f3(fun((integer()) -> integer()), integer(), integer()) -> ok. f3(F, X, Y) -> case double(F, X) of 42 -> case double(F, Y) of 17 -> error(bug); _ -> ok end; _ -> ok end. TRACE is_int(x) is_int(y) is_fun(f, 1) t1 = f(x) f(t1) = 42 t2 = f(y) f(t2) = 17 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() x, y, f, t1, t2 = Consts('x, y, f, t1, t2', T) slv.add([ T.is_int(x), T.is_int(y), T.is_fun(f), arity( T.fval(f) ) == 1, T.is_int(t1), T.is_int(t2), fmap( T.fval(f) )[ L.cons(x, L.nil) ] == t1, fmap( T.fval(f) )[ L.cons(t1, L.nil) ] == T.int(42), fmap( T.fval(f) )[ L.cons(y, L.nil) ] == t2, fmap( T.fval(f) )[ L.cons(t2, L.nil) ] == T.int(17) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) x_sol, y_sol, f_sol = [encoder.encode(m[v]) for v in [x, y, f]] # Create the result f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([cc.mk_int(5)], cc.mk_int(17)), cc.mk_fun_entry([cc.mk_int(4)], cc.mk_int(42)), cc.mk_fun_entry([y_sol], cc.mk_int(5)), cc.mk_fun_entry([x_sol], cc.mk_int(4)) ], cc.mk_int(17)) compare_solutions(f_exp, f_sol)
def fun_scenario3(): """ Scenario 3 ---------- ERLANG CODE -spec f3(fun((integer()) -> integer()), integer(), integer()) -> ok. f3(F, X, Y) -> case double(F, X) of 42 -> case double(F, Y) of 17 -> error(bug); _ -> ok end; _ -> ok end. TRACE is_int(x) is_int(y) is_fun(f, 1) t1 = f(x) f(t1) = 42 t2 = f(y) f(t2) = 17 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() x, y, f, t1, t2 = Consts('x, y, f, t1, t2', T) slv.add([ T.is_int(x), T.is_int(y), T.is_fun(f), arity( T.fval(f) ) == 1, T.is_int(t1), T.is_int(t2), fmap( T.fval(f) )[ L.cons(x, L.nil) ] == t1, fmap( T.fval(f) )[ L.cons(t1, L.nil) ] == T.int(42), fmap( T.fval(f) )[ L.cons(y, L.nil) ] == t2, fmap( T.fval(f) )[ L.cons(t2, L.nil) ] == T.int(17) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) x_sol, y_sol, f_sol = [encoder.encode(m[v]) for v in [x, y, f]] # Create the result f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([x_sol], cc.mk_int(4)), cc.mk_fun_entry([cc.mk_int(5)], cc.mk_int(17)), cc.mk_fun_entry([cc.mk_int(4)], cc.mk_int(42)), cc.mk_fun_entry([y_sol], cc.mk_int(5)) ], cc.mk_int(4)) compare_solutions(f_exp, f_sol)
def fun_scenario8(): """ Scenario 8 ---------- ERLANG CODE -spec f8(fun((integer()) -> integer()), [integer()]) -> integer(). f8(F, L) when is_function(F, 1) -> L1 = lists:filter(F, L), hd(L1). TRACE is_fun(f, 1) is_lst(l) l = [h1 | l1] f(h1) = false l1 = [h2 | l2] f(h2) = false l2 = [] """ erl = Erlang() T, L, fmap, arity, atmFalse = erl.Term, erl.List, erl.fmap, erl.arity, erl.atmFalse # Create the model slv = Solver() f, l, h1, l1, h2, l2 = Consts('f, l, h1, l1, h2, l2', T) slv.add([ # Init T.is_fun(f), arity( T.fval(f) ) == 1, T.is_lst(l), # 1st element L.is_cons( T.lval(l) ), h1 == L.hd( T.lval(l) ), l1 == T.lst( L.tl( T.lval(l) ) ), atmFalse == fmap( T.fval(f) )[ L.cons(h1, L.nil) ], # 2nd element L.is_cons( T.lval(l1) ), h2 == L.hd( T.lval(l1) ), l2 == T.lst( L.tl( T.lval(l1) ) ), atmFalse == fmap( T.fval(f) )[ L.cons(h2, L.nil) ], # Result L.is_nil( T.lval(l2) ) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) l_sol, f_sol = [encoder.encode(m[v]) for v in [l, f]] # Create the result f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([l_sol.subterms[1]], encoder.encode(atmFalse)), cc.mk_fun_entry([l_sol.subterms[0]], encoder.encode(atmFalse)) ], encoder.encode(atmFalse)) compare_solutions(f_exp, f_sol)
def fun_scenario8(): """ Scenario 8 ---------- ERLANG CODE -spec f8(fun((integer()) -> integer()), [integer()]) -> integer(). f8(F, L) when is_function(F, 1) -> L1 = lists:filter(F, L), hd(L1). TRACE is_fun(f, 1) is_lst(l) l = [h1 | l1] f(h1) = false l1 = [h2 | l2] f(h2) = false l2 = [] """ erl = Erlang() T, L, fmap, arity, atmFalse = erl.Term, erl.List, erl.fmap, erl.arity, erl.atmFalse # Create the model slv = Solver() f, l, h1, l1, h2, l2 = Consts('f, l, h1, l1, h2, l2', T) slv.add([ # Init T.is_fun(f), arity( T.fval(f) ) == 1, T.is_lst(l), # 1st element L.is_cons( T.lval(l) ), h1 == L.hd( T.lval(l) ), l1 == T.lst( L.tl( T.lval(l) ) ), atmFalse == fmap( T.fval(f) )[ L.cons(h1, L.nil) ], # 2nd element L.is_cons( T.lval(l1) ), h2 == L.hd( T.lval(l1) ), l2 == T.lst( L.tl( T.lval(l1) ) ), atmFalse == fmap( T.fval(f) )[ L.cons(h2, L.nil) ], # Result L.is_nil( T.lval(l2) ) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) l_sol, f_sol = [encoder.encode(m[v]) for v in [l, f]] # Create the result f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([l_sol.subterms[0]], encoder.encode(atmFalse)), cc.mk_fun_entry([l_sol.subterms[1]], encoder.encode(atmFalse)) ], encoder.encode(atmFalse)) compare_solutions(f_exp, f_sol)
def fun_scenario5(): """ Scenario 5 ---------- ERLANG CODE -spec f5(fun((integer()) -> integer()), integer(), integer(), integer()) -> ok. f5(F, X, Y, Z) -> case F(X, Y, Z) of 42 -> case F(Z, Y, X) of 17 -> error(bug); _ -> ok end; _ -> ok end. TRACE is_int(x) is_int(y) is_int(z) is_fun(f, 3) f(x, y, z) = 42 f(z, y, x) = 17 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() x, y, z, f = Consts('x, y, z, f', T) slv.add([ T.is_int(x), T.is_int(y), T.is_int(z), T.is_fun(f), arity( T.fval(f) ) == 3, fmap( T.fval(f) )[ L.cons(x, L.cons(y, L.cons(z, L.nil))) ] == T.int(42), fmap( T.fval(f) )[ L.cons(z, L.cons(y, L.cons(x, L.nil))) ] == T.int(17), ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) x_sol, y_sol, z_sol, f_sol = [encoder.encode(m[v]) for v in [x, y, z, f]] # Create the result f_exp = cc.mk_fun(3, [ cc.mk_fun_entry([x_sol, y_sol, z_sol], cc.mk_int(42)), cc.mk_fun_entry([z_sol, y_sol, x_sol], cc.mk_int(17)) ], cc.mk_int(42)) compare_solutions(f_exp, f_sol)
def fun_scenario5(): """ Scenario 5 ---------- ERLANG CODE -spec f5(fun((integer()) -> integer()), integer(), integer(), integer()) -> ok. f5(F, X, Y, Z) -> case F(X, Y, Z) of 42 -> case F(Z, Y, X) of 17 -> error(bug); _ -> ok end; _ -> ok end. TRACE is_int(x) is_int(y) is_int(z) is_fun(f, 3) f(x, y, z) = 42 f(z, y, x) = 17 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() x, y, z, f = Consts('x, y, z, f', T) slv.add([ T.is_int(x), T.is_int(y), T.is_int(z), T.is_fun(f), arity( T.fval(f) ) == 3, fmap( T.fval(f) )[ L.cons(x, L.cons(y, L.cons(z, L.nil))) ] == T.int(42), fmap( T.fval(f) )[ L.cons(z, L.cons(y, L.cons(x, L.nil))) ] == T.int(17), ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) x_sol, y_sol, z_sol, f_sol = [encoder.encode(m[v]) for v in [x, y, z, f]] # Create the result f_exp = cc.mk_fun(3, [ cc.mk_fun_entry([z_sol, y_sol, x_sol], cc.mk_int(17)), cc.mk_fun_entry([x_sol, y_sol, z_sol], cc.mk_int(42)) ], cc.mk_int(17)) compare_solutions(f_exp, f_sol)
def fun_scenario1(): """ Scenario 1 ---------- ERLANG CODE -spec f1(fun((integer()) -> integer())) -> ok. f1(F) -> case F(3) of 42 -> case F(10) of 17 -> error(bug); _ -> ok end; _ -> ok end. TRACE is_fun(f, 1) f(3) = 42 f(10) = 17 """ erl = Erlang() T, L, fmap, arity = erl.Term, erl.List, erl.fmap, erl.arity # Create the model slv = Solver() f = Const('f', T) slv.add([ T.is_fun(f), arity( T.fval(f) ) == 1, fmap( T.fval(f) )[ L.cons(T.int(3), L.nil) ] == T.int(42), fmap( T.fval(f) )[ L.cons(T.int(10), L.nil) ] == T.int(17) ]) # Solve the model chk = slv.check() assert chk == sat, "Model in unsatisfiable" m = slv.model() encoder = TermEncoder(erl, m, fmap, arity) f_sol = encoder.encode(m[f]) # Create the result f_exp = cc.mk_fun(1, [ cc.mk_fun_entry([cc.mk_int(3)], cc.mk_int(42)), cc.mk_fun_entry([cc.mk_int(10)], cc.mk_int(17)), ], cc.mk_int(42)) compare_solutions(f_exp, f_sol)
def toFun(self, n): idx = simplify(n).as_long() # In case the solver randomly select a solution to be a fun # without fmap existing in the model arity = self.arity[idx] if self.fmap is None or self.fmap[idx] is None: return self.defaultFun(arity) defn = self.getArrayDecl(self.fmap[idx], self.erl.List).as_list() # Also prune keys with the wrong arity (mainly to genericFun specs adding an Exists axiom) kvs = [self.encodeKVPair(args, val) for [args, val] in defn[0:-1] if self.getActualArity(args) == arity] if len(kvs) == 0: default = self.encodeDefault(defn[-1]) return cc.mk_const_fun(arity, default) else: default = cc.get_value_from_fun_entry(kvs[0]) # Do not add the arity. # It will be deducted from the number of the arguments of the # first input. # return {"t": cc.JSON_TYPE_FUN, "v": kvs, "x": arity} return cc.mk_fun(arity, kvs, default)
def encode(self, data, funs=[]): # TODO description if data[0] == "int": return cc.mk_int(parse_int(data[1])) elif data[0] == "real": return cc.mk_float(parse_real(data[1])) elif data[0] == "atom": node = data[1] v = [] while node != "in": v.append(parse_int(node[1])) node = node[2] return cc.mk_atom(v) elif data[0] == "list": node = data[1] v = [] while node != "tn": v.append(self.encode(node[1], funs)) node = node[2] return cc.mk_list(v) elif data[0] == "tuple": node = data[1] v = [] while node != "tn": v.append(self.encode(node[1], funs)) node = node[2] return cc.mk_tuple(v) elif data[0] == "str": node = data[1] v = [] while node != "sn": v.append(node[1] == "true") node = node[2] return cc.mk_bitstring(v) elif data[0] == "fun": # TODO function decoding and encoding assert isinstance(data, list) and len(data) == 2 fv = parse_int(data[1]) # if a cycle (a function calling itself recursively) is found, # it is obvious that the solver has selected an arbitrary term as a value if fv in funs: return cc.mk_any() funs = funs[:] funs.append(fv) # get function info from solver # TODO save function arity and entries to an array val = self.solver.get_value(["fa", data[1]], ["fm", data[1]]) assert isinstance(val, list) and len(val) == 2 assert isinstance(val[0], list) and len(val[0]) == 2 arity = parse_int(expand_lets(val[0][1])) # if arity is less than or greater than 255, we assume it is an arbitrary value selected by the solver # because there is no constraint limiting the function's arity; thus, we set it to zero if arity < 0 or arity > 255: arity = 0 assert isinstance(val[1], list) and len(val[1]) == 2 node = expand_lets(val[1][1]) entries = [] otherwise = None while node != "fn": assert isinstance(node, list) and len(node) == 4 and node[0] == "fc" x = cc.get_list_subterms(self.encode(["list", node[1]], funs)) # keep only entries with argument length equal to arity if len(x) == arity: y = self.encode(node[2], funs) if otherwise is None: otherwise = y else: entries.append(cc.mk_fun_entry(x, y)) node = node[3] if otherwise is None: otherwise = cc.mk_any() return cc.mk_fun(arity, entries, otherwise) clg.debug_info("encoding failed: " + str(data)) assert False