Exemple #1
0
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)
    return Expr(op, *args)
Exemple #2
0
    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 atleast one of the transition 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)
Exemple #3
0
def standardize_variables(sentence, dic=None):
    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])
Exemple #4
0
def diff(y, x):
    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))
Exemple #5
0
 def refinements(
         hla, state, library
 ):  # TODO - refinements may be (multiple) HLA themselves ...
     """
     state is a Problem, containing the current state kb
     library is a dictionary containing details for every possible refinement. eg:
     {
     "HLA": [
         "Go(Home,SFO)",
         "Go(Home,SFO)",
         "Drive(Home, SFOLongTermParking)",
         "Shuttle(SFOLongTermParking, SFO)",
         "Taxi(Home, SFO)"
            ],
     "steps": [
         ["Drive(Home, SFOLongTermParking)", "Shuttle(SFOLongTermParking, SFO)"],
         ["Taxi(Home, SFO)"],
         [], # empty refinements ie primitive action
         [],
         []
            ],
     "precond_pos": [
         ["At(Home), Have(Car)"],
         ["At(Home)"],
         ["At(Home)", "Have(Car)"]
         ["At(SFOLongTermParking)"]
         ["At(Home)"]
                    ],
     "precond_neg": [[],[],[],[],[]],
     "effect_pos": [
         ["At(SFO)"],
         ["At(SFO)"],
         ["At(SFOLongTermParking)"],
         ["At(SFO)"],
         ["At(SFO)"]
                   ],
     "effect_neg": [
         ["At(Home)"],
         ["At(Home)"],
         ["At(Home)"],
         ["At(SFOLongTermParking)"],
         ["At(Home)"]
                   ]
     }
     """
     e = Expr(hla.name, hla.args)
     indices = [
         i for i, x in enumerate(library["HLA"]) if expr(x).op == hla.name
     ]
     for i in indices:
         action = HLA(
             expr(library["steps"][i][0]),
             [  # TODO multiple refinements
                 [expr(x) for x in library["precond_pos"][i]],
                 [expr(x) for x in library["precond_neg"][i]]
             ],
             [[expr(x) for x in library["effect_pos"][i]],
              [expr(x) for x in library["effect_neg"][i]]])
         if action.check_precond(state.kb, action.args):
             yield action
Exemple #6
0
def S_generator(n, m, k, q):
    """
    :param n: the number of distinct propositional symbols in S
    :param m: the number of clauses in S
    :param k: the maximum number of literals in a clause in S
    :param q: 0.4 <= q <= 0.6, q is the probability that a literal in a
    clause in a negative literal
    :return: a random set of clauses
    """
    if q < 0.4 or q > 0.6:
        raise ValueError("q should be between 0.4 and 0.6(inclusive)")
    letters = string.ascii_uppercase
    len_letters = len(letters)
    if n > len_letters:
        raise ValueError("n should be less than or equal to " +
                         str(len_letters))
    unique_symbols = list()
    for i in range(n):
        unique_symbols.append(Expr(letters[i]))
    S = list()
    for i in range(m):
        n_lt = random.randint(1, k)
        clause = None
        for j in range(n_lt):
            idx = random.randint(0, n - 1)
            sym = unique_symbols[idx]
            if probability(q):
                sym = sym.__invert__()
            if clause is None:
                clause = sym
            else:
                clause = clause.__or__(sym)
        S.append(clause)
    print("clauses S: " + str(S) + "\n")
    return S
Exemple #7
0
 def substitute(self, e, args):
     """Replaces variables in expression with their respective Propostional symbol"""
     new_args = [
         args[i] for x in e.args for i in range(len(self.args))
         if self.args[i] == x
     ]
     return Expr(e.op, *new_args)
Exemple #8
0
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))
Exemple #9
0
 def substitute(self, e, args):
     """Replaces variables in expression with their respective Propostional symbol"""
     new_args = list(e.args)
     for num, x in enumerate(e.args):
         for i in range(len(self.args)):
             if self.args[i] == x:
                 new_args[num] = args[i]
     return Expr(e.op, *new_args)
