def translate_to_SAT(init, transition, goal, time): clauses = [] states = [state for state in transition] # Symbol claiming state s at time t state_counter = itertools.count() for s in states: for t in range(time + 1): state_sym[s, t] = Expr("State_{}".format(next(state_counter))) # Add initial state axiom clauses.append(state_sym[init, 0]) # Add goal state axiom clauses.append(state_sym[goal, time]) # All possible transitions transition_counter = itertools.count() for s in states: for action in transition[s]: s_ = transition[s][action] for t in range(time): # Action 'action' taken from state 's' at time 't' to reach 's_' action_sym[s, action, t] = Expr("Transition_{}".format( next(transition_counter))) # Change the state from s to s_ clauses.append(action_sym[s, action, t] | '==>' | state_sym[s, t]) clauses.append(action_sym[s, action, t] | '==>' | state_sym[s_, t + 1]) # Allow only one state at any time for t in range(time + 1): # must be a state at any time clauses.append(associate('|', [state_sym[s, t] for s in states])) for s in states: for s_ in states[states.index(s) + 1:]: # for each pair of states s, s_ only one is possible at time t clauses.append((~state_sym[s, t]) | (~state_sym[s_, t])) # Restrict to one transition per timestep for t in range(time): # list of possible transitions at time t transitions_t = [tr for tr in action_sym if tr[2] == t] # make sure at least one of the transitions happens clauses.append( associate('|', [action_sym[tr] for tr in transitions_t])) for tr in transitions_t: for tr_ in transitions_t[transitions_t.index(tr) + 1:]: # there cannot be two transitions tr and tr_ at time t clauses.append(~action_sym[tr] | ~action_sym[tr_]) # Combine the clauses to form the cnf return associate('&', clauses)
def diff(y, x): """Return the symbolic derivative, dy/dx, as an Expr. However, you probably want to simplify the results with simp. >>> diff(x * x, x) ((x * 1) + (x * 1)) """ if y == x: return 1 elif not y.args: return 0 else: u, op, v = y.args[0], y.op, y.args[-1] if op == '+': return diff(u, x) + diff(v, x) elif op == '-' and len(y.args) == 1: return -diff(u, x) elif op == '-': return diff(u, x) - diff(v, x) elif op == '*': return u * diff(v, x) + v * diff(u, x) elif op == '/': return (v * diff(u, x) - u * diff(v, x)) / (v * v) elif op == '**' and isnumber(x.op): return (v * u**(v - 1) * diff(u, x)) elif op == '**': return (v * u**(v - 1) * diff(u, x) + u**v * Expr('log')(u) * diff(v, x)) elif op == 'log': return diff(u, x) / u else: raise ValueError("Unknown op: {} in diff({}, {})".format(op, y, x))
def standardize_variables(sentence, dic=None): """Replace all the variables in sentence with new variables.""" if dic is None: dic = {} if not isinstance(sentence, Expr): return sentence elif is_var_symbol(sentence.op): if sentence in dic: return dic[sentence] else: v = Expr('v_{}'.format(next(standardize_variables.counter))) dic[sentence] = v return v else: return Expr(sentence.op, *[standardize_variables(a, dic) for a in sentence.args])
def _competing_needs(self, actionA, actionB): """ Return True if the preconditions of the actions are all pairwise mutex in the parent layer See Also -------- layers.ActionNode layers.BaseLayer.parent_layer """ # TODO: implement this function # raise NotImplementedError # print(self.parent_layer.is_mutex(actionA,actionB)) # print(type(self.parent_layer.children)) # print(self.parent_layer.children) for x in actionA.preconditions: for y in actionB.preconditions: # print("-----",type(x),"->",len(x.args),"->",x.args) #print(type(x),"->",x," :: ",type(y),"->",y) #print(type(x),"->",(x.__invert__)," :: ",type(y),"->",(y) ) if (x.op == '~' and y.op != '~'): y_neg = Expr('~', y) if y_neg.__eq__(x): #print(x, " = ", y_neg); return True if (y.op == '~' and x.op != '~'): x_neg = Expr('~', x) if x_neg.__eq__(y): #print(y, " = ", x_neg); return True return False
def makeNoOp(literal): """ Create so-called 'no-op' actions, which only exist in a planning graph (they are not real actions in the problem domain) to persist a literal from one layer of the planning graph to the next. no-op actions are created such that logical negation is correctly evaluated. i.e., the no-op action of the negative literal ~At(place) is the logical negation of the no-op action of positive literal At(place); in other words NoOp::~At(place) == ~(NoOp::At(place) -- NOTE: NoOp::~At(place) is not a valid action, but the correct semantics are handled and enforced automatically. """ action = Expr("NoOp::" + literal.op, literal.args) return (Action(action, [set([literal]), []], [set([literal]), []]), Action(~action, [set([~literal]), []], [set([~literal]), []]))
def subst(s, x): """Substitute the substitution s into the expression x. >>> subst({x: 42, y:0}, F(x) + y) (F(42) + 0) """ if isinstance(x, list): return [subst(s, xi) for xi in x] elif isinstance(x, tuple): return tuple([subst(s, xi) for xi in x]) elif not isinstance(x, Expr): return x elif is_var_symbol(x.op): return s.get(x, x) else: return Expr(x.op, *[subst(s, arg) for arg in x.args])
def _inconsistent_effects(self, actionA, actionB): """ Return True if an effect of one action negates an effect of the other See Also -------- layers.ActionNode """ #------ TODO: implement this function ''' for x in actionA.effects: if x in actionB.effects: #print("ypu1 -> ",x," :: ", actionB.effects) #return True; print("-") for x in actionB.effects: if x in actionA.effects: #print("ypu2 -> ",x," :: ", actionA.effects) return True; ''' # print("--------",type(actionA.effects)) = <class 'frozenset'> # print("--------",type(actionA)) = <class 'layer.actionNode'> for x in actionA.effects: # print("--------",type(x in actionA.effect)) = <class 'aimacode.utils.expr'> # print("--------",type(x.op)) = <class 'str'> # print("--------",type(x.args)) = <class 'tuple'> for y in actionB.effects: #print("ypu3------> ",x," :: ", actionB.effects) #print("x= ",x) #print("x= ",expr(x)) #print("x.op",x.op ) #if(x.op!='~'): # print("x neg", Expr('~',x)) #print("x.arg---",x.args ) #print("x.arg",x.args[0] ) #print("y= ",y) #print("y.op",y.op ) #print("y.arg",y.args )''' if (x.op == '~' and y.op != '~'): #print("ypu") #print("x= ",x) #print("y= ",y) y_neg = Expr('~', y) #print("~y= ",y_neg) if y_neg.__eq__(x): #print(x, " = ", y_neg) return True if (y.op == '~' and x.op != '~'): x_neg = Expr('~', x) if x_neg.__eq__(y): #print(y, " = ", x_neg) return True return False
def get_relaxed_actions(self): ''' Strip preconditions. Strip effects unless a goal fluent. ''' from aimacode.utils import Expr relaxed = [] doAdd = False for a in self.actions_list: effect_add = [e for e in a.effect_add if e in self.goal] effect_rem = [e for e in a.effect_rem if e in self.goal] if not effect_add and not effect_rem: continue action = Action(Expr(a.name, *a.args), [[], []], [effect_add, effect_rem]) relaxed.append(action) return relaxed
def associate(op, args): """Given an associative op, return an expression with the same meaning as Expr(op, *args), but flattened -- that is, with nested instances of the same op promoted to the top level. >>> associate('&', [(A&B),(B|C),(B&C)]) (A & B & (B | C) & B & C) >>> associate('|', [A|(B|(C|(A&B)))]) (A | B | C | (A & B)) """ args = dissociate(op, args) if len(args) == 0: return _op_identity[op] elif len(args) == 1: return args[0] else: return Expr(op, *args)
def _negation(self, literalA, literalB): """ Return True if two literals are negations of each other """ # TODO: implement this function if literalA.op == "~" and literalB.op != "~": temp_neg = Expr("~", literalB) if temp_neg.__eq__(literalA): return True if literalA.op != "~" and literalB.op == "~": temp_neg = Expr("~", literalA) if temp_neg.__eq__(literalB): return True return False
def _negation(self, literalA, literalB): """ Return True if two literals are negations of each other """ if literalA.op == '~' and literalB.op!='~': temp_neg = Expr('~',literalB); if temp_neg.__eq__(literalA): return True if literalA.op != '~' and literalB.op=='~': temp_neg = Expr('~',literalA); if temp_neg.__eq__(literalB): return True return False
def move_not_inwards(s): """Rewrite sentence s by moving negation sign inward. >>> move_not_inwards(~(A | B)) (~A & ~B)""" s = expr(s) if s.op == '~': def NOT(b): return move_not_inwards(~b) a = s.args[0] if a.op == '~': return move_not_inwards(a.args[0]) # ~~A ==> A if a.op == '&': return associate('|', list(map(NOT, a.args))) if a.op == '|': return associate('&', list(map(NOT, a.args))) return s elif is_symbol(s.op) or not s.args: return s else: return Expr(s.op, *list(map(move_not_inwards, s.args)))
def eliminate_implications(s): "Change implications into equivalent form with only &, |, and ~ as logical operators." if s == False: s = expr("F") if s == True: s = expr("T") s = expr(s) if not s.args or is_symbol(s.op): return s # Atoms are unchanged. args = list(map(eliminate_implications, s.args)) a, b = args[0], args[-1] if s.op == '==>': return b | ~a elif s.op == '<==': return a | ~b elif s.op == '<=>': return (a | ~b) & (b | ~a) elif s.op == '^': assert len(args) == 2 # TODO: relax this restriction return (a & ~b) | (~a & b) else: assert s.op in ('&', '|', '~') return Expr(s.op, *args)
def _inconsistent_effects(self, actionA, actionB): """ Return True if an effect of one action negates an effect of the other See Also -------- layers.ActionNode """ # TODO: implement this function for x in actionA.effects: for y in actionB.effects: if x.op == "~" and y.op != "~": y_neg = Expr("~", y) if y_neg.__eq__(x): return True if y.op == "~" and x.op != "~": x_neg = Expr("~", x) if x_neg.__eq__(y): return True return False
def _negation(self, literalA, literalB): """ Return True if two literals are negations of each other """ # TODO: implement this function # raise NotImplementedError #print("----") #print("literal A = ",literalA," : args = ",literalA.args," : op = ", literalA.op) #print("literal B = ",literalB," : args = ",literalB.args," : op = ", literalB.op) if literalA.op == '~' and literalB.op != '~': temp_neg = Expr('~', literalB) #print("ned literalB",temp_neg); if temp_neg.__eq__(literalA): return True if literalA.op != '~' and literalB.op == '~': temp_neg = Expr('~', literalA) #print("ned literalA",temp_neg); if temp_neg.__eq__(literalB): return True return False
def _inconsistent_effects(self, actionA, actionB): """ Return True if an effect of one action negates an effect of the other See Also -------- layers.ActionNode """ #------ TODO: implement this function for x in actionA.effects: for y in actionB.effects: #check to see if actionA and action B are opposites... if (x.op =='~' and y.op!='~'): y_neg = Expr('~',y) if y_neg.__eq__(x): return True; if (y.op =='~' and x.op!='~'): x_neg = Expr('~',x) if x_neg.__eq__(y): return True; return False;
def _interference(self, actionA, actionB): """ Return True if the effects of either action negate the preconditions of the other See Also -------- layers.ActionNode """ # TODO: implement this function #raise NotImplementedError for x in actionA.effects: for y in actionB.preconditions: if (x.op == '~' and y.op != '~'): y_neg = Expr('~', y) if y_neg.__eq__(x): #print(x, " = ", y_neg); return True if (y.op == '~' and x.op != '~'): x_neg = Expr('~', x) if x_neg.__eq__(y): #print(y, " = ", x_neg); return True for x in actionB.effects: for y in actionA.preconditions: if (x.op == '~' and y.op != '~'): y_neg = Expr('~', y) if y_neg.__eq__(x): #print(x, " = ", y_neg); return True if (y.op == '~' and x.op != '~'): x_neg = Expr('~', x) if x_neg.__eq__(y): #print(y, " = ", x_neg); return True return False
def _interference(self, actionA, actionB): """ Return True if the effects of either action negate the preconditions of the other See Also -------- layers.ActionNode """ # TODO: implement this function #raise NotImplementedError for x in actionA.effects: for y in actionB.preconditions: #check to see if action A effects negates actionB preconditions if (x.op =='~' and y.op!='~'): y_neg = Expr('~',y); if y_neg.__eq__(x): return True; if (y.op =='~' and x.op!='~'): x_neg = Expr('~',x); if x_neg.__eq__(y): return True; for x in actionB.effects: for y in actionA.preconditions: #check to see if action B effects negates actionA preconditions if (x.op =='~' and y.op!='~'): y_neg = Expr('~',y); if y_neg.__eq__(x): return True; if (y.op =='~' and x.op!='~'): x_neg = Expr('~',x); if x_neg.__eq__(y): return True; return False;
def simp(x): "Simplify the expression x." if isnumber(x) or not x.args: return x args = list(map(simp, x.args)) u, op, v = args[0], x.op, args[-1] if op == '+': if v == 0: return u if u == 0: return v if u == v: return 2 * u if u == -v or v == -u: return 0 elif op == '-' and len(args) == 1: if u.op == '-' and len(u.args) == 1: return u.args[0] # --y ==> y elif op == '-': if v == 0: return u if u == 0: return -v if u == v: return 0 if u == -v or v == -u: return 0 elif op == '*': if u == 0 or v == 0: return 0 if u == 1: return v if v == 1: return u if u == v: return u**2 elif op == '/': if u == 0: return 0 if v == 0: return Expr('Undefined') if u == v: return 1 if u == -v or v == -u: return 0 elif op == '**': if u == 0: return 0 if v == 0: return 1 if u == 1: return 1 if v == 1: return u elif op == 'log': if u == 1: return 0 else: raise ValueError("Unknown op: " + op) # If we fall through to here, we can not simplify further return Expr(op, *args)
def ask_generator(self, query): "Yield the empty substitution {} if KB entails query; else no results." if tt_entails(Expr('&', *self.clauses), query): yield {}
def make_percept_sentence(self, percept, t): return Expr("Percept")(percept, t)
def make_action_sentence(self, action, t): return Expr("Did")(action[expr('action')], t)
from aimacode.utils import (removeall, unique, first, isnumber, issequence, Expr, expr, subexpressions) from aimacode.logic import * if __name__ == '__main__': expression = Expr('f', 'x', 1, 'y') print (expression.__repr__()) print (associate('&', dissociate('&', [x, y, z]))) list = [1, 3, 5] list.remove(3) print (list)
def _interference(self, actionA, actionB): """ Return True if the effects of either action negate the preconditions of the other See Also -------- layers.ActionNode """ # TODO: implement this function for x in actionA.effects: for y in actionB.preconditions: if x.op == "~" and y.op != "~": y_neg = Expr("~", y) if y_neg.__eq__(x): return True if y.op == "~" and x.op != "~": x_neg = Expr("~", x) if x_neg.__eq__(y): return True for x in actionB.effects: for y in actionA.preconditions: if x.op == "~" and y.op != "~": y_neg = Expr("~", y) if y_neg.__eq__(x): return True if y.op == "~" and x.op != "~": x_neg = Expr("~", x) if x_neg.__eq__(y): return True return False