예제 #1
0
def random_pdkb(depth, numAg, fluents, numRMLs, output=True):

    agents = list(range(1, numAg + 1))
    kb = PDKB(depth, agents, fluents)
    count = 0
    new_rmls = set()

    while count < numRMLs:
        rml = random_rml(depth, agents, fluents)
        if rml not in kb.rmls and neg(rml) not in kb.rmls:
            # Take advantage of the fact that we know the closure
            #  is just the union of the closure of each RML
            test_rmls = list(kd_closure(rml)) + [rml]
            cons = True
            for trml in test_rmls:
                if neg(trml) in kb.rmls:
                    cons = False

            if cons:
                if output:
                    print "Added %s" % rml
                for trml in test_rmls:
                    kb.add_rml(trml)
                new_rmls.add(rml)
                count += 1

    kb.rmls = new_rmls
    return kb
예제 #2
0
def convert_action(action, depth, agents, props, akprops):

    if str(action.dcond) == '(always)':
        act = Action(action.name, depth, agents, props, akprops, True)

    elif str(action.dcond) == '(never)':
        act = Action(action.name, depth, agents, props, akprops, False)

    elif action.dcond:
        act = Action(action.name, depth, agents, props, akprops,
                     parse_ma_cond(action.dcond))

    else:
        assert False, "Error for action %s. You need to specify the type of derived condition ('always', 'never', or 'custom')." % action.name

    assert isinstance(action.precondition, pdkb.pddl.formula.And)
    for pre in action.precondition.args:
        act.add_pre(prim2rml(pre),
                    negate=isinstance(pre, pdkb.pddl.formula.Not))

    def get_arg_list(form, objtype):
        if isinstance(form, objtype):
            return form.args
        else:
            return [form]

    #print dir(action)
    #['dcond', 'dump', 'effect', 'export', 'is_equal', 'name', 'observe', 'parameters', 'precondition']
    #['agent_list', 'args', 'dump', 'enforce_normalize', 'export', 'is_equal', 'name', 'normalize', 'predicate', 'to_ground']

    for nondet_eff in get_arg_list(action.effect, pdkb.pddl.formula.Oneof):

        act.new_nondet_effect()

        for eff in get_arg_list(nondet_eff, pdkb.pddl.formula.And):

            condp = PDKB(depth, agents, props)
            condn = PDKB(depth, agents, props)

            if isinstance(eff, pdkb.pddl.formula.When):
                for l in get_arg_list(eff.condition, pdkb.pddl.formula.And):
                    if isinstance(l, pdkb.pddl.formula.Not):
                        condn.add_rml(prim2rml(l))
                    else:
                        condp.add_rml(prim2rml(l))

                lit = prim2rml(eff.result)

                if isinstance(eff.result, pdkb.pddl.formula.Not):
                    act.add_neg_effect(condp, condn, lit)
                else:
                    act.add_pos_effect(condp, condn, lit)

            else:
                if isinstance(eff, pdkb.pddl.formula.Not):
                    act.add_neg_effect(condp, condn, prim2rml(eff))
                else:
                    act.add_pos_effect(condp, condn, prim2rml(eff))
    return act
예제 #3
0
def test3():
    kb = PDKB(1, [1], map(Literal, ['p', 'q']))

    l1 = Literal('p')
    l2 = Belief(1, Literal('q'))

    kb.add_rml(l1)
    kb.add_rml(l2)

    test_kripke(kb, [l1, l2])
예제 #4
0
def test2():

    kb = PDKB(1, [1], map(Literal, ['p', 'q']))

    l1 = neg(Literal('p'))
    l2 = Belief(1, Literal('p'))
    l3 = Belief(1, neg(Literal('q')))

    kb.add_rml(l1)
    kb.add_rml(l2)
    kb.add_rml(l3)

    test_kripke(kb, [l1, l2, l3])
예제 #5
0
def test5():
    kb = PDKB(2, [1,2], map(Literal, ['p', 'q']))

    rmls = [
        Literal('p'),
        Belief(1, Literal('q')),
        Belief(1, Belief(2, neg(Literal('q'))))
    ]

    for rml in rmls:
        kb.add_rml(rml)

    test_kripke(kb, rmls)
