def eval_expr_listo(exprs: Union[List, Var], env, value, depth=0, maxdepth=3): """ Evaluate a list of expressions. Not the same as evaluating the List AST """ if depth >= maxdepth: # logger.debug("Depth {} reached, which is the maximum depth".format(depth)) return fail uuid = str(uuid4())[:4] head_expr = var("head_expr_" + uuid) tail_expr = var("tail_expr_" + uuid) head_value = var("head_value_" + uuid) tail_value = var("tail_value_" + uuid) # fmt: off return conde(( typeo(exprs, list), typeo(value, list), # Either empty list or filled list conde( (eq(exprs, []), eq(value, [])), ( conso(head_expr, tail_expr, exprs), eval_expro(head_expr, env, head_value, depth + 1, maxdepth), # TODO: how to do depth in lists? typeo(tail_expr, list), typeo(tail_value, list), eval_expr_listo(tail_expr, env, tail_value, depth + 1, maxdepth), conso(head_value, tail_value, value)))))
def walk(pos, path, end_pos): if eq(path, []): eq(pos, end_pos) return success else: x = var() return conde(edges(pos, path[0], x), walk(x, path[1:], end_pos))
def generic_recusive_predicate( *args, head=head_predicate, bases=base_cases, recursion=recursive_rules, bvars=bc_vars, rvars=rc_vars ): bvars = [ dict( [(c, kanren.var()) for c in v] + [(x, args[x]) for x in range(head.get_arity())] ) for v in bvars ] rvars = [ dict( [(c, kanren.var()) for c in v] + [(x, args[x]) for x in range(head.get_arity())] ) for v in rvars ] base_cases = [ [ a[0].as_kanren()( *[ bvars[ind][ar] if ar in bvars[ind] else ar.get_name() for ar in a[1:] ] ) for a in cl ] for ind, cl in enumerate(bases) ] recursion = [ [ a[0].as_kanren()( *[ rvars[ind][ar] if ar in rvars[ind] else ar.get_name() for ar in a[1:] ] ) if a[0] != head_predicate else kanren.core.Zzz( generic_recusive_predicate, *[ rvars[ind][ar] if ar in rvars[ind] else ar.get_name() for ar in a[1:] ] ) for a in cl ] for ind, cl in enumerate(recursion) ] all_for_conde = base_cases + recursion return kanren.conde(*all_for_conde)
def eval_stmto(stmt, env, new_env, depth=0, maxdepth=3): logger.info("Evaluating stmt {} to new env {} using old env {}".format( ast_dump_if_possible(stmt), ast_dump_if_possible(new_env), ast_dump_if_possible(env), )) if depth >= maxdepth: return fail uuid = str(uuid4())[:4] # fmt: off goals = conde( ( eq( stmt, ast.Assign(targets=var('assign_targets_' + uuid), value=var("assign_value_" + uuid))), # TODO: Allow for multiple assigns: a, b, = ... heado(ast.Name(id=var('assign_lhs_' + uuid), ctx=ast.Store()), var('assign_targets_' + uuid)), eval_expro(var("assign_value_" + uuid), env, var("assign_rhs_" + uuid)), conso([var("assign_lhs_" + uuid), var("assign_rhs_" + uuid)], env, new_env), # new_env = [lhs, rhs] + env ), # Expression statements don't change the environment ( eq(stmt, ast.Expr(value=var("exprbody" + uuid))), # Expressions eq(env, new_env)), ) # fmt: on return goals
def tios(x, z): y = var() w = var() lista = set(run(16, x, conde((padre(y, x), padre(y, w), padre(w, z))))) p = list(run(8, x, padre(x, z))) for i in p: lista.discard(i) return lista
def tios(x, z): y = var() w = var() vtios=set(run(10, x, conde((parent(y,x), parent(y,w), parent(w,z))))) p=list(run(10, x, parent(x, z))) for i in p: vtios.discard(i) return vtios
def math_reduceo(in_expr, out_expr): """Create a relation for a couple math-based identities.""" x_lv = var() x_lv.token = f'x{x_lv.token}' return (lall, conde([ eq(in_expr, etuple(add, x_lv, x_lv)), eq(out_expr, etuple(mul, 2, x_lv)) ], [ eq(in_expr, etuple(log, etuple(exp, x_lv))), eq(out_expr, x_lv) ]), conde([(isinstanceo, [in_expr, (float, int, ExpressionTuple)], True)], [(isinstanceo, [out_expr, (float, int, ExpressionTuple)], True)]))
def eval_expro(expr, env, value, depth=0, maxdepth=3): # logger.debug("Evaluating expr {} to {} with env {}".format(expr, value, env)) uuid = str(uuid4())[:4] if isinstance(expr, ast.AST): logger.info("Found AST for expr -> {}".format( ast_dump_if_possible(expr))) if isinstance(value, ast.AST): logger.info("Found AST for value -> {}".format( ast_dump_if_possible(value))) if depth >= maxdepth: return fail # fmt: off return conde( (eq(expr, ast.Name(id=var('name_' + uuid), ctx=ast.Load())), lookupo(var('name_' + uuid), env, value)), # (lany( # typeo(value, int), # typeo(value, str), # ), # eq(expr, ast.Constant(value=value)),), (eq(expr, ast.Str(s=var('str_e_' + uuid))), typeo( value, str), eq(var('str_e_' + uuid), value)), (eq(expr, ast.Num(n=value)), membero(value, [_ for _ in range(5)])), (eq( expr, ast.BinOp(left=var('e1_' + uuid), op=var('op_e_' + uuid), right=var('e2_' + uuid))), typeo(var('v1_' + uuid), int), typeo(var('v2_' + uuid), int), eval_expro(var('e1_' + uuid), env, var('v1_' + uuid), depth + 1, maxdepth), eval_expro(var('e2_' + uuid), env, var('v2_' + uuid), depth + 1, maxdepth), eval_opo(var('op_e_' + uuid), var('op_v_' + uuid), var('v1_' + uuid), var('v2_' + uuid), value), binopo(var('v1_' + uuid), var('v2_' + uuid), value, op=var('op_v_' + uuid))), # Lists (eq(expr, ast.List(elts=var("list_elements_" + uuid), ctx=ast.Load())), eval_expr_listo(var("list_elements_" + uuid), env, value, depth, maxdepth)), # Functions (eq(expr, ast.Lambda(body=var('body_' + uuid), args=[])), typeo(value, FunctionType), eval_expro(var('body_' + uuid), env, var('body_v_' + uuid), depth + 1, maxdepth), eq(lambda: var('body_v_' + uuid), value)), (eq(expr, ast.Call(func=var('func_' + uuid), args=[], keywords=[])), typeo(var('func_v_' + uuid), FunctionType), eval_expro(var('func_' + uuid), env, var('func_v_' + uuid), depth + 1, maxdepth), applyo(var('func_v_' + uuid), [], value)), )
def lookupo(name, env, t, depth=0, maxdepth=100): if depth >= maxdepth: return fail head = var() rest = var() # fmt: off return conde( (heado(head, env), heado(name, head), tailo(rest, head), heado( t, rest)), (tailo(rest, env), lookupo(name, rest, t, depth + 1, maxdepth)))
def generic_predicate(*args, core_obj=self, hvars=head_vars, ovars=other_args): vars_to_use = dict([(v, kanren.var()) for v in ovars]) return kanren.conde([ x.get_predicate().as_kanren()(*[ args[hvars[y]] if y in hvars else vars_to_use[y] for y in x.get_terms() ]) for x in core_obj.get_literals() ])
def eval_opo(op, value, v1, v2, v): # Extra args for future use # fmt: off return conde( (eq(op, ast.Add()), eq(value, add)), (eq(op, ast.Sub()), eq(value, sub)), (eq(op, ast.Mult()), eq(value, mul)), ( eq(op, ast.Mod()), neq(v2, 0), # Prevent division by zero eq(value, mod)), )
def primos(x,w): y = var() j = var() k = var() l = var() vprimos=set(run(10, x, conde((parent(y,x), parent(j,w), parent(k,y),parent(k,j))))) hermano=hermanos(l,w) for i in hermano: vprimos.discard(i) vprimos.discard(w) return vprimos
def test_instanceo(): b_lv, q_lv = var(), var() goal_sets = [ # Logic variable instance type that's immediately ground in another # goal ([isinstanceo(q_lv, list), eq(q_lv, [])], ([],)), # Logic variable in the type argument that's eventually unified with # a valid type for the given instance argument ([isinstanceo([], q_lv), eq(q_lv, list)], (list,)), # Logic variable type argument that's eventually reified to a tuple # containing a valid type for the instance argument # NOTE: Not currently supported. # ( # [isinstanceo([], q_lv), eq(q_lv, (int, b_lv)), eq(b_lv, list)], # ((int, list),), # ), # A non-ground, non-logic variable instance argument that changes type # when ground ([isinstanceo(cons(1, q_lv), list), eq(q_lv, [])], ([],)), # Logic variable instance argument that's eventually grounded through # another logic variable ([isinstanceo(q_lv, int), eq(b_lv, 1), eq(b_lv, q_lv)], (1,)), # The same, but with `conde` ( [ isinstanceo(q_lv, int), # One succeeds, one fails conde([eq(b_lv, 1)], [eq(b_lv, "hi")]), eq(b_lv, q_lv), ], (1,), ), # Logic variable instance argument that's eventually grounded to a # mismatched instance type through another logic variable ([isinstanceo(q_lv, int), eq(b_lv, 1.0), eq(b_lv, q_lv)], ()), # Logic variable type argument that's eventually grounded to a # mismatched instance type through another logic variable (i.e. both # arguments are ground to `int` types) ([isinstanceo(q_lv, b_lv), eq(b_lv, int), eq(b_lv, q_lv)], ()), # Logic variable type argument that's eventually grounded to a # mismatched instance type through another logic variable (i.e. both # arguments are ground to the value `1`, which violates the second # argument type expectations) ([isinstanceo(q_lv, b_lv), eq(b_lv, 1), eq(b_lv, q_lv)], ()), # Check a term that's unground by ground enough for this constraint ([isinstanceo(q_lv, tuple), eq([(b_lv,)], q_lv)], ()), ] for i, (goal, expected) in enumerate(goal_sets): for goal_ord in permutations(goal): res = run(0, q_lv, *goal_ord) assert res == expected, (i, goal_ord)
def primos(x, w): y = var() t = var() u = var() e = var() lista = set( run(40, x, conde((padre(y, x), padre(t, w), padre(u, y), padre(u, t))))) herm = hermanos(e, w) for i in herm: lista.discard(i) lista.discard(w) return lista
def test_disequality(): a_lv, b_lv = var(), var() q_lv, c_lv = var(), var() goal_sets = [ ([neq(a_lv, 1)], 1), ([neq(cons(1, a_lv), [1]), eq(a_lv, [])], 0), ([neq(cons(1, a_lv), [1]), eq(a_lv, b_lv), eq(b_lv, [])], 0), ([neq([1], cons(1, a_lv)), eq(a_lv, b_lv), eq(b_lv, [])], 0), # TODO FIXME: This one won't work due to an ambiguity in `cons`. # ( # [ # neq([1], cons(1, a_lv)), # eq(a_lv, b_lv), # # Both make `cons` produce a list # conde([eq(b_lv, None)], [eq(b_lv, [])]), # ], # 0, # ), ([neq(cons(1, a_lv), [1]), eq(a_lv, b_lv), eq(b_lv, tuple())], 1), ([neq([1], cons(1, a_lv)), eq(a_lv, b_lv), eq(b_lv, tuple())], 1), ( [ neq([1], cons(1, a_lv)), eq(a_lv, b_lv), # The first should fail, the second should succeed conde([eq(b_lv, [])], [eq(b_lv, tuple())]), ], 1, ), ([neq(a_lv, 1), eq(a_lv, 1)], 0), ([neq(a_lv, 1), eq(b_lv, 1), eq(a_lv, b_lv)], 0), ([neq(a_lv, 1), eq(b_lv, 1), eq(a_lv, b_lv)], 0), ([neq(a_lv, b_lv), eq(b_lv, c_lv), eq(c_lv, a_lv)], 0), ] for i, (goal, num_results) in enumerate(goal_sets): # The order of goals should not matter, so try them all for goal_ord in permutations(goal): res = list(lconj(*goal_ord)({})) assert len(res) == num_results, (i, goal_ord) res = list(lconj(*goal_ord)(ConstrainedState())) assert len(res) == num_results, (i, goal_ord) assert len(run(0, q_lv, *goal_ord)) == num_results, (i, goal_ord)
def locate(): action = var('action') reply = var('reply') post_replies = var('post.repliesCount') reply_syns = {'reply', 'comment'} return ( (post_replies, (reply,)), [ conde((R['dobj'](action, reply),), (R['pobj'](action, reply),)), one_of(R, reply, reply_syns), R['nummod'](reply, post_replies), membero(reply, not_used), membero(post_replies, not_used) ] )
def test_typeo(): a_lv, b_lv, q_lv = var(), var(), var() goal_sets = [ # Logic variable instance type that's immediately ground in another # goal ([typeo(q_lv, int), eq(q_lv, 1)], (1,)), # Use an unhashable constrained term ([typeo(q_lv, list), eq(q_lv, [])], ([],)), # TODO: A constraint parameter that is never ground # ([typeo(a_lv, q_lv), eq(a_lv, 1)], (int,)), # A non-ground, non-logic variable instance argument that changes type # when ground ([typeo(cons(1, a_lv), list), eq(a_lv, [])], (q_lv,)), # Logic variable instance and type arguments ([typeo(q_lv, int), eq(b_lv, 1), eq(b_lv, q_lv)], (1,)), # The same, but with `conde` ( [ typeo(q_lv, int), # One succeeds, one fails conde([eq(b_lv, 1)], [eq(b_lv, "hi")]), eq(b_lv, q_lv), ], (1,), ), # Logic variable instance argument that's eventually grounded to a # mismatched instance type through another logic variable ([typeo(q_lv, int), eq(b_lv, 1.0), eq(b_lv, q_lv)], ()), # Logic variable type argument that's eventually grounded to a # mismatched instance type through another logic variable (i.e. both # arguments are ground to `int` types) ([typeo(q_lv, b_lv), eq(b_lv, int), eq(b_lv, q_lv)], ()), # Logic variable type argument that's eventually grounded to a # mismatched instance type through another logic variable (i.e. both # arguments are ground to the value `1`, which violates the second # argument type expectations) ([typeo(q_lv, b_lv), eq(b_lv, 1), eq(b_lv, q_lv)], ()), # Check a term that's unground by ground enough for this constraint ([typeo(a_lv, tuple), eq([(b_lv,)], a_lv)], ()), ] for i, (goal, expected) in enumerate(goal_sets): for goal_ord in permutations(goal): res = run(0, q_lv, *goal_ord) assert res == expected, (i, goal_ord)
def locate(): post_text = var('post.text') post = var('post') post_syns = {'message', 'content', 'post'} contain = var('contain') return ( (post_text, (contain, post_text)), [ one_of(R, post, post_syns), R['LEMMA'](contain, 'contain'), conde((R['relcl'](post, contain),), (R['acl'](post, contain),)), R['oprd'](contain, post_text), membero(contain, not_used), membero(post_text, not_used) ] )
def single_math_reduceo(expanded_term, reduced_term): """Construct a goal for some simple math reductions.""" x_lv = var() return lall( isinstanceo(x_lv, Real), isinstanceo(x_lv, ExpressionTuple), conde( [ eq(expanded_term, etuple(add, x_lv, x_lv)), eq(reduced_term, etuple(mul, 2, x_lv)), ], [ eq(expanded_term, etuple(log, etuple(exp, x_lv))), eq(reduced_term, x_lv) ], ), )
def eval_programo(program: ast.Module, env, value): logger.info("Evaluating program {} to {} with env {}".format( ast_dump_if_possible(program), ast_dump_if_possible(value), ast_dump_if_possible(env), )) goals = [] curr_env = env for ast_expr in program.body: logger.info("Evaluating statement {} with env {}".format( ast_dump_if_possible(ast_expr), ast_dump_if_possible(curr_env))) new_env = var() g = eval_stmto(ast_expr, curr_env, new_env) curr_env = find_new_env_after_stmt(g, old_env=curr_env, new_env_lv=new_env) goals.append(g) return conde(goals), curr_env
def hermanos(x,w): vhermanos=set(run(10, x, conde((parent(y,x), parent(y,w) )))) vhermanos.discard(w) return vhermanos
def parent(x, y): return conde((father(x, y),), (mother(x,y),))
def abuelos(x, z): y = var() return conde((parent(x,y), parent(y,z) ))
def grandparent(gparent, child): p = var() return conde((parent(gparent, p), parent(p, child)))
def grandparent(x, z): y = var() return conde((parent(x, y), parent(y, z)))
def grandparent(x, z): y = var() return conde((dayCal(x, y), dayCal(y, z)))
def uncle(x, y): temp = var() return conde((father(temp, x), grandparent(temp, y)))
def grandparent(gp, child): p = var() return conde((parent(gp, p), parent(p, child)))
def sibling(x, y): temp = var() return conde((parent(temp, x), parent(temp, y)))
def grandparent(x, y): temp = var() return conde((parent(x, temp), parent(temp, y)))
def parent(p, child): return conde([father(p, child)], [mother(p, child)])
def sibling(a, b): p = var() return conde((parent(p, a), parent(p, b)))
def one_to_threeo(x, y): return conde([eq(x, 1), eq(y, 3)])