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
def test_expand(kb1, kb2): l1 = Literal('p') l2 = Belief(2, Belief(1, l1)) l3 = Belief(2, neg(Belief(1, neg(l1)))) l4 = neg(l3) kb1.expand(set([l1, l2, l3, l4])) kb2.add_rml(l1) kb2.add_rml(l2) kb2.add_rml(l3) kb2.add_rml(l4) assert kb1.size() == kb2.size() l5 = Possible(2, Possible(1, l1)) assert kb1.query(l5) assert kb2.query(l5) l6 = Possible(1, l1) assert kb1.query(l6) == (AxiomSystem.SYSTEM == KT), "KB = %s\nSystem = %s" % (kb1, AxiomSystem.SYSTEM) kb2.remove_rml(l1) kb2.remove_rml(l2) kb2.remove_rml(l3) kb2.remove_rml(l4) kb1.contract(set([l1, l2, l3, l4])) assert not kb1.query(l1) assert not kb2.query(l1)
def test13(): print "-- START TEST 13 --" AxiomSystem.SYSTEM = KD l1 = Belief(1, Belief(2, Literal('p'))) l2 = Belief(1, Possible(2, Literal('p'))) l3 = Possible(2, Literal('p')) l4 = Belief(1, Literal('p')) assert l1.kd_entails_rml(l2) assert not l1.kd_entails_rml(l3) assert not l1.kd_entails_rml(l4) assert l1.kt_entails_rml(l2) assert l1.kt_entails_rml(l3) assert l1.kt_entails_rml(l4) l5 = Belief(1, Possible(3, Literal('p'))) assert not l1.kt_entails_rml(l5) l6 = Possible(1, Belief(2, Literal('p'))) assert not l6.kt_entails_rml(l1) l7 = Possible(1, Literal('p')) assert l6.kt_entails_rml(l7) AxiomSystem.SYSTEM = KT l1 = Belief(2, Belief(1, Possible(2, neg(Literal('r'))))) l2 = Possible(2, neg(Literal('r'))) assert l1.kt_entails_rml(l2) print "-- END TEST 13 --"
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?"
def is_consistent(self): # Check if there is anything obviously inconsistent for rml in self.rmls: if neg(rml) in self.rmls: for r in self.rmls: if r == neg(rml): #print "%s <=/=> %s" % (rml, r) pass return False return True
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])
def unclose_literal(condeff, act): # unclose just follows the above process but uses the contrapositive to_ret = [] to_close = [neg(condeff.eff)] seen = set() while to_close: rml = to_close.pop(0) if rml not in seen: seen.add(rml) to_ret.append((False, CondEff(condeff.condp.copy(), condeff.condn.copy(), neg(rml), condeff.ma_cond, ('unclosure', 'neg', condeff)))) to_close.extend(kd_closure(rml)) return to_ret
def test11(): print "-- START TEST 11 --" # Test helper functions AxiomSystem.SYSTEM = KD p = Belief(2, Belief(1, Literal('p'))) q = Possible(2, Possible(1, Literal('p'))) sub = sub_lattice(p, q) assert len(sub) == 4, "len(%s) == %d" % (str(sub), len(sub)) assert p in sub assert q in sub assert not any(r for r in sub if r.entails_rml(p) and r != p) assert all(r for r in sub if r.entails_rml(q)) assert Belief(2, Possible(1, Literal('p'))) in sub assert Possible(2, Belief(1, Literal('p'))) in sub p = Belief(5, Possible(4, Belief(3, Belief(2, Belief(1, neg(Literal('p'))))))) q = Possible(5, Possible(4, Belief(3, Possible(2, Possible(1, neg(Literal('p'))))))) sub = sub_lattice(p, q) assert len(sub) == 8, "len(%s) == %d" % (str(sub), len(sub)) assert p in sub assert q in sub assert not any(r for r in sub if r.entails_rml(p) and r != p) assert all(r for r in sub if r.entails_rml(q)) assert Possible(5, Possible(4, Belief(3, Possible(2, Belief(1, neg(Literal('p'))))))) in sub assert Belief(5, Belief(4, Belief(3, Belief(2, Belief(1, neg(Literal('p'))))))) not in sub # Switch to axiom system KT AxiomSystem.SYSTEM = KT p = Belief(1, Belief(2, Literal('p'))) q = Possible(2, Literal('p')) sub = sub_lattice(p, q) assert len(sub) == 4, "len(%s) == %d" % (str(sub), len(sub)) assert p in sub assert q in sub assert not any(r for r in sub if r.entails_rml(p) and r != p) assert all(r for r in sub if r.entails_rml(q)) assert Belief(1, Possible(2, Literal('p'))) in sub assert Belief(2, Literal('p')) in sub p = Belief(1, Possible(2, Belief(3, Belief(4, neg(Literal('p')))))) q = Possible(2, neg(Literal('p'))) sub = sub_lattice(p, q) assert len(sub) == 8, "len(%s) == %d" % (str(sub), len(sub)) assert p in sub assert q in sub assert not any(r for r in sub if r.entails_rml(p) and r != p) assert all(r for r in sub if r.entails_rml(q)) assert Possible(2, Belief(3, Belief(4, neg(Literal('p'))))) in sub assert Possible(2, Belief(4, neg(Literal('p')))) in sub assert Possible(2, Possible(3, neg(Literal('p')))) not in sub print "-- END TEST 11 --\n"
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)))]
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)
def test_consistency(pdkb, kb): assert isinstance(pdkb, PDKB) l1 = Literal('p') l2 = Belief(1, Belief(2, l1)) l3 = Possible(3, Belief(2, Belief(1, neg(l1)))) l4 = Belief(2, Possible(1, Belief(3, Belief(1, Literal('p'))))) pdkb.expand(set([l1, l2, l3, l4])) kb.expand(set([l1, l2, l3, l4])) compare(pdkb, kb) l5 = neg(l3) pdkb.update(set([l5])) kb.update(set([l5])) compare(pdkb, kb)
def test14(): print "-- START TEST 14 --" for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system p = Literal('p') q = Literal('q') assert p.inconsistent(neg(p)) assert not p.inconsistent(neg(q)) assert not p.inconsistent(q) b1p = Belief(1, p) b2p = Belief(2, p) b2np = Belief(2, neg(p)) p1np = Possible(1, neg(p)) p2np = Possible(2, neg(p)) p2p = Possible(2, p) assert b1p.inconsistent(p1np) assert p1np.inconsistent(b1p) assert not b1p.inconsistent(b2p) assert not b2p.inconsistent(b1p) assert b2p.inconsistent(b2np) assert b2np.inconsistent(b2p) assert (b1p.inconsistent(b2np) == (axiom_system in [KT, S5])), ax_system() assert (b2np.inconsistent(b1p) == (axiom_system in [KT, S5])), ax_system() assert not b1p.inconsistent(p2np) assert not p2np.inconsistent(b1p) assert not p1np.inconsistent(p2np) assert not p2np.inconsistent(p1np) assert not p2np.inconsistent(p2p) assert (b1p.inconsistent(neg(p)) == (axiom_system in [KT, S5])), ax_system() assert (neg(p).inconsistent(b1p) == (axiom_system in [KT, S5])), ax_system() assert not p1np.inconsistent(p) assert not p.inconsistent(p1np) b2b1p = Belief(2, b1p) b2p1np = Belief(2, p1np) assert b2b1p.inconsistent(b2p1np), ax_system() assert b2p1np.inconsistent(b2b1p), ax_system() assert (b1p.inconsistent(b2p1np) == (axiom_system in [KT, S5])), ax_system() assert (b2p1np.inconsistent(b1p) == (axiom_system in [KT, S5])), ax_system() assert not b2p.inconsistent(Possible(3, neg(p))), ax_system() assert b2p.inconsistent(Possible(2, Belief(1, neg(p)))) == (axiom_system in [KT, S5]), ax_system() print "-- END TEST 14 --"
def test_update(kb): l1 = Belief(1, Belief(2, Literal('p'))) l2 = Belief(1, Belief(2, Literal('q'))) kb.update(set([l1, l2])) assert kb.is_consistent(), str(kb) assert kb.query(l1) assert kb.query(l2) l3 = Possible(1, Possible(2, neg(Literal('p')))) l4 = Belief(1, Possible(2, Literal('p'))) kb.update(set([l3])) assert kb.is_consistent(), str(kb) assert not kb.query(l1) assert kb.query(l2) assert kb.query(l3) assert kb.query(l4) assert kb.is_consistent(), str(kb) l5 = Belief(3, neg(Literal('r'))) kb.update(set([l5])) l6 = Belief(3, Literal('r')) kb.update(set([l6])) assert not kb.query(l5) assert kb.query(l6) assert kb.query(Possible(3, Literal('r'))) AxiomSystem.SYSTEM = KT kb.reset() kb.update(set([Belief(1, Belief(2, Literal('p')))])) p1 = Possible(2, Belief(1, neg(Literal('p')))) p2 = Possible(3, neg(Literal('p'))) kb.update(set([p1, p2])) q = Literal('p') assert kb.query(q) == (AxiomSystem.SYSTEM in [KT, S5]) assert kb.is_consistent(), str(kb)
def random_rml(depth, agents, fluents): b = random.choice(fluents) d = random.randint(0, depth) def coin(): return random.choice([True, False]) if coin(): b = neg(b) for i in range(d): if b.is_lit(): options = agents else: options = list(set(agents) - set([b.agent])) b = Belief(random.choice(options), b) if coin(): b = neg(b) return b
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)
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 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"
def perspectival_view(self, allow_repeat=False): def no_repeats(rml): if rml.is_lit(): return True elif rml.agent == rml.rml.agent: return False else: return no_repeats(rml.rml) if allow_repeat: all_rmls = self.all_rmls else: all_rmls = filter(no_repeats, self.all_rmls) CW = set() for rml in all_rmls: if rml in self.rmls: CW.add(Belief(0, rml)) else: CW.add(Possible(0, neg(rml))) return CW
def perspectival_view(self, allow_repeat=False, root_agent=0): """Returns the set of RMLs from the perspective of the root agent.""" def no_repeats(rml): if rml.is_lit(): return True elif rml.agent == rml.rml.agent: return False else: return no_repeats(rml.rml) if allow_repeat: all_rmls = self.all_rmls else: all_rmls = list(filter(no_repeats, self.all_rmls)) CW = set() for rml in all_rmls: if rml in self.rmls: CW.add(Belief(root_agent, rml)) else: CW.add(Possible(root_agent, neg(rml))) return CW
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
def is_omniscient(self): for rml in self.all_rmls: if (rml not in self.rmls) and (neg(rml) not in self.rmls): return False return True
'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() a.expand()
def project(rmls, ag): belief_rmls = [x for x in rmls if isinstance(x, Belief)] return set([rml.rml for rml in filter_agent(belief_rmls, ag)]) CLOSURE = dict([(KD, [kd_closure]), (KT, [kt_closure, kd_closure]), (KD45, [kd_closure]), (S5, [kt_closure, kd_closure])]) if __name__ == '__main__': print("\n----\n") l1 = Literal('p') l2 = Belief(2, Belief(1, l1)) l3 = Belief(2, neg(Belief(1, neg(l1)))) l4 = neg(l3) print("%s -> %s" % (str(l2), str(list(map(str, kd_closure(l2)))))) print("%s -> %s" % (str(l3), str(list(map(str, kd_closure(l3)))))) print("\n----\n") kb = PDKB(2, [1, 2], list(map(Literal, ['p', 'q']))) kb.add_rml(l2) print(kb) kb.logically_close() print(kb) print("\n----\n") kb.add_rml(l4)
def negated_changes(condeff, act): return [(False, CondEff(condeff.condp.copy(), condeff.condn.copy(), neg(condeff.eff), condeff.ma_cond, ('negation-removal', 'pos', condeff)))]
def close_omniscience(self): """Puts the KB into a form that everything is either believed or it's negation is.""" for rml in self.all_rmls: if isinstance(rml, Possible) and neg(rml) not in self.rmls: self.add_rml(rml)
def _generate_kripke(self, M, rmls, DEBUG=''): if DEBUG: DEBUG += ' ' if DEBUG: print("\n\n%sGenerating for rmls: %s" % (DEBUG, str(rmls))) if 0 == len(rmls): return set() assert all([not rml.is_lit() for rml in rmls]) cur_ag = list(rmls)[0].agent assert all([cur_ag == rml.agent for rml in rmls]) all_new_worlds = set() # Split the rmls into universal belief (B \phi) and existential (P \phi) # and strip the initial modal operator universal_rmls = set( [rml.rml for rml in [x for x in rmls if isinstance(x, Belief)]]) existential_rmls = set([rml.rml for rml in (rmls - universal_rmls)]) assert all([ cur_ag != rml.agent for rml in [x for x in universal_rmls | existential_rmls if not x.is_lit()] ]) # lits will be the literals that must hold in all worlds lits = set([x for x in universal_rmls if x.is_lit()]) props = set([x.get_prop() for x in lits]) universal_rmls -= lits # The existential lits must not disagree with lits ex_lits = set([x for x in existential_rmls if x.is_lit()]) assert all([neg(lit) not in lits for lit in ex_lits]), \ "Error: Tried an existential literal with conflicting belief. E.g., Bp & P!p" existential_rmls -= ex_lits # We can safely remove every existential rml that will be covered by # some universal rml existential_rmls -= universal_rmls for rml in existential_rmls: if neg(rml) in universal_rmls: print("%s!!Warning!! Inconsistent existential rml: %s" % (DEBUG, str(rml))) if DEBUG: print("%sAgent: %s" % (DEBUG, str(cur_ag))) print("%sLits: %s" % (DEBUG, str(lits))) print("%sUniversal RMLs: %s" % (DEBUG, str(universal_rmls))) print("%sExistential RMLs: %s" % (DEBUG, str(existential_rmls))) if self.compressed or len(props) == len(self.props): w = World({lit.get_prop(): (not lit.negated) for lit in lits}) lit_worlds = set([w]) M.add_world(w) all_new_worlds.add(w) else: lit_worlds = generate_all_worlds(set(self.props) - props) for w in lit_worlds: for p in props: w[p] = (p in lits) M.add_world(w) all_new_worlds.add(w) # Handle the universals by default next_agents = set([rml.agent for rml in universal_rmls]) next_worlds = {} for next_ag in next_agents: new_worlds = self._generate_kripke( M, filter_agent(universal_rmls, next_ag), DEBUG) if DEBUG: print("%sNew worlds for universal rmls, are: %s" % (DEBUG, str(new_worlds))) next_worlds[next_ag] = new_worlds for w2 in new_worlds: for w1 in all_new_worlds: M.connect(w1, w2, next_ag) # Make sure to clone the canonical world when using it!!! canon_world = list(lit_worlds)[0] # Handle the existentials for rml in existential_rmls: w = canon_world.clone() M.add_world(w) all_new_worlds.add(w) new_worlds = self._generate_kripke( M, set([rml]) | filter_agent(universal_rmls, rml.agent), DEBUG) if DEBUG: print("%sNew worlds for existential rml, %s, are: %s" % (DEBUG, str(rml), str(new_worlds))) for w2 in new_worlds: M.connect(w, w2, rml.agent) for ag in next_worlds: if ag != rml.agent: for w2 in next_worlds[ag]: M.connect(w, w2, ag) if not self.compressed: M.make_equiv(all_new_worlds, cur_ag) return all_new_worlds
def is_omniscient(self): """Checks to see if the KB is omniscient (i.e., everything or its negation is believed)""" for rml in self.all_rmls: if (rml not in self.rmls) and (neg(rml) not in self.rmls): return False return True
def is_consistent(self): """Checks to see if there is anything obviously inconsistent""" for rml in self.rmls: if neg(rml) in self.rmls: return False return True
def close_omniscience(self): for rml in self.all_rmls: if isinstance(rml, Possible) and neg(rml) not in self.rmls: self.add_rml(rml)