예제 #6
0
    def project_pre(self, ag):
        assert 0 == len(self.npre), "Cannot project when there is lack-of-belief preconditions"
        new_pre = PDKB(self.pre.depth, self.pre.agents, self.pre.props)
        for rml in self.pre:
            if rml.agent == ag:
                if isinstance(rml, Possible):
                    self.npre.add_rml(neg(rml.rml))
                elif isinstance(rml, Belief):
                    new_pre.add_rml(rml.rml)
                else:
                    assert False, "Trying to project a Literal?"

            else:
                new_pre.add_rml(rml)
        self.pre = new_pre
예제 #7
0
    def apply_effect(self, state, poseff, negeff):

        new_rmls = set([rml for rml in state.rmls])

        for condeff in negeff:
            if condeff.fires(state) and condeff.eff in new_rmls:
                new_rmls.remove(condeff.eff)

        for condeff in poseff:
            if condeff.fires(state):
                new_rmls.add(condeff.eff)

        new_state = PDKB(state.depth, state.agents, state.props)
        for rml in new_rmls:
            new_state.add_rml(rml)

        return new_state
예제 #8
0
def test1():
    print "\n----\n"

    l1 = Literal('p')
    l2 = Belief(2, Belief(1, l1))
    l3 = Belief(2, neg(Belief(1, neg(l1))))
    l4 = neg(l3)

    l5 = neg(Belief(1, neg(Belief(2, l1))))
    l6 = neg(Belief(1, neg(Belief(2, Possible(3, Belief(4, l1))))))

    print "KD closure operation:"
    print "%s -> %s" % (str(l2), str(map(str, kd_closure(l2))))
    print "%s -> %s" % (str(l3), str(map(str, kd_closure(l3))))

    print "\n----\n"

    kb = PDKB(2, [1,2], map(Literal, ['p', 'q']))
    kb.add_rml(l2)
    print "Initial KB:"
    print kb
    print "\nClosing..."
    kb.logically_close()
    print kb

    print "\n----\n"

    kb.add_rml(l4)
    print "Initial Closed KB:"
    kb.logically_close()
    print kb
    print "\nConsistent: %s" % str(kb.is_consistent())

    print "\n----\n"

    kb = PDKB(2, [1,2], map(Literal, ['p', 'q']))
    kb.add_rml(Belief(1, Literal('p')))
    kb.add_rml(Belief(2, Literal('q')))
    kb.add_rml(Belief(1, Belief(2, Literal('q'))))
    kb.add_rml(neg(Belief(1, Literal('q'))))
    print "Initial KB:"
    print kb
    print "\n...projecting on agent 1\n"
    print project(kb.rmls, 1)

    print "\n----\n"
예제 #9
0
def uncertain_changes(condeff, act):
    empty = PDKB(act.depth, act.agents, act.props)
    condn = PDKB(act.depth, act.agents, act.props)

    # Can't have an uncertain firing if there is no condition required
    if len(condeff.condp.rmls) == 0:
        return []

    for rml in condeff.condn.rmls:
        condn.add_rml(rml)

    for rml in condeff.condp.rmls:
        condn.add_rml(neg(rml))

    return [(False,
             CondEff(empty, condn, neg(condeff.eff), condeff.ma_cond,
                     ('uncertain_firing', 'pos', condeff)))]
예제 #10
0
    def project(self, ag, akprops):
        condp = PDKB(self.condp.depth, self.condp.agents, self.condp.props)
        condn = PDKB(self.condp.depth, self.condp.agents, self.condp.props)

        for rml in self.condp:
            if isinstance(rml, Possible):
                condn.add_rml(neg(rml.rml))
            elif isinstance(rml, Belief):
                condp.add_rml(rml.rml)
            elif rml.is_ak(akprops):
                condp.add_rml(rml)
            else:
                assert False, "Trying to project a Literal?"

        if isinstance(self.eff, Possible):
            return (False,
                    CondEff(condp, condn, neg(self.eff.rml), self.ma_cond,
                            self.reason))
        elif isinstance(self.eff, Belief):
            return (True,
                    CondEff(condp, condn, self.eff.rml, self.ma_cond,
                            self.reason))
        elif self.eff.is_ak(akprops):
            return (True,
                    CondEff(condp, condn, self.eff, self.ma_cond, self.reason))
        else:
            assert False, "Bad effect for projection?"