Exemple #10
0
    def translate_to_SAT(init, transition, goal, time):
        clauses = []
        states = [state for state in transition]

        state_counter = itertools.count()
        for s in states:
            for t in range(time + 1):
                state_sym[s, t] = Expr("State_{}".format(next(state_counter)))

        clauses.append(state_sym[init, 0])

        clauses.append(state_sym[goal, time])

        transition_counter = itertools.count()
        for s in states:
            for action in transition[s]:
                s_ = transition[s][action]
                for t in range(time):
                    action_sym[s, action, t] = Expr("Transition_{}".format(
                        next(transition_counter)))

                    clauses.append(action_sym[s, action, t] | '==>'
                                   | state_sym[s, t])
                    clauses.append(action_sym[s, action, t] | '==>'
                                   | state_sym[s_, t + 1])

        for t in range(time + 1):
            clauses.append(associate('|', [state_sym[s, t] for s in states]))

            for s in states:
                for s_ in states[states.index(s) + 1:]:
                    clauses.append((~state_sym[s, t]) | (~state_sym[s_, t]))

        for t in range(time):
            transitions_t = [tr for tr in action_sym if tr[2] == t]

            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:]:
                    clauses.append(~action_sym[tr] | ~action_sym[tr_])

        return associate('&', clauses)
Exemple #11
0
    def build(self, actions, objects):
        """Populates the lists and dictionaries containing the state action dependencies"""

        for clause in self.current_state:
            p_expr = Expr('P' + clause.op, *clause.args)
            self.current_action_links[p_expr] = [clause]
            self.next_action_links[p_expr] = [clause]
            self.current_state_links[clause] = [p_expr]
            self.next_state_links[clause] = [p_expr]

        for a in actions:
            num_args = len(a.args)
            possible_args = tuple(itertools.permutations(objects, num_args))

            for arg in possible_args:
                if a.check_precond(self.kb, arg):
                    for num, symbol in enumerate(a.args):
                        if not symbol.op.islower():
                            arg = list(arg)
                            arg[num] = symbol
                            arg = tuple(arg)

                    new_action = a.substitute(Expr(a.name, *a.args), arg)
                    self.current_action_links[new_action] = []

                    for clause in a.precond:
                        new_clause = a.substitute(clause, arg)
                        self.current_action_links[new_action].append(new_clause)
                        if new_clause in self.current_state_links:
                            self.current_state_links[new_clause].append(new_action)
                        else:
                            self.current_state_links[new_clause] = [new_action]
                   
                    self.next_action_links[new_action] = []
                    for clause in a.effect:
                        new_clause = a.substitute(clause, arg)

                        self.next_action_links[new_action].append(new_clause)
                        if new_clause in self.next_state_links:
                            self.next_state_links[new_clause].append(new_action)
                        else:
                            self.next_state_links[new_clause] = [new_action]
Exemple #12
0
def subst(s, x):
    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])
Exemple #13
0
def associate(op, args):
    # Given an associative op, return an expression with the same
    #  meaning as Expr(op, *args)

    args = dissociate(op, args)
    if len(args) == 0:
        return _op_identity[op]
    elif len(args) == 1:
        return args[0]
    else:
        return Expr(op, *args)
