def test_delta(): parser = LDLfParser() sa, sb, sc = "A", "B", "C" a, b, c = PLAtomic(sa), PLAtomic(sb), PLAtomic(sc) i_ = PLFalseInterpretation() i_a = PLInterpretation({sa}) i_b = PLInterpretation({sb}) i_ab = PLInterpretation({sa, sb}) true = PLTrue() false = PLFalse() tt = LDLfLogicalTrue() ff = LDLfLogicalFalse() assert parser("<A>tt").delta(i_) == false assert parser("<A>tt").delta(i_a) == PLAtomic(tt) assert parser("<A>tt").delta(i_b) == false assert parser("<A>tt").delta(i_ab) == PLAtomic(tt) assert parser("[B]ff").delta(i_) == true assert parser("[B]ff").delta(i_a) == true assert parser("[B]ff").delta(i_b) == PLAtomic(ff) assert parser("[B]ff").delta(i_ab) == PLAtomic(ff) f = parser("!(<!(A<->B)+(B;A)*+(!last)?>[(true)*]end)") assert f.delta(i_) == f.to_nnf().delta(i_) assert f.delta(i_ab) == f.to_nnf().delta(i_ab) assert f.delta(i_, epsilon=True) == f.to_nnf().delta(i_, epsilon=True) assert f.delta(i_ab, epsilon=True) == f.to_nnf().delta(i_ab, epsilon=True) # with epsilon=True, the result is either PLTrue or PLFalse assert f.delta(i_, epsilon=True) in [PLTrue(), PLFalse()]
def test_delta(): parser = LDLfParser() i_ = {} i_a = {"A": True} i_b = {"B": True} i_ab = {"A": True, "B": True} true = PLTrue() false = PLFalse() tt = PLAtomic(LDLfLogicalTrue()) ff = PLAtomic(LDLfLogicalFalse()) assert parser("<A>tt").delta(i_) == false assert parser("<A>tt").delta(i_a) == tt assert parser("<A>tt").delta(i_b) == false assert parser("<A>tt").delta(i_ab) == tt assert parser("[B]ff").delta(i_) == true assert parser("[B]ff").delta(i_a) == true assert parser("[B]ff").delta(i_b) == ff assert parser("[B]ff").delta(i_ab) == ff f = parser("!(<?(!last)>end)") assert f.delta(i_) == f.to_nnf().delta(i_) assert f.delta(i_ab) == f.to_nnf().delta(i_ab) assert f.delta(i_, epsilon=True) == f.to_nnf().delta(i_, epsilon=True) assert f.delta(i_ab, epsilon=True) == f.to_nnf().delta(i_ab, epsilon=True) # with epsilon=True, the result is either PLTrue or PLFalse assert f.delta(i_, epsilon=True) in [PLTrue(), PLFalse()]
def __init__(self, input_space, bricks_cols=3, bricks_rows=3, lines_num=3, gamma=0.99, on_the_fly=False): assert lines_num == bricks_cols or lines_num == bricks_rows self.line_symbols = [Symbol("l%s" % i) for i in range(lines_num)] lines = self.line_symbols parser = LDLfParser() string_formula = get_breakout_lines_formula(lines) print(string_formula) f = parser(string_formula) reward = 10000 super().__init__(BreakoutGoalFeatureExtractor(input_space, bricks_cols=bricks_cols, bricks_rows=bricks_rows), set(lines), f, reward, gamma=gamma, on_the_fly=on_the_fly)
def test_ldlf_example_readme(): from flloat.parser.ldlf import LDLfParser parser = LDLfParser() formula = "<true*; a & b>tt" parsed_formula = parser(formula) assert ( str(parsed_formula) == "<((true)* ; (b & a))>(tt)" or str(parsed_formula) == "<((true)* ; (a & b))>(tt)" ) assert parsed_formula.find_labels() == {c for c in "ab"} t1 = [ {"a": False, "b": False}, {"a": True, "b": False}, {"a": True, "b": False}, {"a": True, "b": True}, {"a": False, "b": False}, ] assert parsed_formula.truth(t1, 0) t2 = [{"a": False, "b": False}, {"a": True, "b": False}, {"a": False, "b": True}] assert not parsed_formula.truth(t2, 0) dfa = parsed_formula.to_automaton() assert dfa.accepts(t1) assert not dfa.accepts(t2)
def test_find_labels(): parser = LDLfParser() f = "< (!(A | B | C ))* ; (A | C) ; (!(A | B | C))* ; (B | C) ><true>tt" formula = parser(f) assert formula.find_labels() == {c for c in "ABC"} f = "(<(((?(<B>tt));true)*) ; (? (<(A & B)>tt))>tt)" formula = parser(f) assert formula.find_labels() == {c for c in "AB"}
def test_nnf(): parser = LDLfParser() assert parser("!tt").to_nnf() == LDLfLogicalFalse() assert parser("!!tt").to_nnf() == LDLfLogicalTrue() f = parser("!(<!(A&B)>end)").to_nnf() ff = parser("[!A | !B]<true>tt") assert f == ff assert parser("!(<!(A&B)>end)").to_nnf() == parser("[!A | !B]<true>tt") f = parser("!(<((!(A<->D))+((B;C)*)+(?(!last)))>[(true)*]end)") assert f.to_nnf() == f.to_nnf().to_nnf()
def test_nnf(): parser = LDLfParser() assert parser("!tt").to_nnf() == LDLfLogicalFalse() assert parser("!!tt").to_nnf() == LDLfLogicalTrue() assert parser("!(<!(A&B)>end)").to_nnf() == parser("[!A | !B]<true>tt") f = parser("!(<!(A<->D)+(B;C)*+(!last)?>[(true)*]end)") assert f.to_nnf() == parser( "[(([true]<true>tt)? + ((B ; C))* + ((A | D) & (!(D) | !(A))))]<(true)*><true>tt" ) assert f.to_nnf() == f.to_nnf().to_nnf().to_nnf().to_nnf()
def __init__(self, on_the_fly=False): self.row_symbols = [Symbol(r) for r in ["r0", "r1", "r2"]] rows = self.row_symbols parser = LDLfParser() f = parser( "<(!r0 & !r1 & !r2)*;(r0 & !r1 & !r2)*;(r0 & r1 & !r2)*; r0 & r1 & r2>tt" ) reward = 10000 super().__init__(BreakoutRowBottomUpGoalFeatureExtractor(), set(rows), f, reward, on_the_fly=on_the_fly)
def make_env(config: MinecraftConfiguration, output_dir, goal_reward: float = 1000.0, reward_shaping: bool = True) -> gym.Env: """ Make the Minecraft environment. :param config: the Minecraft configuration. :param output_dir: the path to the output directory. :param reward_shaping: apply automata-based reward shaping. :return: the Gym environment. """ temporal_goals = [] for t in config.tasks: formula_string = make_goal(t) print("Formula: {}".format(formula_string)) formula = LDLfParser()(formula_string) tg = TemporalGoal( formula=formula, reward=goal_reward, # labels=LABELS, reward_shaping=reward_shaping, zero_terminal_state=False, extract_fluents=extract_minecraft_fluents) temporal_goals.append(tg) tg._automaton.to_dot( os.path.join(output_dir, "true_automaton_{}".format(t.name))) print("Original automaton at {}".format( os.path.join(output_dir, "true_automaton_{}.svg".format(t.name)))) env = MinecraftTemporalWrapper( MinecraftExpertWrapper(config), temporal_goals, combine=lambda obs, qs: tuple((*obs, *qs)), feature_extractor=lambda obs, action: (obs["x"], obs["y"], obs["theta"]) if config.action_space_type == ActionSpaceType.DIFFERENTIAL else (obs["x"], obs["y"])) positive_traces_path = Path(output_dir, "positive_traces.txt") negative_traces_path = Path(output_dir, "negative_traces.txt") env = TemporalGoalWrapperLogTraces(env, extract_minecraft_fluents, positive_traces_path, negative_traces_path) return env
def make_env(config: BreakoutConfiguration, output_dir, goal_reward: float = 1000.0, reward_shaping: bool = True) -> gym.Env: """ Make the Breakout environment. :param config: the Breakout configuration. :param output_dir: the path to the output directory. :param reward_shaping: apply automata-based reward shaping. :return: the Gym environment. """ unwrapped_env = BreakoutExpertWrapper(config) formula_string = make_goal(config.brick_cols) formula = LDLfParser()(formula_string) labels = {"c{}".format(i) for i in range(config.brick_cols)} tg = TemporalGoal(formula=formula, reward=goal_reward, labels=labels, reward_shaping=reward_shaping, zero_terminal_state=False, extract_fluents=extract_breakout_fluents) print("Formula: {}".format(formula_string)) tg._automaton.to_dot(os.path.join(output_dir, "true_automaton")) print("Original automaton at {}".format( os.path.join(output_dir, "true_automaton.svg"))) env = TemporalGoalWrapper( unwrapped_env, [tg], combine=lambda obs, qs: tuple((*obs, *qs)), feature_extractor=( lambda obs, action: ( obs["paddle_x"], #obs["paddleup_x"], ))) positive_traces_path = Path(output_dir, "positive_traces.txt") negative_traces_path = Path(output_dir, "negative_traces.txt") env = TemporalGoalWrapperLogTraces(env, extract_breakout_fluents, positive_traces_path, negative_traces_path) return env
def make_env(config: SapientinoConfiguration, output_dir, goal_reward: float = 1000.0, reward_shaping: bool = True) -> gym.Env: """ Make the Breakout environment. :param config: the Breakout configuration. :param output_dir: the path to the output directory. :param reward_shaping: apply automata-based reward shaping. :return: the Gym environment. """ formula_string = make_goal() print("Formula: {}".format(formula_string)) formula = LDLfParser()(formula_string) tg = TemporalGoal(formula=formula, reward=goal_reward, labels={color for color in colors}.union({"bad_beep"}), reward_shaping=reward_shaping, zero_terminal_state=False, extract_fluents=extract_sapientino_fluents) tg._automaton.to_dot(os.path.join(output_dir, "true_automaton")) print("Original automaton at {}".format( os.path.join(output_dir, "true_automaton.svg"))) env = SapientinoTemporalWrapper( SapientinoWrapper(SapientinoDictSpace(config)), [tg], combine=lambda obs, qs: tuple((*obs, *qs)), feature_extractor=lambda obs, action: (obs["x"], obs["y"], obs["th"]) if config.differential else (obs["x"], obs["y"])) positive_traces_path = Path(output_dir, "positive_traces.txt") negative_traces_path = Path(output_dir, "negative_traces.txt") env = TemporalGoalWrapperLogTraces(env, extract_sapientino_fluents, positive_traces_path, negative_traces_path) return env
def test_truth(): sa, sb = "a", "b" a, b = PLAtomic(sa), PLAtomic(sb) i_ = PLFalseInterpretation() i_a = PLInterpretation({sa}) i_b = PLInterpretation({sb}) i_ab = PLInterpretation({sa, sb}) tr_false_a_b_ab = FiniteTrace([i_, i_a, i_b, i_ab, i_]) tt = LDLfLogicalTrue() ff = LDLfLogicalFalse() assert tt.truth(tr_false_a_b_ab, 0) assert not ff.truth(tr_false_a_b_ab, 0) assert not LDLfNot(tt).truth(tr_false_a_b_ab, 0) assert LDLfNot(ff).truth(tr_false_a_b_ab, 0) assert LDLfAnd([LDLfPropositional(a), LDLfPropositional(b)]).truth(tr_false_a_b_ab, 3) assert not LDLfDiamond(RegExpPropositional(PLAnd([a, b])), tt).truth( tr_false_a_b_ab, 0) parser = LDLfParser() trace = FiniteTrace.from_symbol_sets([{}, {"A"}, {"A"}, {"A", "B"}, {}]) formula = "<true*;A&B>tt" parsed_formula = parser(formula) assert parsed_formula.truth(trace, 0) formula = "[(A+!B)*]<C>tt" parsed_formula = parser(formula) assert not parsed_formula.truth(trace, 1) formula = "<(<!C>tt)?><A>tt" parsed_formula = parser(formula) assert parsed_formula.truth(trace, 1) formula = "<!C+A>tt" parsed_formula = parser(formula) assert parsed_formula.truth(trace, 1)
def __init__(self, input_space, formula_string, gamma=0.99, on_the_fly=False): # self.location_syms = [Symbol(l[0]) for l in LOCATIONS] # self.get, self.use = Symbol("get"), Symbol("use") self.locations = [l[0] for l in LOCATIONS] parser = LDLfParser() # parser = LTLfParser() print(formula_string) f = parser(formula_string) reward = 1 super().__init__(MinecraftTEFeatureExtractor(input_space), f.find_labels(), f, reward, gamma=gamma, on_the_fly=on_the_fly)
def test_ldlf_example_readme(): from flloat.parser.ldlf import LDLfParser parser = LDLfParser() formula = "<true*; A & B>tt" parsed_formula = parser(formula) assert str(parsed_formula) == "<((true)* ; (B & A))>(tt)" or str( parsed_formula) == "<((true)* ; (A & B))>(tt)" assert parsed_formula.find_labels() == {c for c in "AB"} from flloat.semantics.traces import FiniteTrace t1 = FiniteTrace.from_symbol_sets([{}, {"A"}, {"A"}, {"A", "B"}, {}]) assert parsed_formula.truth(t1, 0) t2 = FiniteTrace.from_symbol_sets([{}, {"A"}, {"B"}]) assert not parsed_formula.truth(t2, 0) dfa = parsed_formula.to_automaton() assert dfa.accepts(t1.trace) assert not dfa.accepts(t2.trace)
def __init__(self, input_space, gamma=0.99, on_the_fly=False, relaxed=True): self.color_syms = [Symbol(c) for c in COLORS] + [Symbol("no_color")] self.bip = Symbol("bip") parser = LDLfParser() if not relaxed: # the formula sb = str(self.bip) not_bip = ";(!%s)*;" % sb and_bip = lambda x: str(x) + " & " + sb # every color-bip in sequence, no bip between colors. formula_string = "<(!%s)*;" % sb + not_bip.join( map(and_bip, self.color_syms[:-1])) + ">tt" else: sb = str(self.bip) not_bip = ";true*;" and_bip = lambda x: str(x) + " & " + sb # every color-bip in sequence, no bip between colors. formula_string = "<true*;" + not_bip.join( map(and_bip, self.color_syms[:-1])) + ">tt" print(formula_string) f = parser(formula_string) reward = 1 super().__init__(SapientinoTEFeatureExtractor(input_space), set(self.color_syms).union({self.bip}), f, reward, gamma=gamma, on_the_fly=on_the_fly)
def __init__(self, input_space, bricks_cols=3, bricks_rows=3, lines_num=3, gamma=0.99, on_the_fly=False): self.line_symbols = [Symbol("l%s" % i) for i in range(lines_num)] lines = self.line_symbols parser = LDLfParser() f = parser( "<(!l0 & !l1 & !l2)*;(l0 & !l1 & !l2);(l0 & !l1 & !l2)*;(l0 & l1 & !l2); (l0 & l1 & !l2)*; l0 & l1 & l2>tt" ) reward = 10000 super().__init__(BreakoutGoalFeatureExtractor(input_space, bricks_cols=bricks_cols, bricks_rows=bricks_rows), set(lines), f, reward, gamma=gamma, on_the_fly=on_the_fly)
def setup_class(cls): cls.parser = LDLfParser() cls.trace = [{}, {"A": True}, {"A": True}, {"A": True, "B": True}, {}]
def test_parser(): parser = LDLfParser() a, b = PLAtomic("A"), PLAtomic("B") tt = LDLfLogicalTrue() ff = LDLfLogicalFalse() true = PLTrue() false = PLFalse() r_true = RegExpPropositional(true) r_false = RegExpPropositional(false) assert tt == parser("tt") assert ff == parser("ff") assert LDLfDiamond(r_true, tt) == parser("<true>tt") assert LDLfDiamond(r_false, tt) == parser("<false>tt") assert parser("!tt & <!A&B>tt") == LDLfAnd([ LDLfNot(tt), LDLfDiamond(RegExpPropositional(PLAnd([PLNot(a), b])), tt) ]) assert parser("[true*]([true]ff | <!A>tt | <(true)*><B>tt)") == LDLfBox( RegExpStar(r_true), LDLfOr([ LDLfBox(r_true, ff), LDLfDiamond(RegExpPropositional(PLNot(a)), tt), LDLfDiamond(RegExpStar(r_true), (LDLfDiamond(RegExpPropositional(b), tt))), ]), ) assert parser("[A&B&A]ff <-> <A&B&A>tt") == LDLfEquivalence([ LDLfBox(RegExpPropositional(PLAnd([a, b, a])), ff), LDLfDiamond(RegExpPropositional(PLAnd([a, b, a])), tt), ]) assert parser("<A+B>tt") == LDLfDiamond( RegExpUnion([RegExpPropositional(a), RegExpPropositional(b)]), tt) assert parser("<A;B>tt") == LDLfDiamond( RegExpSequence([RegExpPropositional(a), RegExpPropositional(b)]), tt) assert parser("<A+(B;A)>end") == LDLfDiamond( RegExpUnion([ RegExpPropositional(a), RegExpSequence([RegExpPropositional(b), RegExpPropositional(a)]), ]), LDLfEnd(), ) assert parser("!(<(!(A<->D))+((B;C)*)+(?!last)>[(true)*]end)") == LDLfNot( LDLfDiamond( RegExpUnion([ RegExpPropositional(PLNot(PLEquivalence([a, PLAtomic("D")]))), RegExpStar( RegExpSequence([ RegExpPropositional(PLAtomic("B")), RegExpPropositional(PLAtomic("C")), ])), RegExpTest(LDLfNot(LDLfLast())), ]), LDLfBox(RegExpStar(RegExpPropositional(PLTrue())), LDLfEnd()), ))
def setup_class(cls): cls.parser = LDLfParser() cls.i_ = {} cls.i_a = {"A": True} cls.i_b = {"B": True} cls.i_ab = {"A": True, "B": True}
def __init__( self, env_name, fluents, n_functions, logdir=None, verbose=True ): """Initialize. :param env_name: a gym environment name. :param fluents: the list of propositional atoms that will be predicted. :param n_functions: number of predictions to valuate in parallel. :param logdir: if provided, the automaton just parsed is saved here. :param verbose: log the parsing step, because it may take a long time! """ # Loading if verbose: print("> Parsing", env_name, "constraints") data = selector.read_back(env_name) json_constraints = data["constraints"] # Parsing constraint = " & ".join(json_constraints) formula = LDLfParser()(constraint) # type: LDLfFormula # Check: all atoms must be evaluated atoms = formula.find_labels() all_predicted = all((a in fluents for a in atoms)) if not all_predicted: raise ValueError( "One of the atoms " + str(atoms) + " is not in fluents") # Conversion (slow op) automaton = formula.to_automaton() # type: SymbolicAutomaton automaton = automaton.determinize() if verbose: print("> Parsed") # Visualize the automaton if logdir is not None: graphviz = automaton.to_graphviz() graphviz.render( "constraint.gv", directory=logdir, view=False, cleanup=False) # Store self.env_name = env_name self.fluents = fluents self._str = constraint self._formula = formula self._automaton = automaton self._n_functions = n_functions self._n_fluents = len(self.fluents) # Automaton parallel execution self._tf_automata = TfSymbolicAutomaton(self._automaton, self.fluents) # Prepare buffers self._current_states = tf.Variable( tf.zeros([self._n_functions], dtype=tf.int32), trainable=False, name="current_states") self._final_counts = tf.Variable( tf.zeros( [self._n_functions, len(self._tf_automata.final_states)], dtype=tf.int32), trainable=False, name="final_counts_buffer") self._timestep = tf.Variable(0, trainable=False, name="timestep") # Ready for a new run self._reset()
def setup_class(cls): cls.parser = LDLfParser() cls.i_ = PLInterpretation(set()) cls.i_a = PLInterpretation({"A"}) cls.i_b = PLInterpretation({"B"}) cls.i_ab = PLInterpretation({"A", "B"})
RegExpStar, LDLfOr, RegExpUnion, RegExpSequence, LDLfEnd, RegExpTest, LDLfLast, ) from flloat.parser.ldlf import LDLfParser from flloat.pl import PLTrue, PLFalse, PLAnd, PLNot, PLAtomic, PLEquivalence from .conftest import LDLfFixtures from .strategies import propositional_words from .parsing import ParsingCheck from . import test_pl parser = LDLfParser() def test_parser(): parser = LDLfParser() a, b = PLAtomic("A"), PLAtomic("B") tt = LDLfLogicalTrue() ff = LDLfLogicalFalse() true = PLTrue() false = PLFalse() r_true = RegExpPropositional(true) r_false = RegExpPropositional(false) assert tt == parser("tt") assert ff == parser("ff")
def __init__( self, env_name, fluents, reward, logdir, load=None, verbose=True, ): """Initialize. :param env_name: a gym atari environment name. :param fluents: the list of propositional atoms that are known at each step. :param reward: (float) this reward is returned when the execution reaches a final state (at the first instant an execution satisfies the restraining specification). :param logdir: the automaton just parsed is saved here. :param load: if provided, the automaton is not computed but loaded from this file. A path to a rb.pickle file. :param verbose: verbose flag (automaton conversion may take a while). """ # Read data = selector.read_back(env_name) json_rb = data["restraining_bolt"] + data["constraints"] # Parsing restraining_spec = " & ".join(json_rb) formula = LDLfParser()(restraining_spec) # type: LDLfFormula # Check: all atoms must be evaluated atoms = formula.find_labels() all_predicted = all((a in fluents for a in atoms)) if not all_predicted: raise ValueError("One of the atoms " + str(atoms) + " is not in fluents") # Parse if load is None: # Conversion (slow op) if verbose: print("> Parsing", env_name, "restraining specification") automaton = formula.to_automaton() # type: SymbolicAutomaton automaton = automaton.determinize().complete() if verbose: print("> Parsed") # Save and visualize the automaton graphviz = automaton.to_graphviz() graphviz.render("rb.gv", directory=logdir, view=False, cleanup=False) with open(os.path.join(logdir, "rb.pickle"), "wb") as f: pickle.dump(automaton, f) # Load else: with open(load, "rb") as f: automaton = pickle.load(f) if verbose: print(">", load, "loaded") # Visualize the automaton loaded (debugging) graphviz = automaton.to_graphviz() graphviz.render("loaded_rb.gv", directory=logdir, view=False, cleanup=False) # Runner simulator = AutomatonSimulator(automaton) # Store self.env_name = env_name self.fluents = fluents self._str = restraining_spec self._formula = formula self._automaton = automaton self._simulator = simulator self._reward = reward self._last_state = None