예제 #11
0
def parse_test_pdkb(fname):
    lines = read_file(fname)
    (depth, num_ag, props) = lines.pop(0).split(' ')

    depth = int(depth)
    num_ag = int(num_ag)
    props = props.split(',')

    assert 'B' not in props, "Error: Can't use 'B' as a proposition."
    assert num_ag < 10, "Error: Can't use more than 10 agents."

    def parse_rml(s):
        if '!' == s[0]:
            return neg(parse_rml(s[1:]))
        elif 'B' == s[0]:
            return Belief(int(s[1]), parse_rml(s[2:]))
        elif 'P' == s[0]:
            return Possible(int(s[1]), parse_rml(s[2:]))
        else:
            return Literal(s)

    rmls = [parse_rml(l.replace(' ', '')) for l in lines[:lines.index('END')]]

    desc = "\n".join(lines[lines.index('END') + 1:])
    if desc:
        print "Running test with the following description:"
        print "\n--------\n"
        print desc
        print "\n-----\n"

    kb = PDKB(depth, list(range(1, num_ag + 1)), map(Literal, props))

    for rml in rmls:
        kb.add_rml(rml)

    return rmls
    test_kripke(kb, rmls)
예제 #12
0
class Action(object):
    def __init__(self,
                 name,
                 depth,
                 agents,
                 props,
                 akprops,
                 derived_cond,
                 extra_ancillary=[]):
        self.name = name
        self.depth = depth
        self.agents = agents
        self.props = props
        self.akprops = akprops
        self.derived_cond = derived_cond

        self.pre = PDKB(depth, agents, props)
        self.npre = PDKB(depth, agents, props)
        self.effs = []

        # Detect all of the ancillary effects
        self.COMPILERS_POS = []
        self.COMPILERS_NEG = []

        for mod_name in ancillary.compute_modules() + extra_ancillary:
            mod = importlib.import_module(mod_name)
            self.COMPILERS_POS.extend(mod.COMPILERS_POS)
            self.COMPILERS_NEG.extend(mod.COMPILERS_NEG)

    def num_effs(self):
        count = 0
        for eff in self.effs:
            count += len(eff[0]) + len(eff[1])
        return count

    def applicable(self, state, agent=False):
        if DEBUG and not (self.pre.rmls <= state.rmls
                          and 0 == len(self.npre.rmls & state.rmls)):
            print("\nDEBUG: Action %s is not applicable" % self.name)
            print("Precondition:\n%s" % str(self.pre))
            print("State:\n%s\n" % str(state))
        return (self.pre.rmls <= state.rmls) and (0 == len(self.npre.rmls
                                                           & state.rmls))

    def possibly_applicable(self, state):
        assert False, "Not Implemented"

    def apply(self, state):
        return [self.apply_effect(state, eff[0], eff[1]) for eff in self.effs]

    def apply_effect(self, state, poseff, negeff):

        new_rmls = set([rml for rml in state.rmls])

        for condeff in negeff:
            if condeff.fires(state) and condeff.eff in new_rmls:
                new_rmls.remove(condeff.eff)

        for condeff in poseff:
            if condeff.fires(state):
                new_rmls.add(condeff.eff)

        new_state = PDKB(state.depth, state.agents, state.props)
        for rml in new_rmls:
            new_state.add_rml(rml)

        return new_state

    def expand(self, relevant_lits=None):
        relevant_lits = relevant_lits or set()
        for i in range(len(self.effs)):
            self.effs[i] = self._expand(self.effs[i][0], self.effs[i][1],
                                        relevant_lits)

    def project_effects(self, ag):
        for i in range(len(self.effs)):
            self.effs[i] = self._project(self.effs[i][0], ag)

    def project_pre(self, ag):
        assert 0 == len(
            self.npre
        ), "Cannot project when there is lack-of-belief preconditions"
        new_pre = PDKB(self.pre.depth, self.pre.agents, self.pre.props)
        for rml in self.pre:
            if rml.agent == ag:
                if isinstance(rml, Possible):
                    self.npre.add_rml(neg(rml.rml))
                elif isinstance(rml, Belief):
                    new_pre.add_rml(rml.rml)
                else:
                    assert False, "Trying to project a Literal?"

            else:
                new_pre.add_rml(rml)
        self.pre = new_pre

    def _expand(self, effp, effn, relevant_lits):

        # Because a negated condition can produce a positive (through belief closure)
        #  and a positive condition can produce a negative (through lack of knowledge),
        #  we need to keep a mix of both around for the closure.
        condleft = [(True, cond) for cond in effp] + [(False, cond)
                                                      for cond in effn]

        newposconds = set()
        newnegconds = set()

        while condleft:

            (is_pos, condeff) = condleft.pop(0)

            if is_pos and (condeff not in newposconds):
                if len(relevant_lits) == 0 or condeff.eff in relevant_lits:
                    newposconds.add(condeff)
                    for compiler in self.COMPILERS_POS:
                        condleft.extend(compiler(condeff, self))

            elif (not is_pos) and (condeff not in newnegconds):
                if len(relevant_lits) == 0 or condeff.eff in relevant_lits:
                    newnegconds.add(condeff)
                    for compiler in self.COMPILERS_NEG:
                        condleft.extend(compiler(condeff, self))

        return (list(newposconds), list(newnegconds))

    def _project(self, effp, ag):
        valid_effs = [x for x in effp if x.uniform(ag, self.akprops)]
        projected_effs = [eff.project(ag, self.akprops) for eff in valid_effs]
        newposconds = []
        newnegconds = []
        for (ispos, eff) in projected_effs:
            if ispos:
                newposconds.append(eff)
            else:
                newnegconds.append(eff)

        return (newposconds, newnegconds)

    def new_nondet_effect(self):
        self.effs.append((set(), set()))

    def add_pos_effect(self, condp, condn, lit, cond_ma_cond=False):
        self.effs[-1][0].add(CondEff(condp, condn, lit, cond_ma_cond))

    def add_neg_effect(self, condp, condn, lit, cond_ma_cond=False):
        self.effs[-1][1].add(CondEff(condp, condn, lit, cond_ma_cond))

    def add_pre(self, rml, negate=False):
        if negate:
            self.npre.add_rml(rml)
        else:
            self.pre.add_rml(rml)

    def pddl(self):
        toRet = "    (:action %s" % self.name
        toRet += "\n        :precondition (and %s)" % '\n                           '.join(
            ["(%s)" % rml.pddl() for rml in self.pre] +
            ["(not (%s))" % rml.pddl() for rml in self.npre])
        if len(self.effs) > 1:
            toRet += "\n\n        :effect (oneof %s)" % '\n\n\n                       '.join(["(and\n%s)" % '\n\n'.join([cond.pddl('                           ') for cond in eff[0]] + \
                                                                                                                        [cond.pddl('                           ', True) for cond in eff[1]]) for eff in self.effs])
        else:
            toRet += "\n        :effect (and\n%s)" % '\n\n'.join([cond.pddl('                    ') for cond in [i[1] for i in sorted([(e.id(), e) for e in self.effs[0][0]])]] + \
                                                                 [cond.pddl('                    ', True) for cond in [i[1] for i in sorted([(e.id(), e) for e in self.effs[0][1]])]])
        toRet += ")"
        return toRet
