def test_only_mode_control(): """Unrealizable due to non-determinism. Switched system with 2 modes: 'left', 'right'. Modes are controlled by the system. States are controlled by the environment. So only control over dynamics is through mode switching. Transitions are thus interpreted as non-deterministic. This can model uncertain outcomes in the real world, e.g., due to low quality actuators or bad low-level feedback controllers. """ # Create a finite transition system env_sws = transys.FTS() env_sws.owner = 'env' env_sws.sys_actions.add_from({'right', 'left'}) # str states n = 4 states = transys.prepend_with(range(n), 's') env_sws.atomic_propositions.add_from(['home', 'lot']) # label TS with APs ap_labels = [set(), set(), {'home'}, {'lot'}] for i, label in enumerate(ap_labels): state = 's' + str(i) env_sws.states.add(state, ap=label) # mode1 transitions transmat1 = np.array([[0, 1, 0, 1], [0, 1, 0, 0], [0, 1, 0, 1], [0, 0, 0, 1]]) env_sws.transitions.add_adj(sp.lil_matrix(transmat1), states, {'sys_actions': 'right'}) # mode2 transitions transmat2 = np.array([[1, 0, 0, 0], [1, 0, 1, 0], [0, 0, 1, 0], [1, 0, 1, 0]]) env_sws.transitions.add_adj(sp.lil_matrix(transmat2), states, {'sys_actions': 'left'}) env_vars = {'park'} env_init = {'eloc = "s0"', 'park'} env_prog = {'!park'} env_safe = set() sys_vars = {'X0reach'} sys_init = {'X0reach'} sys_prog = {'home'} sys_safe = {'next(X0reach) <-> lot || (X0reach && !park)'} sys_prog |= {'X0reach'} specs = spec.GRSpec(env_vars, sys_vars, env_init, sys_init, env_safe, sys_safe, env_prog, sys_prog) r = synth.is_realizable('gr1c', specs, env=env_sws, ignore_env_init=True) assert not r
def ppp2ts(part): """Derive transition system from proposition preserving partition. @param part: labeled polytopic partition from which to derive the transition system @type part: L{PropPreservingPartition} @return: C{(ts, state_map)} finite transition system labeled with propositions from the given partition, and map of polytope indices to transition system states. @rtype: (L{transys.FTS}, \C{dict}) """ # generate transition system and add transitions ofts = trs.FTS() adj = part.adj #sp.lil_matrix n = adj.shape[0] ofts_states = range(n) ofts_states = trs.prepend_with(ofts_states, 's') ofts.states.add_from(ofts_states) ofts.transitions.add_adj(adj, ofts_states) # decorate TS with state labels atomic_propositions = set(part.prop_regions) ofts.atomic_propositions.add_from(atomic_propositions) for state, region in zip(ofts_states, part.regions): state_prop = region.props.copy() ofts.states.add(state, ap=state_prop) return (ofts, ofts_states)
def ts_test(): ts = trs.FTS() ts.states.add('s0') assert ('s0' in ts) assert ('s0' in ts.node) assert ('s0' in ts.states) states = {'s0', 's1', 's2', 's3'} ts.states.add_from(states) assert (set(ts.states) == states) ts.transitions.add('s0', 's1') ts.transitions.add_from([('s1', 's2'), ('s2', 's3'), ('s3', 's0')]) ts.states.initial.add('s0') ts.states.initial.add_from({'s0', 's1'}) ts.atomic_propositions.add('p') assert (set(ts.atomic_propositions) == {'p'}) ts.states['s0']['ap'] = {'p'} ts.states['s1']['ap'] = set() ts.states['s2']['ap'] = set() ts.states['s3']['ap'] = set() assert (ts.states['s0']['ap'] == {'p'}) for state in {'s1', 's2', 's3'}: assert (ts.states[state]['ap'] == set()) logger.debug(ts) return ts
def label_per_state(): """Add states with (possibly) different AP labels each. """ fts = trs.FTS() fts.states.add_from(['s0', 's1']) fts.atomic_propositions.add('p') fts.states.add('s0', ap={'p'}) fts.states.add('s1', ap=None) fts.plot()
def scipy_sparse_labeled_adj(): n = 10 A = lil_matrix((n, n)) A[0, :3] = rand(3) adj2states = range(n) print(A) ofts = trs.FTS() ofts.states.add_from(set(range(10))) ofts.sys_actions.add('move') ofts.env_actions.add('rain') ofts.transitions.add_adj(A, adj2states, sys_actions='move', env_actions='rain') ofts.plot() """same thing as above, using A as a submatrix instead """ A = lil_matrix((3, 3)) A[0, :3] = rand(3) adj2states = [0, 1, 2] print(A) ofts = trs.FTS() ofts.states.add_from(set(range(10))) ofts.sys_actions.add('move') ofts.env_actions.add('rain') ofts.transitions.add_adj(A, adj2states, sys_actions='move', env_actions='rain') ofts.plot() return ofts
def multiple_env_actions_check(solver='omega'): """Two env players, 3 states controlled by sys. sys wins marginally, due to assumption on next combination of actions by env players. """ # 1 <---> 2 # 1 ---> 3 env_actions = [ { 'name': 'env_alice', 'values': transys.MathSet({'left', 'right'}) }, { 'name': 'env_bob', 'values': transys.MathSet({'bleft', 'bright'}) } ] sys = transys.FTS(env_actions) sys.states.add_from({'s1', 's2', 's3'}) sys.states.initial.add_from({'s1'}) sys.add_edge('s1', 's2', env_alice='left', env_bob='bright') sys.add_edge('s2', 's1', env_alice='left', env_bob='bright') # at state 3 sys loses sys.add_edge('s1', 's3', env_alice='right', env_bob='bleft') logging.debug(sys) env_safe = {('(loc = "s1") -> X( (env_alice = "left") && ' '(env_bob = "bright") )')} sys_prog = {'loc = "s1"', 'loc = "s2"'} specs = spec.GRSpec( env_safety=env_safe, sys_prog=sys_prog, moore=False, plus_one=False, qinit='\A \E') r = synth.is_realizable(specs, sys=sys, solver=solver) assert r # slightly relax assumption specs = spec.GRSpec( sys_prog=sys_prog, moore=False, plus_one=False, qinit='\A \E') r = synth.is_realizable(specs, sys=sys, solver=solver) assert not r
def env_ofts_bool_actions(): env = transys.FTS() env.owner = 'env' env.states.add_from({'e0', 'e1', 'e2'}) env.states.initial.add('e0') env.env_actions.add_from({'park', 'go'}) env.sys_actions.add_from({'up', 'down'}) env.transitions.add('e0', 'e1', env_actions='park', sys_actions='up') env.transitions.add('e1', 'e2', env_actions='go', sys_actions='down') # env.plot() return env
def sys_fts_2_states(): sys = transys.FTS() sys.states.add_from(['X0', 'X1']) sys.states.initial.add_from(['X0', 'X1']) sys.transitions.add('X0', 'X1') sys.transitions.add('X1', 'X0') sys.transitions.add('X1', 'X1') sys.atomic_propositions.add_from({'home', 'lot'}) sys.states.add('X0', ap={'home'}) sys.states.add('X1', ap={'lot'}) # sys.plot() return sys
def env_fts_2_states(): env = transys.FTS() env.owner = 'env' env.states.add_from({'e0', 'e1'}) env.states.initial.add('e0') # Park as an env action env.env_actions.add_from({'park', 'go'}) env.transitions.add('e0', 'e0', env_actions='park') env.transitions.add('e0', 'e0', env_actions='go') # env.plot() return env
def fts_minimal_example(): """Small example, for more see the maximal example.""" fts = trs.FTS() fts.states.add_from(['s0', 's1']) fts.states.initial.add('s0') fts.atomic_propositions.add_from({'green', 'not_green'}) fts.states.add('s0', ap={'not_green'}) fts.states.add('s1', ap={'green'}) fts.transitions.add('s0', 's1') fts.transitions.add('s1', 's0') if not fts.plot() and save_fig: fts.save('small_fts.png') return fts
def tulip_synthesis(self): # call Tulip to synthesize a discrete controller sys = transys.FTS() sys.states.add_from(self.free_space.keys()) idx = self.determine_discrete_state() sys.states.initial.add(idx) for node in self.discrete_graph.edges.keys(): sys.transitions.add_comb(set([node]), set(self.discrete_graph.edges[node])) sys.atomic_propositions.add_from(set(self.ap.keys())) for state in self.label.keys(): sys.states.add(state,ap=set(self.label[state])) ctrl = synth.synthesize(self.Tulip_spec, sys=sys) if ctrl is None: pdb.set_trace() else: dumpsmach.write_python_case("discrete_ctrl.py", ctrl, classname="symb_ctrl") from discrete_ctrl import symb_ctrl self.discrete_controller = symb_ctrl() self.prior_discrete_graph = self.discrete_graph.copy() self.prior_label = self.label.copy()
# between adjacent cells are allowed, which we model as a transition # system in this example (it would also be possible to do this via a # formula) # # We label the states using the following picture # # +----+----+----+ # | X3 | X4 | X5 | # +----+----+----+ # | X0 | X1 | X2 | # +----+----+----+ # # @system_dynamics_section@ # Create a finite transition system sys = transys.FTS() # Define the states of the system sys.states.add_from(['X0', 'X1', 'X2', 'X3', 'X4', 'X5']) sys.states.initial.add('X0') # start in state X0 # Define the allowable transitions #! TODO (IF): can arguments be a singleton instead of a list? #! TODO (IF): can we use lists instead of sets? #! * use optional flag to allow list as label sys.transitions.add_comb({'X0'}, {'X1', 'X3'}) sys.transitions.add_comb({'X1'}, {'X0', 'X4', 'X2'}) sys.transitions.add_comb({'X2'}, {'X1', 'X5'}) sys.transitions.add_comb({'X3'}, {'X0', 'X4'}) sys.transitions.add_comb({'X4'}, {'X3', 'X1', 'X5'}) sys.transitions.add_comb({'X5'}, {'X4', 'X2'})
# import logging logging.basicConfig(level=logging.INFO) logging.getLogger('tulip.spec').setLevel(logging.ERROR) logging.getLogger('tulip.synth').setLevel(logging.DEBUG) from tulip import spec, synth, transys import numpy as np from scipy import sparse as sp ########################################### # Hybrid system with 2 env, 2 system modes: ########################################### sys_hyb = transys.FTS() # We assume robots ability to transition between cells depends both on # discrete controlled modes (e.g., gears) and environment modes (e.g., surface # conditions). sys_hyb.sys_actions.add_from({'gear0', 'gear1'}) sys_hyb.env_actions.add_from({'slippery', 'normal'}) # str states n = 6 states = ['s' + str(i) for i in xrange(n)] sys_hyb.atomic_propositions.add_from(['home', 'lot']) state_labels = [{'home'}, set(), set(), set(), set(), {'lot'}]
import numpy as np from scipy import sparse as sp ############################### # Switched system with 4 modes: ############################### # In this scenario we have limited actions "left, right, up, down" with # uncertain (nondeterministics) outcomes (e.g., due to bad actuators or # bad low-level feedback controllers) # Only control over the dynamics is through mode switching # Transitions should be interpreted as nondeterministic # Create a finite transition system env_sws = transys.FTS() env_sws.owner = 'env' env_sws.sys_actions.add_from({'right', 'up', 'left', 'down'}) # str states n = 6 states = transys.prepend_with(range(n), 's') env_sws.states.add_from(set(states)) env_sws.states.initial.add('s0') env_sws.atomic_propositions.add_from(['home', 'lot']) state_labels = [{'home'}, set(), set(), set(), set(), {'lot'}] # Add states and decorate TS with state labels (aka atomic propositions) for state, label in zip(states, state_labels):
def create_w_specs_all_init_cond(current_horizon, x_goal_loc, y_goal_loc, w_part, transition_part, dimension_x, dimension_y): # Don't synthesize for corner w regions (i.e. w region that's only a corner) that can't be fulfilled (... so ugly) # Note: Better way of doing this would be to not add corner regions to w_part... if (w_part[current_horizon] == [(dimension_x, dimension_y, 1)] or w_part[current_horizon] == [(dimension_x, dimension_y, 2)] or w_part[current_horizon] == [(dimension_x, dimension_y, 3)] or w_part[current_horizon] == [(dimension_x, dimension_y, 4)] or w_part[current_horizon] == [(dimension_x, 1, 1)] or w_part[current_horizon] == [(dimension_x, 1, 2)] or w_part[current_horizon] == [(dimension_x, 1, 3)] or w_part[current_horizon] == [(dimension_x, 1, 4)] or w_part[current_horizon] == [(1, dimension_y, 1)] or w_part[current_horizon] == [(1, dimension_y, 2)] or w_part[current_horizon] == [(1, dimension_y, 3)] or w_part[current_horizon] == [(1, dimension_y, 4)] or w_part[current_horizon] == [(1, 1, 1)] or w_part[current_horizon] == [(1, 1, 2)] or w_part[current_horizon] == [(1, 1, 3)] or w_part[current_horizon] == [(1, 1, 4)]): return # Create FTS and actions sys_auto = transys.FTS() sys_auto.sys_actions.add_from({'Stop', 'Go'}) # Fake AP's to enable all specs related to base and goal position sys_auto.states.add_from(['FAKE']) sys_auto.atomic_propositions.add_from({'Base', 'GoalPos'}) sys_auto.states['FAKE']['ap'] |= {'Base', 'GoalPos'} # Add all AP's for the transition space, including those tied to 'Base' and 'GoalPos' if present in transition space for locat in transition_part[current_horizon]: add_ap_sub = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str( locat[2]) sys_auto.states.add_from([add_ap_sub]) if locat[0] == 2 and locat[ 1] == 2: # TODO add some global indicator of the base location sys_auto.states[add_ap_sub]['ap'] |= {'Base'} if locat[0] == x_goal_loc and locat[1] == y_goal_loc: sys_auto.states[add_ap_sub]['ap'] |= {'GoalPos'} # Initial condition, empty set sys_auto_init = set() #print(transition_part[current_horizon]) #print(w_part[current_horizon]) #input('uhmmm...') # NOTE: that current_horizon is 1, 2, 3, ... # Create all transitions through brute force method of checking existence of locations in the transition region next # to every starting point, dependent on the orientation. This is ran on transition region and inclusion in w region # is checked in creating transitions. This is because all w regions are contained in the transition region, and # transitions from a w region are different than those form just transition regions for locat in transition_part[current_horizon]: init = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str( locat[2]) if locat in w_part[current_horizon]: sys_auto.transitions.add_comb({init}, {init}, sys_actions="Stop") # Transitions allowed if orientation is up if locat[2] == 1: if (locat[0], locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str( locat[0]) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] + 1, locat[1] + 1, 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] + 1) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] - 1, locat[1] + 1, 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] + 1) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") # Transitions allowed if orientation is right elif locat[2] == 2: if (locat[0] + 1, locat[1], 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str( locat[1]) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] + 1, locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] + 1, locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") # Transitions allowed if orientation is down elif locat[2] == 3: if (locat[0], locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str( locat[0]) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] + 1, locat[1] - 1, 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] - 1) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] - 1, locat[1] - 1, 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] - 1) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") # Transitions allowed if orientation is left elif locat[2] == 4: if (locat[0] - 1, locat[1], 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str( locat[1]) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] - 1, locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") if (locat[0] - 1, locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="Go") # Create possible transitions for initial conditions in only the transition region. Only transitions are # staying still, assigned to both action groups. This works because in implementation the controllers will # switch to the next horizon here else: sys_auto.transitions.add_comb({init}, {init}, sys_actions="Stop") sys_auto.transitions.add_comb({init}, {init}, sys_actions="Go") # Begin generating the specifications!! # Create the additional environmental variables, including signal for w region next to goal env_auto_vars = {'StopSignal', 'Fire'} if current_horizon == 1: env_auto_vars |= {'SyncSignal'} # Create the environment specifications, including progress related to sync signal next to goal env_auto_safe = set() env_auto_init = {'!StopSignal', '!Fire'} env_auto_prog = {'!StopSignal', '!Fire'} if current_horizon == 1: env_auto_prog |= {'SyncSignal'} # System variables and safety specification empty sets sys_auto_vars = set() sys_auto_safe = set() # Create stop signal requirements # TODO This should be changed to present actions... sys_auto_safe |= {'(StopSignal&&!Fire)->(X(sys_actions = "Stop"))'} sys_auto_safe |= {'(!(StopSignal&&!Fire))->(X(sys_actions = "Go"))'} # Add relevant phi variables to safety (i.e. all phi contained within this region). Never enter phi locations phi = '' for locat in transition_part[current_horizon]: state = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str( locat[2]) for names in phi_states: if state == names: phi = phi + '!(loc = "' + names + '")&&' phi = phi + 'True' sys_auto_safe |= {phi} # Empty initial progress sys_auto_prog = set() # Display progress statement to user print(('Beginning synthesis of W' + str(current_horizon) + ' for goal (' + str(x_goal_loc) + ',' + str(y_goal_loc) + ')!')) # Cycle through all initial conditions in this w region for synthesizing controller for idxn, locat in enumerate(w_part[current_horizon]): locat_sub = locat #if locat == (9, 8, 3): # print('here') # input('wait...') # Create checks to see if current position is viable initial condition current_state = 'Pos' + str(locat_sub[0]) + '_' + str( locat_sub[1]) + 'Ori' + str(locat_sub[2]) # Run through names in phi_states to check if it's included indicator = 0 for names in phi_states: if current_state == names: indicator = 1 # If current state passed, then add to initial condition and synthesize. Otherwise, move to next I.C. if indicator == 0: sys_auto_init = {'(loc = "' + current_state + '")'} else: continue # Create the progress statements and synthesize. Progress statements differ depending on current horizon # For horizon W1 if current_horizon == 1: # This section is the 'sync' version of specs, which is just the normal "correct" version print('Sync synthesis for ' + current_state) # Start timer for synthesis start_time = time.time() # Spec just states that the sync signal implies goal position is there sync_spec = '(SyncSignal)->GoalPos' sys_auto_prog = {sync_spec} # Create the GR spec for all the generated env and sys specs specs_final_sync = spec.GRSpec(env_auto_vars, sys_auto_vars, env_auto_init, sys_auto_init, env_auto_safe, sys_auto_safe, env_auto_prog, sys_auto_prog) # Synthesizer attributes specs_final_sync.moore = True option = 'omega' specs_final_sync.qinit = '\E \A' # synthesizer should find initial system values that satisfy # `env_init /\ sys_init` and work, for every environment variable # initial values that satisfy `env_init`. # SYNTHESIZE!!! ctrl_final_sync = synth.synthesize(option, specs_final_sync, env=None, sys=sys_auto, ignore_sys_init=True) # Failure results in adjustments to the horizon related to current I.C. if ctrl_final_sync is None: print('Failed to synthesize ' + current_state + ', moving to next w_part and transition_part') w_part[current_horizon + 1].append(locat) if locat not in transition_part[current_horizon + 1]: transition_part[current_horizon + 1].append(locat) w_part[current_horizon][idxn] = None transition_part[current_horizon].remove(locat) #if locat == (9, 8, 2): # print('here') # print(w_part[current_horizon]) # input('wait...') # Stopwatch and print synth_time = time.time() - start_time print(synth_time) # Write controller to relevant location if it synthesized filename = 'ctrls/Goal' + str(x_goal_loc) + '_' + str(y_goal_loc) + '/G' + str(x_goal_loc) + '_' + \ str(y_goal_loc) + current_state + '.py' #'_W' + str(current_horizon) + if ctrl_final_sync is not None: dumpsmach.write_python_case(filename, ctrl_final_sync) #if locat == (9, 8, 2): # print('here') # print(w_part[current_horizon]) # input('wait...') # All other horizons from the first one (>= W2) else: print('Synthesis for ' + current_state) # Start timer for synthesis start_time = time.time() # Generate progress to any area of transition region that aren't in the w region (inner layer) spec_inter = '((' for locat2 in transition_part[current_horizon]: if locat2 not in w_part[current_horizon]: locations = 'Pos' + str(locat2[0]) + '_' + str( locat2[1]) + 'Ori' + str(locat2[2]) spec_inter = spec_inter + 'loc = "' + locations + '")||(' # Finish tail end of progress spec (false is there to wrap up string generated by loop) spec_inter = spec_inter + 'False))' sys_auto_prog |= {spec_inter} # Create the GR spec for all the generated env and sys specs specs_inter = spec.GRSpec(env_auto_vars, sys_auto_vars, env_auto_init, sys_auto_init, env_auto_safe, sys_auto_safe, env_auto_prog, sys_auto_prog) # Synthesizer attributes specs_inter.moore = True option = 'omega' specs_inter.qinit = '\E \A' # synthesizer should find initial system values that satisfy # `env_init /\ sys_init` and work, for every environment variable # initial values that satisfy `env_init`. # SYNTHESIZE!!! ctrl_inter = synth.synthesize(option, specs_inter, sys=sys_auto, ignore_sys_init=True) # Failure results in adjustments to the horizon related to current I.C. if ctrl_inter is None: print('Failed to synthesize ' + current_state + ', moving to next w_part and transition_part') w_part[current_horizon + 1].append(locat) if locat not in transition_part[current_horizon + 1]: transition_part[current_horizon + 1].append(locat) w_part[current_horizon][idxn] = None transition_part[current_horizon].remove(locat) # Stopwatch and print synth_time = time.time() - start_time print(synth_time) # Write controller to relevant location if it synthesized filename = 'ctrls/Goal' + str(x_goal_loc) + '_' + str(y_goal_loc) + '/G' + str(x_goal_loc) + '_' + \ str(y_goal_loc) + current_state + '.py' #'_W' + str(current_horizon) + if ctrl_inter is not None: dumpsmach.write_python_case(filename, ctrl_inter)
logging.basicConfig(filename='sys_and_env_ts.log', level=logging.DEBUG, filemode='w') logger = logging.getLogger(__name__) from tulip import transys, spec, synth # the system's spatial layout: # +----+----+----+ # | X3 | X4 | X5 | # +----+----+----+ # | X0 | X1 | X2 | # +----+----+----+ sys = transys.FTS() sys.states.add_from(['X0', 'X1', 'X2', 'X3', 'X4', 'X5']) sys.states.initial.add_from(['X0', 'X1']) sys.transitions.add_from( [('X0', x) for x in {'X1', 'X3'}] + [('X1', x) for x in {'X0', 'X4', 'X2'}] + [('X2', x) for x in {'X1', 'X5'}] + [('X3', x) for x in {'X0', 'X4'}] + [('X4', x) for x in {'X3', 'X1', 'X5'}] + # compared to home_parking, this car can stay in lot next [('X5', x) for x in {'X4', 'X2', 'X5'}]) sys.atomic_propositions.add_from({'home', 'lot'}) sys.states.add('X0', ap={'home'}) sys.states.add('X5', ap={'lot'}) print sys
# between adjacent cells are allowed, which we model as a transition # system in this example (it would also be possible to do this via a # formula) # # We label the states using the following picture # # +----+----+----+ # | X3 | X4 | X5 | # +----+----+----+ # | X0 | X1 | X2 | # +----+----+----+ # # @system_dynamics_section@ # Create a finite transition system sys_water = transys.FTS() sys_water_vars = set() # Define the states of the system sys_water.states.add_from(['Water100', 'Water60', 'Water20', 'Water0']) sys_water.states.initial.add('Water100') # start in state X0 #sys_water.states.initial.add('Water60') #sys_water.states.initial.add('Water20') #sys_water.states.initial.add('Water0') # Define the allowable transitions sys_water.transitions.add_comb({'Water100'}, {'Water60', 'Water100'}) sys_water.transitions.add_comb({'Water60'}, {'Water100', 'Water20', 'Water60'}) sys_water.transitions.add_comb({'Water20'}, {'Water100', 'Water0', 'Water20'}) sys_water.transitions.add_comb({'Water0'}, {'Water100', 'Water0'})
""" Simple example with uncontrolled switching, for debugging 6 cell robot example. +---+---+---+ | 3 | 4 | 5 | +---+---+---+ | 0 | 1 | 2 | +---+---+---+ """ from tulip import spec, synth, transys import numpy as np from scipy import sparse as sp sys_swe = transys.FTS() sys_swe.env_actions.add_from({'sun', 'rain'}) # Environment actions are mutually exclusive. n = 2 states = ['s' + str(i) for i in xrange(n)] sys_swe.states.add_from(states) sys_swe.states.initial |= ['s0'] # different transitions possible, depending on weather transmat1 = sp.lil_matrix(np.array([[0, 1], [1, 0]])) sys_swe.transitions.add_adj(transmat1, states, env_actions='sun') # avoid being killed by environment transmat2 = sp.lil_matrix(np.array([[1, 0], [0, 1]])) sys_swe.transitions.add_adj(transmat2, states, env_actions='rain')
sys_prog = {'mem'} specs = spec.GRSpec(env_vars=env_vars, sys_vars=sys_vars, sys_init=sys_init, sys_safety=sys_safe, env_prog=env_prog, sys_prog=sys_prog) specs.moore = False specs.qinit = '\A \E' ctrl = synth.synthesize(specs) ctrl.save('gr1_arbitrary_set0.pdf') """ 2nd example """ sys = trs.FTS() states = {'a', 'b', 'c', 'd', 'e', 'foo'} sys.states.add_from(states) sys.states.initial.add('a') sys.transitions.add_from([('a', x) for x in {'b', 'd'}] + [('b', x) for x in {'a', 'e', 'c'}] + [('c', x) for x in {'b', 'foo'}] + [('d', x) for x in {'a', 'e'}] + [('e', x) for x in {'d', 'b', 'foo'}] + [('foo', x) for x in {'e', 'c'}])
def create_w_specs_all_init_cond(current_horizon, x_goal_loc, y_goal_loc, w_part, transition_part, dimension_x, dimension_y): # Don't synthesize for corner w regions (i.e. w region that's only a corner) that can't be fulfilled (... so ugly) # Note: Better way of doing this would be to not add corner regions to w_part... if (w_part[current_horizon] == [(dimension_x, dimension_y, 1)] or w_part[current_horizon] == [(dimension_x, dimension_y, 2)] or w_part[current_horizon] == [(dimension_x, dimension_y, 3)] or w_part[current_horizon] == [(dimension_x, dimension_y, 4)] or w_part[current_horizon] == [(dimension_x, 1, 1)] or w_part[current_horizon] == [(dimension_x, 1, 2)] or w_part[current_horizon] == [(dimension_x, 1, 3)] or w_part[current_horizon] == [(dimension_x, 1, 4)] or w_part[current_horizon] == [(1, dimension_y, 1)] or w_part[current_horizon] == [(1, dimension_y, 2)] or w_part[current_horizon] == [(1, dimension_y, 3)] or w_part[current_horizon] == [(1, dimension_y, 4)] or w_part[current_horizon] == [(1, 1, 1)] or w_part[current_horizon] == [(1, 1, 2)] or w_part[current_horizon] == [(1, 1, 3)] or w_part[current_horizon] == [(1, 1, 4)]): return # Create FTS and actions sys_auto = transys.FTS() sys_auto.sys_actions.add_from({'Stop', 'go', 'goVert', 'goHori'}) # Fake AP's to enable all specs related to base and goal position sys_auto.states.add_from(['fAKE']) sys_auto.atomic_propositions.add_from({'Base', 'goalPos'}) sys_auto.states['fAKE']['ap'] |= {'Base', 'goalPos'} # Add all AP's for the transition space, including those tied to 'Base' and 'goalPos' if present in transition space for locat in transition_part[current_horizon]: add_ap_sub = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str(locat[2]) sys_auto.states.add_from([add_ap_sub]) if locat[0] == 2 and locat[1] == 2: # TODO add some global indicator of the base location sys_auto.states[add_ap_sub]['ap'] |= {'Base'} if locat[0] == x_goal_loc and locat[1] == y_goal_loc: sys_auto.states[add_ap_sub]['ap'] |= {'goalPos'} # Initial condition, empty set sys_auto_init = set() #print(transition_part[current_horizon]) #print(w_part[current_horizon]) #input('uhmmm...') # NOTE: that current_horizon is 1, 2, 3, ... # Create all transitions through brute force method of checking existence of locations in the transition region next # to every starting point, dependent on the orientation. This is ran on transition region and inclusion in w region # is checked in creating transitions. This is because all w regions are contained in the transition region, and # transitions from a w region are different than those form just transition regions for locat in transition_part[current_horizon]: init = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str(locat[2]) if locat in w_part[current_horizon]: sys_auto.transitions.add_comb({init}, {init}, sys_actions="Stop") # Transitions allowed if orientation is up if locat[2] == 1: if (locat[0], locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0]) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="goVert") if (locat[0] + 1, locat[1] + 1, 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] + 1) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") if (locat[0] - 1, locat[1] + 1, 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] + 1) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") # Transitions allowed if orientation is right elif locat[2] == 2: if (locat[0] + 1, locat[1], 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1]) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="goHori") if (locat[0] + 1, locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") if (locat[0] + 1, locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") # Transitions allowed if orientation is down elif locat[2] == 3: if (locat[0], locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0]) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="goVert") if (locat[0] + 1, locat[1] - 1, 2) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] + 1) + '_' + str(locat[1] - 1) + 'Ori' + str(2) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") if (locat[0] - 1, locat[1] - 1, 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] - 1) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") # Transitions allowed if orientation is left elif locat[2] == 4: if (locat[0] - 1, locat[1], 4) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1]) + 'Ori' + str(4) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="goHori") if (locat[0] - 1, locat[1] + 1, 1) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] + 1) + 'Ori' + str(1) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") if (locat[0] - 1, locat[1] - 1, 3) in transition_part[current_horizon]: endloc = 'Pos' + str(locat[0] - 1) + '_' + str(locat[1] - 1) + 'Ori' + str(3) sys_auto.transitions.add_comb({init}, {endloc}, sys_actions="go") # Create possible transitions for initial conditions in only the transition region. Only transitions are # staying still, assigned to both action groups. This works because in implementation the controllers will # switch to the next horizon here else: sys_auto.transitions.add_comb({init}, {init}, sys_actions="Stop") sys_auto.transitions.add_comb({init}, {init}, sys_actions="go") check_hori = None if w_part[current_horizon - 1] is None: check_hori = None else: check_hori = None for ct in w_part[current_horizon - 1]: if ct is not None: if 'Pos' + str(ct[0]) + '_' + str(ct[1]) + 'Ori' + str(ct[2]) not in phi_states: check_hori = True # Begin generating the specifications!! # Create the additional environmental variables, including signal for w region next to goal env_auto_vars = {'fire'}#'StopSignal', if current_horizon == 1 or check_hori is None: env_auto_vars |= {'SyncHori'}#, 'SyncSignal', 'SyncVert'} #env_auto_vars |= {'SH1', 'SH2', 'SHb'}#, 'SV1', 'SV2', 'SVb', 'S1', 'S2', 'Sb'} # Create the environment specifications, including progress related to sync signal next to goal env_auto_safe = set() env_auto_init = {'!fire'}#'!StopSignal', env_auto_prog = {'!fire'}#'!StopSignal', #if current_horizon == 1 or check_hori is None: #env_auto_prog |= {'SyncSignal||SyncVert||SyncHori'} #if current_horizon == 1 or check_hori is None: #env_auto_safe |= {'SyncSignal->(!SyncVert && !SyncHori)'} #env_auto_safe |= {'SyncVert->(!SyncSignal && !SyncHori)'} #env_auto_safe |= {'SyncHori->(!SyncSignal && !SyncVert)'} # Create the specification for [](SyncHori->(SyncHori U Goal)) #env_auto_safe |= {'(SH1&&!SH2&&!SHb)||(!SH1&&SH2&&!SHb)||(!SH1&&!SH2&&SHb)'} #env_auto_init |= {'SH1'} #env_auto_prog |= {'SH1||SH2'} #env_auto_safe |= {'((SH1 && (!SyncHori || goalPos) && X SH1) || ' + # '(SH1 && (SyncHori && !goalPos) && X SH2) || ' + # '(SH2 && (SyncHori && !goalPos) && X SH2) || ' + # '(SH2 && !SyncHori && X SHb) || ' + # '(SH2 && (SyncHori && goalPos) && X SH1) || ' + # '(SHb && X SHb))'} #env_auto_safe |= {'SyncSignal->(!((!goalPos)U(!SyncSignal)))'} #env_auto_safe |= {'SyncVert->(!((!goalPos)U(!SyncVert)))'} #env_auto_safe |= {'SyncHori->(!((!goalPos)U(!SyncHori)))'} #env_auto_safe |= {'X VertPrev <-> SyncVert'} #env_auto_safe |= {'X HoriPrev <-> SyncHori'} #env_auto_safe |= {'(X (Sync_Hori_extra) && goalPos)->(SyncHori)'} #env_auto_safe |= {'(X(X (Sync_Hori_extra) && goalPos))->(SyncHori)'} #env_auto_safe |= {'(X (Sync_Vert_extra) && goalPos)->(SyncVert)'} # System variables and safety specification empty sets sys_auto_vars = set() sys_auto_safe = set() # Add relevant phi variables to safety (i.e. all phi contained within this region). Never enter phi locations phi = '' for locat in transition_part[current_horizon]: state = 'Pos' + str(locat[0]) + '_' + str(locat[1]) + 'Ori' + str(locat[2]) for names in phi_states: if state == names: phi = phi + '!(loc = "' + names + '")&&' phi = phi + 'True' sys_auto_safe |= {phi} # Empty initial progress sys_auto_prog = set() # Display progress statement to user print(('Beginning synthesis of W' + str(current_horizon) + ' for goal (' + str(x_goal_loc) + ',' + str(y_goal_loc) + ')!')) # Cycle through all initial conditions in this w region for synthesizing controller for idxn, locat in enumerate(w_part[current_horizon]): locat_sub = locat #if locat == (9, 8, 3): # print('here') # input('wait...') # Create checks to see if current position is viable initial condition current_state = 'Pos' + str(locat_sub[0]) + '_' + str(locat_sub[1]) + 'Ori' + str(locat_sub[2]) # Run through names in phi_states to check if it's included indicator = 0 for names in phi_states: if current_state == names: indicator = 1 # If current state passed, then add to initial condition and synthesize. Otherwise, move to next I.C. if indicator == 0: sys_auto_init = {'(loc = "' + current_state + '")'} else: continue # Create the progress statements and synthesize. Progress statements differ depending on current horizon # For horizon W1 if current_horizon == 1 or check_hori is None: # This section is the 'sync' version of specs, which is just the normal "correct" version print('Sync synthesis for ' + current_state) # Start timer for synthesis start_time = time.time() statement_hori = ((x_goal_loc + 1, y_goal_loc) not in obstacle_location and \ (x_goal_loc - 1, y_goal_loc) not in obstacle_location and 'Pos' + str(x_goal_loc + 1) + '_' + \ str(y_goal_loc) + 'Ori2' \ not in phi_states and 'Pos' + str(x_goal_loc + 1) + '_' + str(y_goal_loc) + 'Ori4' not in phi_states and \ 'Pos' + str(x_goal_loc - 1) + '_' + str(y_goal_loc) + 'Ori2' not in phi_states and 'Pos' + \ str(x_goal_loc - 1) + '_' + str(y_goal_loc) + \ 'Ori4' not in phi_states) statement_vert = ((x_goal_loc, y_goal_loc + 1) not in obstacle_location and \ (x_goal_loc, y_goal_loc - 1) not in obstacle_location and 'Pos' + str(x_goal_loc) + '_' + str(y_goal_loc + 1) + 'Ori1' \ not in phi_states and 'Pos' + str(x_goal_loc) + '_' + str(y_goal_loc + 1) + 'Ori3' not in phi_states and \ 'Pos' + str(x_goal_loc) + '_' + str(y_goal_loc - 1) +'Ori1' not in phi_states and 'Pos' + \ str(x_goal_loc) + '_' + str(y_goal_loc - 1) + 'Ori3' not in phi_states) sync_hori_cond = '(!Sync_Hori_extra && goalPos)' sync_vert_cond = '(!Sync_Vert_extra && goalPos)' sync_cond = '(X (Sync_extra) && goalPos)' sync_spec_hori = 'Sync_Hori_extra' sync_spec_vert = 'Sync_Vert_extra' sync_spec = 'Sync_extra' stop_condition_all = 'StopSignal&&!fire' if statement_hori and statement_vert: sys_auto_vars |= {'Sync_Hori_extra'}#, 'Sync_Vert_extra', 'Sync_extra'}#, 'SH_proxy', 'SV_proxy', 'S_proxy'}#, 'Sync_vert_prev', 'Sync_hori_prev'} sys_auto_init |= {'Sync_Hori_extra'}#, 'Sync_Vert_extra', 'Sync_extra'}#, '!SH_proxy', '!SV_proxy', '!S_proxy'} # Proxy variables and rules #sys_auto_safe |= {'(!SH_proxy&&!SV_proxy&&!S_proxy)||(SH_proxy&&!SV_proxy&&!S_proxy)||' + # '(!SH_proxy&&SV_proxy&&!S_proxy)||(!SH_proxy&&!SV_proxy&&S_proxy)'} #sys_auto_safe |= {'((SH_proxy&&!SV_proxy&&!S_proxy)||' + # '(!SH_proxy&&SV_proxy&&!S_proxy)||(!SH_proxy&&!SV_proxy&&S_proxy))->' + # '((SH_proxy <-> X SH_proxy)&&(SV_proxy <-> X SV_proxy)&&(S_proxy <-> X S_proxy))'} #sys_auto_safe |= {'(!SH_proxy&&!SV_proxy&&!S_proxy&&SyncHori)->(X SH_proxy)'} #sys_auto_safe |= {'(!SH_proxy&&!SV_proxy&&!S_proxy&&SyncVert)->(X SV_proxy)'} #sys_auto_safe |= {'(!SH_proxy&&!SV_proxy&&!S_proxy&&SyncSignal)->(X S_proxy)'} #sys_auto_safe |= {'(goalPos&&!Sync_Hori_extra)->(X !SH_proxy)'} #sys_auto_safe |= {'(goalPos&&!Sync_Vert_extra)->(X !SV_proxy)'} #sys_auto_safe |= {'(goalPos&&!Sync_extra)->(X !S_proxy)'} #sys_auto_safe |= {'(X Sync_vert_prev <-> SyncVert) && (X Sync_hori_prev <-> SyncHori)'} sys_auto_safe |= {'((!SyncHori)&& X Sync_Hori_extra) || ((X (Sync_Hori_extra) <-> goalPos)) || (Sync_Hori_extra && !SyncHori)'}#{'(X (Sync_Hori_extra) <-> goalPos) || (Sync_Hori_extra && !SyncHori)'} #sys_auto_safe |= {'((!SyncVert)&& X Sync_Vert_extra) || ((X (Sync_Vert_extra) <-> goalPos)) || (Sync_Vert_extra && !SyncVert)'} #sys_auto_safe |= {'(X (Sync_extra) <-> goalPos) || (Sync_extra && !S_proxy)'}#{'(X (Sync_extra) <-> goalPos) || (Sync_extra && !SyncSignal)'} #stop_condition1 = '(!(X(' + sync_hori_cond + '))&&!(' + sync_hori_cond + '))' #stop_condition2 = '(!(X(' + sync_vert_cond + '))&&!(' + sync_vert_cond + '))' #stop_condition3 = '(!(X(' + sync_cond + '))&&!(' + sync_cond + '))' #sys_auto_safe |= {'(' + stop_condition_all + '&&' + stop_condition1 + '&&' \ # + stop_condition2 + '&&' + stop_condition3 + ')->(X(sys_actions = "Stop"))'} #sys_auto_safe |= {'(!(' + stop_condition_all + '&&' + stop_condition1 + '&&' \ # + stop_condition2 + '&&' + stop_condition3 + '))->(X(sys_actions != "Stop"))'} sys_auto_safe |= {'X(sys_actions != "Stop")'} #sys_auto_safe |= {'(' + sync_hori_cond + ')->((X sys_actions = "goHori") && (sys_actions = "goHori"))'} #sys_auto_safe |= {'(' + sync_vert_cond + ')->((X(sys_actions = "goVert")) && (sys_actions = "goVert"))'} sys_auto_prog |= {sync_spec_hori} #sys_auto_prog |= {sync_spec_vert} #sys_auto_prog |= {sync_spec} '''elif statement_vert: stop_condition = '(StopSignal&&!fire&&!(X(' + sync_spec_vert + '))&&'+ \ '!(X(' + sync_spec + ')))' sys_auto_safe |= {stop_condition + '->(X(sys_actions = "Stop"))'} sys_auto_safe |= {'(!' + stop_condition + ')->(X(sys_actions != "Stop"))'} sys_auto_safe |= {'(X(' + sync_spec_vert + '))->(sys_actions = "goVert" && X(sys_actions = "goVert"))'} sys_auto_prog = {sync_spec_vert} sys_auto_prog |= {sync_spec} elif statement_hori: stop_condition = '(StopSignal&&!fire&&!(X(' + sync_spec_hori + '))&&'+ \ '!(X(' + sync_spec + ')))' sys_auto_safe |= {stop_condition + '->(X(sys_actions = "Stop"))'} sys_auto_safe |= {'(!' + stop_condition + ')->(X(sys_actions != "Stop"))'} sys_auto_safe |= {'(X(' + sync_spec_hori + '))->(sys_actions = "goHori" && X(sys_actions = "goHori"))'} sys_auto_prog = {sync_spec_hori} sys_auto_prog |= {sync_spec} else: stop_condition = '(StopSignal&&!fire)' sys_auto_safe |= {stop_condition + '->(X(sys_actions = "Stop"))'} sys_auto_safe |= {'(!' + stop_condition + ')->(X(sys_actions != "Stop"))'} sys_auto_prog = {sync_spec}''' #if statement_vert: # Spec just states that the sync signal implies goal position is there # Create the GR spec for all the generated env and sys specs specs_final_sync = spec.GRSpec(env_auto_vars, sys_auto_vars, env_auto_init, sys_auto_init, env_auto_safe, sys_auto_safe, env_auto_prog, sys_auto_prog) print(specs_final_sync) # Synthesizer attributes specs_final_sync.moore = True option = 'omega' specs_final_sync.qinit = '\E \A' # synthesizer should find initial system values that satisfy # `env_init /\ sys_init` and work, for every environment variable # initial values that satisfy `env_init`. # SYNTHESIZE!!! ctrl_final_sync = synth.synthesize(option, specs_final_sync, env=None, sys=sys_auto, ignore_sys_init=True) print(sys.getsizeof(ctrl_final_sync)) # failure results in adjustments to the horizon related to current I.C. if ctrl_final_sync is None: print('Failed to synthesize ' + current_state + ', moving to next w_part and transition_part') w_part[current_horizon + 1].append(locat) if locat not in transition_part[current_horizon + 1]: transition_part[current_horizon + 1].append(locat) w_part[current_horizon][idxn] = None transition_part[current_horizon].remove(locat) #if locat == (9, 8, 2): # print('here') # print(w_part[current_horizon]) # input('wait...') # Stopwatch and print synth_time = time.time() - start_time print(synth_time) # Write controller to relevant location if it synthesized filename = 'ctrls3/Goal' + str(x_goal_loc) + '_' + str(y_goal_loc) + '/G' + str(x_goal_loc) + '_' + \ str(y_goal_loc) + current_state + '.py' #'_W' + str(current_horizon) + if ctrl_final_sync is not None: dumpsmach.write_python_case(filename, ctrl_final_sync) #if locat == (9, 8, 2): # print('here') # print(w_part[current_horizon]) # input('wait...') # All other horizons from the first one (>= W2) else: print('Synthesis for ' + current_state) # Start timer for synthesis start_time = time.time() # Generate progress to any area of transition region that aren't in the w region (inner layer) spec_inter = '((' for locat2 in transition_part[current_horizon]: if locat2 not in w_part[current_horizon]: locations = 'Pos' + str(locat2[0]) + '_' + str(locat2[1]) + 'Ori' + str(locat2[2]) spec_inter = spec_inter + 'loc = "' + locations + '")||(' # Finish tail end of progress spec (false is there to wrap up string generated by loop) spec_inter = spec_inter + 'False))' sys_auto_prog |= {spec_inter} stop_condition = '(StopSignal&&!fire)' sys_auto_safe |= {stop_condition + '->(X(sys_actions = "Stop"))'} sys_auto_safe |= {'(!' + stop_condition + ')->(X(sys_actions != "Stop"))'} # Create the GR spec for all the generated env and sys specs specs_inter = spec.GRSpec(env_auto_vars, sys_auto_vars, env_auto_init, sys_auto_init, env_auto_safe, sys_auto_safe, env_auto_prog, sys_auto_prog) # Synthesizer attributes specs_inter.moore = True option = 'omega' specs_inter.qinit = '\E \A' # synthesizer should find initial system values that satisfy # `env_init /\ sys_init` and work, for every environment variable # initial values that satisfy `env_init`. # SYNTHESIZE!!! ctrl_inter = synth.synthesize(option, specs_inter, sys=sys_auto, ignore_sys_init=True) # Failure results in adjustments to the horizon related to current I.C. if ctrl_inter is None: print('Failed to synthesize ' + current_state + ', moving to next w_part and transition_part') w_part[current_horizon + 1].append(locat) if locat not in transition_part[current_horizon + 1]: transition_part[current_horizon + 1].append(locat) w_part[current_horizon][idxn] = None transition_part[current_horizon].remove(locat) # Stopwatch and print synth_time = time.time() - start_time print(synth_time) # Write controller to relevant location if it synthesized filename = 'ctrls/Goal' + str(x_goal_loc) + '_' + str(y_goal_loc) + '/G' + str(x_goal_loc) + '_' + \ str(y_goal_loc) + current_state + '.py' #'_W' + str(current_horizon) + if ctrl_inter is not None: dumpsmach.write_python_case(filename, ctrl_inter)
def runPaperExample(exampleRun, ver='1', riskgt=17, energygt=0): # set initial variables if (exampleRun == 'test1'): ver = '1' riskgt = 17 energygt = 0 elif (exampleRun == 'test2'): ver = '2' riskgt = 17 energygt = 6 elif (exampleRun == 'test3'): ver = '3' riskgt = 16 energygt = 6 # set logfile import logging logging.basicConfig(filename='deliberative_action_planner_%s.log' % ver, level=logging.INFO, filemode='w') # level=logging.DEBUG logger = logging.getLogger(__name__) # Create a finite transition system sys_sws = transys.FTS() # system actions only, no (open) env. yet # add the states and actions #sys_sws.states.add_from(['s1','s2','s3','s4','s5']) for i in range(1, 5 + 1): sys_sws.states.add('s' + str(i)) #sys_sws.actions.add_from(['a12_1','a12_2','a23_1', 'a23_2', 'a15_1', 'a15_2', 'a14_1', 'a45_1', 'a35_1']) # then set up the transitions (state1, action1 -> state2) for numlist in [[1, 2, 2], [2, 3, 2], [1, 5, 2], [1, 4, 1], [4, 5, 1], [3, 5, 1]]: st1 = numlist[ 0] # [s"#1" loc1, s"#2" loc2, number of actions a"#1#2_#"] st2 = numlist[1] numactions = numlist[2] st1str = 's' + str(st1) st2str = 's' + str(st2) #sys_sws.states.add_from([st1str,st2str]) # could do this instead of above for i in range(1, numactions + 1): astr = 'a' + str(st1) + str(st2) + '_' + str(i) sys_sws.actions.add(astr) # could do this instead of above sys_sws.transitions.add(st1str, st2str, actions=astr) sys_sws.transitions.add(st2str, st1str, actions=astr) # then set up transitions for (state1, wait -> state1) sys_sws.actions.add('wait') for st1 in range(1, 5 + 1): st1str = 's' + str(st1) sys_sws.transitions.add(st1str, st1str, actions='wait') # set s1 as initial state initial_state_str = 's1' #initial_state_str = 's2' sys_sws.states.initial.add(initial_state_str) # This is what is visible to the outside world (and will go into synthesis method) print( sys_sws ) # show the Finite Transition System, make sure it was encoded properly sys_sws.save('deliberative_%sa.pdf' % ver) # save the visual diagram of the FTS, for same reason # sys_sws.save() shows all possible transitions between states according to actions print("Done saving deliberative_%sa.pdf" % ver) # # Environment variables and specification # # The environment can issue a park signal that the robot just respond # to by moving to the lower left corner of the grid. We assume that # the park signal is turned off infinitely often. # env_vars = set() # empty set env_init = set() # empty set env_prog = set() # empty set env_safe = set() # empty set # # System specification # # The system specification is that the robot should (repeatedly?) revisit # the rightmost spire (this is because there are no 'wait' or 'stay in same # state' actions currently). # does sys_vars actually use the "0" value? it doesn't seem to... # basically, looks like a "0" value pulls the value completely off the stack (as False?), in the 'atomic proposition' sense of things # so, we want to avoid using value=0 for this kind of stuff! ^_^ # note: for gr1c, lower bound must be zero (0) print("Writing up goals and such for system") print("Writing up sys vars and such for system") sys_vars = dict() sys_init = set() sys_prog = set() sys_safe = set() sys_init |= {'sys_actions=wait'} # start in wait mode goalstr = 's5' #goalstr = 's3' sys_prog |= {'loc=%s' % goalstr} # goal --> []<> (get to s5) sys_safe |= { 'loc=%s -> next(loc=%s)' % (goalstr, goalstr) } # then stay there forever # this didn't seem to work with the FTS before, now does for some reason, not sure what's going on... energylo = 0 energyhi = 20 sys_vars.update({'energy': (energylo, energyhi)}) sys_init |= {'energy=%d' % energyhi} sys_safe |= {'energy > %d' % energygt } # must keep fuel/energy usage above energygt risklo = 0 riskhi = 20 sys_vars.update({'risk': (risklo, riskhi)}) sys_init |= {'risk=%d' % riskhi} sys_safe |= {'risk > %d' % riskgt} # must keep risk usage above riskgt # 0 1 2 3 4 5 6 7 8 9 allactStr = [ 'a35_1', 'a23_1', 'a23_2', 'a12_1', 'a12_2', 'a15_2', 'a15_1', 'a45_1', 'a14_1', 'wait' ] alldropenergy = [4, 3, 6, 2, 3, 7, 6, 5, 3, 0] alldroprisk = [1, 4, 0, 2, 1, 1, 2, 0, 0, 0] for actStr, energydrop, riskdrop in zip(allactStr, alldropenergy, alldroprisk): #energystr = energyStr(energylo,energyhi,energydrop) energystr = dropStr('energy', energylo, energyhi, energydrop) sys_safe |= { 'sys_actions=%s -> (%s && (X(energy=0) <-> energy<=%d))' % (actStr, energystr, alldropenergy[i - 1]) } # wait action keeps energy at same level (no energy used) riskstr = dropStr('risk', risklo, riskhi, riskdrop) sys_safe |= { 'sys_actions=%s -> (%s && (X(risk=0) <-> risk<=%d))' % (actStr, riskstr, alldroprisk[i - 1]) } # wait action keeps energy at same level (no energy used) # 0 1 2 3 4 # atakepicture# alldropenergy2 = [0, 0, 0, 0, 0] alldroprisk2 = [0, 0, 0, 0, 0] for i in range(1, 5 + 1): # [1] atakepicture1,picAtS1Taken, ... actStr = 'atakepicture%d' % i energystr = dropStr('energy', energylo, energyhi, alldropenergy2[i - 1]) sys_safe |= { 'sys_actions=%s -> (%s && (X(energy=0) <-> energy<=%d))' % (actStr, energystr, alldropenergy2[i - 1]) } # wait action keeps energy at same level (no energy used) riskstr = dropStr('risk', risklo, riskhi, alldroprisk2[i - 1]) sys_safe |= { 'sys_actions=%s -> (%s && (X(risk=0) <-> risk<=%d))' % (actStr, riskstr, alldroprisk2[i - 1]) } # wait action keeps energy at same level (no energy used) actboolStr = 'picAtS%dTaken' % i locStr = 's%d' % i sys_sws.actions.add(actStr) sys_sws.transitions.add('s%d' % i, 's%d' % i, actions=actStr) sys_vars.update({actboolStr: 'boolean'}) sys_init |= {'!%s' % actboolStr} sys_safe |= { '(energy>%d && loc=%s && sys_actions=%s) -> X(%s)' % (alldropenergy2[i - 1], locStr, actStr, actboolStr) } sys_safe |= { '(energy<=%d && loc=%s && sys_actions=%s) -> X(energy=0)' % (alldropenergy2[i - 1], locStr, actStr) } sys_safe |= { '(sys_actions!=%s && !%s) -> (X(!%s))' % (actStr, actboolStr, actboolStr) } # don't allow other actions to arbitrarily set this to True sys_safe |= {'%s -> X(%s)' % (actboolStr, actboolStr) } # if picture is taken, 'stays' taken sys_prog |= {'picAtS2Taken'} # goal --> trying to take picture at s2 # 0 1 2 3 4 # atakesample# alldropenergy3 = [1, 1, 1, 1, 1] alldroprisk3 = [0, 0, 0, 0, 0] for i in range(1, 5 + 1): # [1] atakepicture1,picAtS1Taken, ... actStr = 'atakesample%d' % i energystr = dropStr('energy', energylo, energyhi, alldropenergy3[i - 1]) sys_safe |= { 'sys_actions=%s -> (%s && (X(energy=0) <-> energy<=%d))' % (actStr, energystr, alldropenergy3[i - 1]) } # wait action keeps energy at same level (no energy used) riskstr = dropStr('risk', risklo, riskhi, alldroprisk3[i - 1]) sys_safe |= { 'sys_actions=%s -> (%s && (X(risk=0) <-> risk<=%d))' % (actStr, riskstr, alldroprisk3[i - 1]) } # wait action keeps energy at same level (no energy used) actboolStr = 'samAtS%dTaken' % i locStr = 's%d' % i sys_sws.actions.add(actStr) sys_sws.transitions.add('s%d' % i, 's%d' % i, actions=actStr) sys_vars.update({actboolStr: 'boolean'}) sys_init |= {'!%s' % actboolStr} sys_safe |= { '(energy>%d && loc=%s && sys_actions=%s) -> X(%s)' % (alldropenergy3[i - 1], locStr, actStr, actboolStr) } sys_safe |= { '(energy<=%d && loc=%s && sys_actions=%s) -> X(energy=0)' % (alldropenergy3[i - 1], locStr, actStr) } sys_safe |= { '(sys_actions!=%s && !%s) -> (X(!%s))' % (actStr, actboolStr, actboolStr) } # don't allow other actions to arbitrarily set this to True sys_safe |= {'%s -> X(%s)' % (actboolStr, actboolStr) } # if sample is taken, 'stays' taken #sys_prog |= {'samAtS5Taken'} # goal --> trying to take sample at s5 # # after all sys_goal specs are written... # goal_conditions = '' for goalpieceStr in list(sys_prog): goal_conditions += goalpieceStr + ' && ' goal_conditions = goal_conditions[0:len(goal_conditions) - 4] # remove trailing ' && ' # set up stepcounter at the end of everything, after all sys_goal specs are written: steplo = 0 stephi = 8 # lower this number to try and force gr1c to be more efficient sys_vars.update({'stepCounter': (steplo, stephi)}) sys_init |= {'stepCounter=%d' % steplo} stepstr = riseStr('stepCounter', steplo, stephi, 1) sys_safe |= { '!(%s) -> %s' % (goal_conditions, stepstr) } # goal_conditions not met implies stepCounter increases by 1 each time stepstr = riseStr('stepCounter', steplo, stephi, 0) sys_safe |= { '(%s) -> %s' % (goal_conditions, stepstr) } # goal_conditions met implies stepCounter doesn't increase (any more) # then lower stephi to try and force gr1c to find a more efficient (shortest number of actions) solution sys_safe |= { 'stepCounter < %d' % (stephi) } # must keep counter below stephi; requires below that we stop counting steps after we finish all goals # add this in so we can tell when we're just doing extra stuff post-whatever sys_vars.update({'sysgoalsReached': 'boolean'}) sys_init |= {'!sysgoalsReached'} sys_safe |= {'!(%s) <-> !sysgoalsReached' % (goal_conditions) } # goal_conditions not met implies sysgoals(not_yet)Reached sys_safe |= {'(%s) <-> sysgoalsReached' % (goal_conditions) } # goal_conditions met implies sysgoalsReached # changes might've been made this far down, so show again... print( sys_sws ) # show the Finite Transition System, make sure it was encoded properly sys_sws.save('deliberative_%sb.pdf' % ver) # save the visual diagram of the FTS, for same reason print("Done saving deliberative_%sb.pdf" % ver) print("Creating spec for sys_sws system") # Create the specification specs = spec.GRSpec(env_vars=env_vars, sys_vars=sys_vars, env_init=env_init, sys_init=sys_init, env_safety=env_safe, sys_safety=sys_safe, env_prog=env_prog, sys_prog=sys_prog) print(specs.pretty()) # GRSpec(env_vars=None, sys_vars=None, env_init='', sys_init='', env_safety='', sys_safety='', env_prog='', sys_prog='') # (env_init & []env_safety & []<>env_prog_1 & []<>env_prog_2 & ...) # -> (sys_init & []sys_safety & []<>sys_prog_1 & []<>sys_prog_2 & ...) # # C{env_vars}: alias for C{input_variables} of L{LTL}, concerning variables that are determined by the environment # C{env_init}: a list of string that specifies the assumption about the initial state of the environment. # C{env_safety}: a list of string that specifies the assumption about the evolution of the environment state. # C{env_prog}: a list of string that specifies the justice assumption on the environment. # C{sys_vars}: alias for C{output_variables} of L{LTL}, concerning variables that are controlled by the system. # C{sys_init}: a list of string that specifies the requirement on the initial state of the system. # C{sys_safety}: a list of string that specifies the safety requirement. # C{sys_prog}: a list of string that specifies the progress requirement. print("Done creating spec for sys_sws system") # Controller synthesis # # At this point we can synthesize the controller using one of the available # methods. Here we make use of gr1c. # print("Synthesizing solution for sys_sws system") ctrl = synth.synthesize('gr1c', specs, sys=sys_sws) print("Done synthesizing solution for sys_sws system") print("Creating .png file for sys_sws system") if ctrl is None: print( "Got gr1c error, not attempting save =or= print-to-screen =or= MealyMachine dumpsmach" ) else: # Generate a graphical representation of the controller for viewing if not ctrl.save('deliberative_%s_sws.png' % ver): print("Couldn't save .png file, printing ctrl instead") print(ctrl) print("Done printing ctrl instead") print("Done creating .png file for sys_sws system") print("Writing MealyMachine out via dumpsmach") # ctrl is a MealyMachine from tulip import dumpsmach dumpsmach.write_python_case(filename='dumpsmachtest_dlap%s.py' % ver, M=ctrl, classname="TulipStrategy", start='Sinit') print("Done writing MealyMachine out to dumpsmachtest_dlap%s.py" % ver)
def test_var_name_conflicts(): """Check redefinitions between states, actions, atomic props.""" def conversion_raises(f, ofts): with assert_raises(AssertionError): f(ofts, ignore_initial=True, statevar='loc', bool_actions=False) # FTS to spec # states vs APs sys = transys.FTS() sys.states.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) # states vs sys_actions sys = transys.FTS() sys.states.add('out') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys = transys.FTS() sys.states.add('sys_actions') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) # states vs env_actions env = transys.FTS() env.states.add('out') env.env_actions.add('out') env.owner = 'env' conversion_raises(synth.env_to_spec, env) env = transys.FTS() env.states.add('env_actions') env.env_actions.add('out') env.owner = 'env' conversion_raises(synth.env_to_spec, env) # APs vs sys_actions sys = transys.FTS() sys.states.add('s0') sys.atomic_propositions.add('out') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.atomic_propositions.add('sys_actions') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) # APs vs env_actions env = transys.FTS() env.states.add('s0') env.atomic_propositions.add('out') env.env_actions.add('out') env.owner = 'env' conversion_raises(synth.env_to_spec, env) env = transys.FTS() env.states.add('s0') env.atomic_propositions.add('env_actions') env.env_actions.add('out') env.owner = 'env' conversion_raises(synth.env_to_spec, env) # OpenFTS to spec # states vs APs sys = transys.FTS() sys.states.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) # states vs sys_actions sys = transys.FTS() sys.states.add('out') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('sys_actions') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) # states vs env_actions sys = transys.FTS() sys.states.add('out') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('env_actions') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) # sys_actions vs APs sys = transys.FTS() sys.states.add('s0') sys.sys_actions.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.sys_actions.add('out') sys.atomic_propositions.add('sys_actions') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) # env_actions vs APs sys = transys.FTS() sys.states.add('s0') sys.env_actions.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.env_actions.add('out') sys.atomic_propositions.add('env_actions') conversion_raises(synth.sys_to_spec, sys) sys.owner = 'env' conversion_raises(synth.env_to_spec, sys)
# NO, 26 Jul 2013. import numpy as np from scipy import sparse as sp from tulip import spec from tulip import synth from tulip import transys ############################### # Switched system with 4 modes: ############################### # In this scenario we have limited actions "left, right, up, down" with # certain (nondeterministic) outcomes # Create a finite transition system sys_sws = transys.FTS() sys_sws.sys_actions.add_from({'right', 'up', 'left', 'down'}) # str states n = 6 states = transys.prepend_with(range(n), 's') sys_sws.states.add_from(set(states)) sys_sws.states.initial.add_from({'s0', 's3'}) sys_sws.atomic_propositions.add_from(['home', 'lot']) state_labels = [{'home'}, set(), set(), set(), set(), {'lot'}] # Add states and decorate TS with state labels (aka atomic propositions) for state, label in zip(states, state_labels): sys_sws.states.add(state, ap=label)
def test_var_name_conflicts(): """Check redefinitions between states, actions, atomic props.""" conversion_raises = lambda x, y: assert_raises( Exception, spec=x, sys=y, ignore_initial=True, statevar='loc', bool_actions=False) # FTS to spec # states vs APs sys = transys.FTS() sys.states.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) # states vs sys_actions sys = transys.FTS() sys.states.add('out') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys = transys.FTS() sys.states.add('sys_actions') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) # states vs env_actions env = transys.FTS() env.states.add('out') env.env_actions.add('out') conversion_raises(synth.env_to_spec, env) env = transys.FTS() env.states.add('env_actions') env.env_actions.add('out') conversion_raises(synth.env_to_spec, env) # APs vs sys_actions sys = transys.FTS() sys.states.add('s0') sys.atomic_propositions.add('out') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.atomic_propositions.add('sys_actions') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) # APs vs env_actions env = transys.FTS() env.states.add('s0') env.atomic_propositions.add('out') env.env_actions.add('out') conversion_raises(synth.env_to_spec, env) env = transys.FTS() env.states.add('s0') env.atomic_propositions.add('env_actions') env.env_actions.add('out') conversion_raises(synth.env_to_spec, env) # OpenFTS to spec # states vs APs sys = transys.FTS() sys.states.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) # states vs sys_actions sys = transys.FTS() sys.states.add('out') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('sys_actions') sys.sys_actions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) # states vs env_actions sys = transys.FTS() sys.states.add('out') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('env_actions') sys.env_actions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) # sys_actions vs APs sys = transys.FTS() sys.states.add('s0') sys.sys_actions.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.sys_actions.add('out') sys.atomic_propositions.add('sys_actions') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) # env_actions vs APs sys = transys.FTS() sys.states.add('s0') sys.env_actions.add('out') sys.atomic_propositions.add('out') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys) sys = transys.FTS() sys.states.add('s0') sys.env_actions.add('out') sys.atomic_propositions.add('env_actions') conversion_raises(synth.sys_to_spec, sys) conversion_raises(synth.env_to_spec, sys)
def full_road_ex(): import discretize from tulip import transys sys = transys.FTS() road(sys, 0, 0, 0, 5, 0.4) road(sys, 0, 5, 5, 5, 0.4) road(sys, 5, 5, 5, 0, 0.4) road(sys, 5, 0, 0, 0, 0.4) add_states(['Xequal0spaceYequal0spacephiequal' + str(3)], sys) #print sys.states() add_transitions(['Xequal0spaceYequal3.75spacephiequal' + str(2)], ['Xequal1.25spaceYequal5spacephiequal' + str(0)], sys) add_transitions(['Xequal3.75spaceYequal5spacephiequal' + str(0)], ['Xequal5spaceYequal3.75spacephiequal' + '6'], sys) add_transitions(['Xequal5spaceYequal1.25spacephiequal' + '6'], ['Xequal3.75spaceYequal0spacephiequal' + str(4)], sys) add_transitions(['Xequal1.25spaceYequal0spacephiequal' + str(4)], ['Xequal0spaceYequal1.25spacephiequal' + str(2)], sys) add_transitions(['Xequal0spaceYequal0spacephiequal' + str(3)], ['Xequal0spaceYequal0spacephiequal' + str(3)], sys) add_transitions(['Xequal0spaceYequal0spacephiequal' + str(3)], ['Xequal0spaceYequal1.25spacephiequal' + str(2)], sys) add_states(['Xequal1.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal0spaceYequal1.25spacephiequal' + str(2)], ['Xequal1.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal1.25spaceYequal2.5spacephiequal' + str(0)], ['Xequal1.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal1.25spaceYequal2.5spacephiequal' + str(0)], ['Xequal0spaceYequal1.25spacephiequal' + str(2)], sys) add_states(['Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequal0spaceYequal1.25spacephiequal' + str(2)], ['Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4)], ['Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4)], ['Xequal0spaceYequal1.25spacephiequal' + str(2)], sys) add_states(['Xequal2.5spaceYequal6.25spacephiequal' + str(2)], sys) add_transitions(['Xequal1.25spaceYequal5spacephiequal' + str(0)], ['Xequal2.5spaceYequal6.25spacephiequal' + str(2)], sys) add_transitions(['Xequal2.5spaceYequal6.25spacephiequal' + str(2)], ['Xequal2.5spaceYequal6.25spacephiequal' + str(2)], sys) add_transitions(['Xequal2.5spaceYequal6.25spacephiequal' + str(2)], ['Xequal1.25spaceYequal5spacephiequal' + str(0)], sys) add_states(['Xequal2.5spaceYequal3.75spacephiequal' + str(6)], sys) add_transitions(['Xequal1.25spaceYequal5spacephiequal' + str(0)], ['Xequal2.5spaceYequal3.75spacephiequal' + str(6)], sys) add_transitions(['Xequal2.5spaceYequal3.75spacephiequal' + str(6)], ['Xequal2.5spaceYequal3.75spacephiequal' + str(6)], sys) add_transitions(['Xequal2.5spaceYequal3.75spacephiequal' + str(6)], ['Xequal1.25spaceYequal5spacephiequal' + str(0)], sys) add_states(['Xequal6.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal5spaceYequal3.75spacephiequal' + str(6)], ['Xequal6.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal6.25spaceYequal2.5spacephiequal' + str(0)], ['Xequal6.25spaceYequal2.5spacephiequal' + str(0)], sys) add_transitions(['Xequal6.25spaceYequal2.5spacephiequal' + str(0)], ['Xequal5spaceYequal3.75spacephiequal' + str(6)], sys) add_states(['Xequal3.75spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequal5spaceYequal3.75spacephiequal' + str(6)], ['Xequal3.75spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequal3.75spaceYequal2.5spacephiequal' + str(4)], ['Xequal3.75spaceYequal2.5spacephiequal' + str(4)], sys) add_transitions(['Xequal3.75spaceYequal2.5spacephiequal' + str(4)], ['Xequal5spaceYequal3.75spacephiequal' + str(6)], sys) add_states(['Xequal2.5spaceYequal1.25spacephiequal' + str(2)], sys) add_transitions(['Xequal3.75spaceYequal0spacephiequal' + str(4)], ['Xequal2.5spaceYequal1.25spacephiequal' + str(2)], sys) add_transitions(['Xequal2.5spaceYequal1.25spacephiequal' + str(2)], ['Xequal2.5spaceYequal1.25spacephiequal' + str(2)], sys) add_transitions(['Xequal2.5spaceYequal1.25spacephiequal' + str(2)], ['Xequal3.75spaceYequal0spacephiequal' + str(4)], sys) add_states(['Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6)], sys) add_transitions(['Xequal3.75spaceYequal0spacephiequal' + str(4)], ['Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6)], sys) add_transitions(['Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6)], ['Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6)], sys) add_transitions(['Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6)], ['Xequal3.75spaceYequal0spacephiequal' + str(4)], sys) sys.atomic_propositions.add_from({'pSpace'}) sys.states.add('Xequal1.25spaceYequal2.5spacephiequal' + str(0), ap={'pSpace'}) sys.states.add('Xequalmmm1.25spaceYequal2.5spacephiequal' + str(4), ap={'pSpace'}) sys.states.add('Xequal2.5spaceYequal6.25spacephiequal' + str(2), ap={'pSpace'}) sys.states.add('Xequal2.5spaceYequal3.75spacephiequal' + str(6), ap={'pSpace'}) sys.states.add('Xequal6.25spaceYequal2.5spacephiequal' + str(0), ap={'pSpace'}) sys.states.add('Xequal3.75spaceYequal2.5spacephiequal' + str(4), ap={'pSpace'}) sys.states.add('Xequal2.5spaceYequal1.25spacephiequal' + str(2), ap={'pSpace'}) sys.states.add('Xequal2.5spaceYequalmmm1.25spacephiequal' + str(6), ap={'pSpace'}) return sys