def preprocess(self): # Project the initial state new_init = PDKB(self.init.depth, self.init.agents, self.init.props) rmls = self.init.rmls for ag in self.agent_projection: rmls = project(rmls, ag) new_init.rmls = rmls self.init = new_init self.orig_cond_count = 0 self.comp_cond_count = 0 # Expand and project the action's effects with derived conditional effects for act in self.domain.actions: self.orig_cond_count += sum([ len(act.effs[i][0]) + len(act.effs[i][1]) for i in range(len(act.effs)) ]) act.expand() self.comp_cond_count += sum([ len(act.effs[i][0]) + len(act.effs[i][1]) for i in range(len(act.effs)) ]) for ag in self.agent_projection: act.project_effects(ag) if self.agent_projection: # We project the precondition separately since we are in the # perspective of the final agent act.project_pre(self.agent_projection[-1])
def pddl(self): pdkb = PDKB(self.depth, self.agents, self.props) akpdkb = PDKB(0, [], self.akprops) to_ret = "(define (domain %s)\n\n" % self.name to_ret += " (:requirements :strips :conditional-effects)\n\n" to_ret += " (:predicates\n" PROPS = pdkb.all_rmls | akpdkb.all_rmls assert 0 == len( pdkb.all_rmls & akpdkb.all_rmls ), "Error: Detected overlap in regular fluents and always known fluents" print("\n\n# Agents: %d" % len(self.agents)) print("# Props: %d" % len(PROPS)) print("# Acts: %d" % len(self.actions)) print("# Effs: %d" % sum([a.num_effs() for a in self.actions])) print("Depth: %d" % self.depth) for (key, rml) in sorted([(str(r), r) for r in PROPS]): to_ret += " (%s)\n" % rml.pddl() to_ret += " )\n\n" for (key, act) in sorted([(a.name, a) for a in self.actions]): to_ret += "%s\n\n" % act.pddl() to_ret += ')' return to_ret
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 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 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 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))
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])
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 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
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 test7(): print "-- START TEST 7 --" AxiomSystem.SYSTEM = KD kb = PDKB(1, [1,2,3], map(Literal, ['p', 'q'])) test_remove(kb) kb = IndexedPDKB(1, [1,2,3], map(Literal, ['p', 'q'])) test_remove(kb) AxiomSystem.SYSTEM = KT kb = PDKB(1, [1,2,3], map(Literal, ['p', 'q'])) test_remove_kt(kb) kb = IndexedPDKB(1, [1,2,3], map(Literal, ['p', 'q'])) test_remove_kt(kb) print "-- END TEST 7 --\n"
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 test9(): print("-- START TEST 9 --") for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system kb1 = PDKB(3, [1,2,3], list(map(Literal, ['p', 'q', 'r']))) kb2 = IndexedPDKB(3, [1,2,3], list(map(Literal, ['p', 'q', 'r']))) test_consistency(kb1, kb2) print("-- END TEST 9 --\n")
def test10(): print "-- START TEST 10 --" for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system kb1 = PDKB(3, [1,2,3,4], map(Literal, ['p', 'q', 'r'])) kb2 = IndexedPDKB(3, [1,2,3,4], map(Literal, ['p', 'q', 'r'])) test_consistency_random_kb(kb1, kb2) print "-- END TEST 10 --\n"
def preprocess(self): # Project the initial state new_init = PDKB(self.init.depth, self.init.agents, self.init.props) rmls = self.init.rmls for ag in self.agent_projection: rmls = project(rmls, ag) new_init.rmls = rmls self.init = new_init # Expand and project the action's effects with derived conditional effects for act in self.domain.actions: act.expand() for ag in self.agent_projection: act.project_effects(ag) if self.agent_projection: # We project the precondition separately since we are in the # perspective of the final agent act.project_pre(self.agent_projection[-1])
def test8(): print "-- START TEST 8 --" for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system kb = PDKB(1, [1,2], map(Literal, ['p', 'q'])) test_update(kb) indexed_kb = IndexedPDKB(1, [1,2], map(Literal, ['p', 'q'])) test_update(indexed_kb) print "-- END TEST 8 --\n"
def test_consistency_random_kb(pdkb, kb): assert isinstance(pdkb, PDKB) NUM_RUNS = 10000 fluents = map(Literal, 'pqrst') agents = list(range(1, 4)) added = [] for i in range(0, NUM_RUNS): print >> sys.stderr, str(i) + " ", kb.reset() pdkb.reset() rmls = [ random_rml(4, agents, fluents), random_rml(3, agents, fluents), random_rml(2, agents, fluents), ] # Only add the RMLs if they are consistent check_consistency = PDKB(4, agents, fluents) check_consistency.update(set(rmls)) if check_consistency.is_consistent(): assert pdkb.is_consistent() kb_copy = kb.copy() pdkb_copy = pdkb.copy() pdkb.update(set(rmls)) kb.update(set(rmls)) rml = compare(pdkb, kb) if isinstance(rml, RML): kb_copy.restrict(rml) pdkb_copy.restrict(rml) kb.restrict(rml) pdkb.restrict(rml) print "before = " + str(kb_copy) print "before = " + str(pdkb_copy) print "\t add " + str(rmls) print "\t after = " + str(kb) print "\t after = " + str(pdkb) sys.exit()
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)
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 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 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 test6(): print "-- START TEST 6 --" for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system kb1 = PDKB(1, [1,2], map(Literal, ['p', 'q'])) kb2 = PDKB(1, [1,2], map(Literal, ['p', 'q'])) test_expand(kb1, kb2) # Test that adding an RML already implied does nothing kb1 = IndexedPDKB(1, [1,2], map(Literal, ['p', 'q'])) kb1.expand(set([Belief(1, Literal('p'))])) kb2 = kb1.copy() kb1.expand(set([Possible(1, Literal('p'))])) assert kb1 == kb2 # Test that adding an RML that implies an existing RML removes that RML kb1 = IndexedPDKB(1, [1,2], map(Literal, ['p', 'q'])) kb1.expand(set([Possible(1, Literal('p'))])) old_size = kb1.size() kb1.expand(set([Belief(1, Literal('p'))])) assert kb1.size() == old_size, "kb1 = %s, old = %s" % (kb1.size(), old_size) l1 = Belief(1, Literal('p')) l2 = Belief(2, Literal('p')) assert not l1.entails_rml(l2) for axiom_system in [KD, KT]: AxiomSystem.SYSTEM = axiom_system kb1 = IndexedPDKB(1, [1,2], map(Literal, ['p', 'q'])) kb2 = IndexedPDKB(1, [1,2], map(Literal, ['p', 'q'])) test_expand(kb1, kb2) print "-- END TEST 6 --\n"
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
condition, spacing, self.eff.pddl()) else: return reason + spacing + "(when (and %s)\n%s (%s))" % ( condition, spacing, self.eff.pddl()) if __name__ == '__main__': a = Action('foo', 2, [1, 2], list(map(Literal, [ 'p', 'q', ])), True) a.add_pre(Belief(1, Literal('p'))) a.add_pre(Belief(2, Literal('p'))) a.new_nondet_effect() p1 = PDKB(2, [1, 2], list(map(Literal, [ 'p', 'q', ]))) p2 = PDKB(2, [1, 2], list(map(Literal, [ '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',
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 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