예제 #13
0
        'p',
        'q',
    ])))
    p3 = PDKB(2, [1, 2], list(map(Literal, [
        'p',
        'q',
    ])))
    p4 = PDKB(2, [1, 2], list(map(Literal, [
        'p',
        'q',
    ])))
    pempty = PDKB(2, [1, 2], list(map(Literal, [
        'p',
        'q',
    ])))
    p1.add_rml(Belief(1, Literal('p')))
    p1.add_rml(Belief(1, Possible(2, neg(Literal('p')))))
    lit = Belief(2, Literal('q'))
    p2.add_rml(Belief(2, Literal('q')))
    p3.add_rml(Literal('p'))
    p4.add_rml(Literal('q'))

    a.add_pos_effect(p3, pempty, Literal('q'))
    a.add_pos_effect(p1, pempty, lit)
    a.new_nondet_effect()
    a.add_neg_effect(pempty, p1, lit)
    a.add_pos_effect(p1, pempty, lit)

    print(a.pddl())
    print()
예제 #14
0
class Problem(object):
    def __init__(self):
        self.domain = None

    def parse_parts(self, prob):
        self.parse_projection(prob)
        self.parse_init(prob)
        self.parse_goal(prob)

    def parse_projection(self, prob):
        assert 'projection' in dir(prob)
        self.agent_projection = list(reversed(prob.projection))

    def parse_init(self, prob):

        self.init = PDKB(self.domain.depth, self.domain.agents,
                         self.domain.props)

        assume_closed = False
        if prob.init_type == 'complete':
            assume_closed = True

        assert isinstance(prob.init, pdkb.pddl.formula.And)

        for prim in prob.init.args:
            init_rmls = [prim2rml(prim, False)]
            for t in prob.types:
                going = True
                while going:
                    new_init_rmls = []
                    going = False
                    for old_init_rml in init_rmls:
                        if "$%s$" % t not in old_init_rml:
                            new_init_rmls.append(old_init_rml)
                        else:
                            going = True
                            for v in prob.type_to_obj[t]:
                                # Only do a single split so we can reuse the same variable type
                                lside = old_init_rml[:old_init_rml.
                                                     index("$%s$" % t)]
                                rside = old_init_rml[old_init_rml.
                                                     index("$%s$" % t) +
                                                     len("$%s$" % t):]
                                new_init_rmls.append(lside + v + rside)
                    init_rmls = new_init_rmls
            for rml_line in init_rmls:
                self.init.add_rml(parse_rml(rml_line))

        # Close the initial state
        self.init.logically_close()

        if assume_closed:
            self.init.close_omniscience()

        assert self.init.is_consistent(), "Error: Inconsistent initial state"

    def parse_goal(self, prob):

        self.goal = PDKB(self.domain.depth, self.domain.agents,
                         self.domain.props)

        assert isinstance(prob.goal, pdkb.pddl.formula.And)

        for g in prob.goal.args:
            self.goal.add_rml(prim2rml(g))