Exemple #14
0
    def find_mutex(self):
        """Finds mutually exclusive actions"""

        # Inconsistent effects
        pos_nsl, neg_nsl = self.separate(self.next_state_links)

        for negeff in neg_nsl:
            new_negeff = Expr(negeff.op[3:], *negeff.args)
            for poseff in pos_nsl:
                if new_negeff == poseff:
                    for a in self.next_state_links[poseff]:
                        for b in self.next_state_links[negeff]:
                            if {a, b} not in self.mutex:
                                self.mutex.append({a, b})

        # Interference will be calculated with the last step
        pos_csl, neg_csl = self.separate(self.current_state_links)

        # Competing needs
        for posprecond in pos_csl:
            for negprecond in neg_csl:
                new_negprecond = Expr(negprecond.op[3:], *negprecond.args)
                if new_negprecond == posprecond:
                    for a in self.current_state_links[posprecond]:
                        for b in self.current_state_links[negprecond]:
                            if {a, b} not in self.mutex:
                                self.mutex.append({a, b})

        # Inconsistent support
        state_mutex = []
        for pair in self.mutex:
            next_state_0 = self.next_action_links[list(pair)[0]]
            if len(pair) == 2:
                next_state_1 = self.next_action_links[list(pair)[1]]
            else:
                next_state_1 = self.next_action_links[list(pair)[0]]
            if (len(next_state_0) == 1) and (len(next_state_1) == 1):
                state_mutex.append({next_state_0[0], next_state_1[0]})
        
        self.mutex = self.mutex + state_mutex
Exemple #15
0
    def act(self, kb, args):
        """Executes the action on the state's knowledge base"""

        if isinstance(kb, list):
            kb = FolKB(kb)

        if not self.check_precond(kb, args):
            raise Exception('Action pre-conditions not satisfied')
        for clause in self.effect:
            kb.tell(self.substitute(clause, args))
            if clause.op[:3] == 'Not':
                new_clause = Expr(clause.op[3:], *clause.args)

                if kb.ask(self.substitute(new_clause, args)) is not False:
                    kb.retract(self.substitute(new_clause, args))
            else:
                new_clause = Expr('Not' + clause.op, *clause.args)

                if kb.ask(self.substitute(new_clause, args)) is not False:    
                    kb.retract(self.substitute(new_clause, args))

        return kb
Exemple #16
0
def distribute_and_over_or_withbug(s):
    """Given a sentence s consisting of conjunctions and disjunctions
    of literals, return an equivalent sentence in CNF.
    >>> distribute_and_over_or((A & B) | C)
    ((A | B) & (B | C))
    """
    s = expr(s)
    if not isinstance(s, Expr):
        return s
    #firstParseArgs = tuple([distribute_and_over_or(arg) for arg in s.args])
    #s = Expr(s.op, firstParseArgs)
    if s.op == '|':
        for subarg in s.args:
            if subarg.op == '&':
                otherArgs = [
                    otherArg for otherArg in s.args if otherArg != subarg]

                newArgs = []
                if len(otherArgs) > 1:
                    otherExpr = Expr('|', tuple(otherArgs))
                    for t in subarg.args:
                        newArgs.append(Expr('|', t, otherExpr))
                else:
                    otherExpr = otherArgs[0]
                    for t in subarg.args:
                        newArgs.append(Expr('|', t, otherExpr))

                toReturn = Expr('&')
                toReturn.args = tuple(newArgs)
                return toReturn
    else:
        newArgs = []
        for subarg in s.args:
            newArgs.append(distribute_and_over_or(subarg))
        s.args = tuple(newArgs)
    return s
Exemple #17
0
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])
Exemple #18
0
def associate(op, args):
    """Dada uma op associativa, retornar uma expressão com o mesmo
     significado como Expr (op, * args), ou seja, com instâncias aninhadas
     do mesmo grupo promovido ao nível superior.
    >>> 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)
Exemple #19
0
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)
Exemple #20
0
def eliminate_implications(s):
    "Altera as implicações em forma equivalente com apenas &, |, e ~ como operadores lógicos."
    s = expr(s)
    if not s.args or is_symbol(s.op):
        return s
    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
        return (a & ~b) | (~a & b)
    else:
        assert s.op in ('&', '|', '~')
        return Expr(s.op, *args)
Exemple #21
0
def eliminate_implications(s):
    """Change implications into equivalent form with only &, |, and ~ as logical operators."""
    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)
Exemple #22
0
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)))
Exemple #23
0
def move_not_inwards(s):
    """Reescreva sentenças s movendo sinal de negação.
    >>> 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)))