예제 #15
0
def commonly_known_effect(condeff,
                          agents,
                          depth,
                          props,
                          akprops,
                          posneg,
                          schema,
                          negated=False):

    if (schema is False) or (condeff.depth >= depth):
        return []

    condeffs = []

    if schema is True:
        schema = [[], []]

    if condeff.ma_cond:
        schema[0].extend(condeff.ma_cond[0])
        schema[1].extend(condeff.ma_cond[1])

    for ag in agents:

        # We can't remove belief we don't have.
        # E.g., (-) p -> B1 q and (-) p -> !B1 q together state that
        #       when p holds, we're not sure if 1 believes q or not.
        #       When introspecting for agent 1, it doesn't make sense
        #       to try and consider (+) B1 p -> !B1 !B1 q as that would
        #       make (+) B1 p -> B1 q, which when projected would be
        #       (+) p -> q. Definitely an undesired result.
        #if ag == condeff.eff.agent and isinstance(condeff.eff, Not) and negated:
        if ag == condeff.eff.agent and negated:
            #print "Warning: Ignoring the commonly known extension for the following conditional effect:\n%s" % str(condeff)
            continue

        condp = PDKB(depth, agents, props)
        condn = PDKB(depth, agents, props)

        for rml in condeff.condp:
            if rml.is_lit() and rml.is_ak(akprops):
                condp.add_rml(rml)
            else:
                condp.add_rml(Belief(ag, rml).merge_modalities())
        for rml in condeff.condn:
            if rml.is_lit() and rml.is_ak(akprops):
                condp.add_rml(neg(rml))
            else:
                condp.add_rml(neg(Belief(ag, rml)).merge_modalities())

        for rmlscheme in schema[0]:
            rml = parse_rml(ag.join(rmlscheme.split('?')))
            if rml.is_lit() and rml.is_ak(akprops):
                condp.add_rml(rml)
            else:
                condp.add_rml(Belief(ag, rml).merge_modalities())
        for rmlscheme in schema[1]:
            rml = parse_rml(ag.join(rmlscheme.split('?')))
            if rml.is_lit() and rml.is_ak(akprops):
                condp.add_rml(rml)
            else:
                condp.add_rml(neg(Belief(ag, rml)).merge_modalities())

        if condeff.eff.is_ak(akprops):
            new_eff = condeff.eff
        else:
            new_eff = Belief(ag, condeff.eff).merge_modalities()

        if negated:
            new_eff = neg(new_eff)

        # Only add the new conditional effect if it is different (this may not
        #  be the case if there was some introspection removed)
        new_cond = CondEff(condp, condn, new_eff, condeff.ma_cond,
                           ('commonly_known', posneg, condeff))
        if new_cond != condeff:
            condeffs.append((True, new_cond))

    return condeffs