Exemple #24
0
    def build(self, actions, objects):

        #Add persistence actions for positive states
        for clause in self.current_state_pos:
            self.current_action_links_pos[Expr('Persistence',
                                               clause)] = [clause]
            self.next_action_links[Expr('Persistence', clause)] = [clause]
            self.current_state_links_pos[clause] = [
                Expr('Persistence', clause)
            ]
            self.next_state_links_pos[clause] = [Expr('Persistence', clause)]

        #Add persistence actions for negative states
        for clause in self.current_state_neg:
            self.current_action_links_neg[Expr(
                'Persistence', Expr('not' + clause.op,
                                    clause.args))] = [clause]
            self.next_action_links[Expr('Persistence',
                                        Expr('not' + clause.op,
                                             clause.args))] = [clause]
            self.current_state_links_neg[clause] = [
                Expr('Persistence', Expr('not' + clause.op, clause.args))
            ]
            self.next_state_links_neg[clause] = [
                Expr('Persistence', Expr('not' + clause.op, clause.args))
            ]

        for a in actions:
            num_args = len(a.args)
            possible_args = tuple(itertools.permutations(objects, num_args))

            for arg in possible_args:
                if a.check_precond(self.poskb, arg):
                    for num, symbol in enumerate(a.args):
                        if not symbol.op.islower():
                            arg = list(arg)
                            arg[num] = symbol
                            arg = tuple(arg)

                    new_action = a.substitute(Expr(a.name, *a.args), arg)
                    self.current_action_links_pos[new_action] = []
                    self.current_action_links_neg[new_action] = []

                    for clause in a.precond_pos:
                        new_clause = a.substitute(clause, arg)
                        self.current_action_links_pos[new_action].append(
                            new_clause)
                        if new_clause in self.current_state_links_pos:
                            self.current_state_links_pos[new_clause].append(
                                new_action)
                        else:
                            self.current_state_links_pos[new_clause] = [
                                new_action
                            ]

                    for clause in a.precond_neg:
                        new_clause = a.substitute(clause, arg)
                        #new_clause = Expr('not'+new_clause.op, new_clause.arg)
                        self.current_action_links_neg[new_action].append(
                            new_clause)
                        if new_clause in self.current_state_links_neg:
                            self.current_state_links_neg[new_clause].append(
                                new_action)
                        else:
                            self.current_state_links_neg[new_clause] = [
                                new_action
                            ]

                    self.next_action_links[new_action] = []
                    for clause in a.effect_add:
                        new_clause = a.substitute(clause, arg)
                        self.next_action_links[new_action].append(new_clause)
                        if new_clause in self.next_state_links_pos:
                            self.next_state_links_pos[new_clause].append(
                                new_action)
                        else:
                            self.next_state_links_pos[new_clause] = [
                                new_action
                            ]

                    for clause in a.effect_rem:
                        new_clause = a.substitute(clause, arg)
                        self.next_action_links[new_action].append(new_clause)
                        if new_clause in self.next_state_links_neg:
                            self.next_state_links_neg[new_clause].append(
                                new_action)
                        else:
                            self.next_state_links_neg[new_clause] = [
                                new_action
                            ]
Exemple #25
0
 def ask_generator(self, query):
     """Yield the empty substitution {} if KB entails query; else no results."""
     if tt_entails(Expr('&', *self.clauses), query):
         yield {}
Exemple #26
0
def implies_and_implies(lhs, rhs):
    return Expr('<=>', lhs, rhs)
Exemple #27
0
def implies(lhs, rhs):
    return Expr('==>', lhs, rhs)
Exemple #28
0
def location(x, y, time=None):
    if time is None:
        return Expr('L', x, y)
    else:
        return Expr('L', x, y, time)
Exemple #29
0
def ok_to_move(x, y, time):
    return Expr('OK', x, y, time)
Exemple #30
0
def turn_right(time):
    return Expr('TurnRight', time)
Exemple #31
0
def turn_left(time):
    return Expr('TurnLeft', time)