def _confirm_add(self): """ Confirm new mode addition """ # ID trans_id = self.transition_id.get() # Source and Destination for mode_id in self.mode_dict: if (self.mode_dict[mode_id] == self.source_str.get()): src = mode_id elif (self.mode_dict[mode_id] == self.destination_str.get()): dest = mode_id # Guard guard = Guard(self.guard_str.get()) # Actions actions = [] for action in self.action_toggle.get_rows(): if ((action.get()).strip()): actions.append(Action(action.get())) transition = Transition(guard, actions, trans_id, src, dest) self.automaton.add_transition(transition) Session.write("Transition Entry Confirmed.\n") self.changed = True self.destroy() return
def _confirm_edit(self): """" Commits changes to Session. Does NOT save changes """ # ID self.transition.id = self.transition_id.get() # Source and Destination for mode_id in self.mode_dict: if (self.mode_dict[mode_id] == self.source_str.get()): self.transition.source = mode_id elif (self.mode_dict[mode_id] == self.destination_str.get()): self.transition.destination = mode_id # Guard self.transition.guard = Guard(self.guard_str.get()) # Actions self.transition.clear_actions() for action in self.action_toggle.rows: if ((action.get()).strip()): self.transition.add_action(Action(action.get())) Session.write("Transition Entry Confirmed.\n") self.changed = True self.destroy() return
def _delete(self): """ Delete active Mode """ # Build list of transitions that would be deleted del_trans = [] for tran in self.automaton.transitions: if((tran.source == self.mode.id) or \ (tran.destination == self.mode.id)): del_trans.append(tran) # Messagebox warning user of transitions that also will be deleted msg = "Delete " + self.mode.name + "(" + str(self.mode.id) + ") ?\n" msg += "WARNING: The following transitions will also be deleted:\n" for tran in del_trans: msg += tran.name + '\n' if (messagebox.askyesno('Delete Mode', msg)): self.automaton.remove_mode(self.mode) for tran in del_trans: self.automaton.remove_transition(tran) Session.write("Mode Deleted.\n") self.changed = True else: Session.write("Mode Deletion Canceled.\n") self.changed = False self.destroy() return
def _confirm_edit(self): """ Commit changes to Session. Does NOT save changes """ # Name self.mode.name = self.name.get() # ID self.mode.id = self.mode_id.get() # Initial self.mode.initial = self.initial.get() # Flows self.mode.clear_dais() for raw_text in self.flow_toggle.get_rows(): if ((raw_text.get()).strip()): self.mode.add_dai(DAI(raw_text.get())) # Invariants self.mode.clear_invariants() for raw_text in self.invariant_toggle.get_rows(): if ((raw_text.get()).strip()): self.mode.add_invariant(Invariant(raw_text.get())) Session.write("Mode Entry Confirmed.\n") self.changed = True self.destroy() return
def _confirm(self): """ Commit changes to Session. Does NOT save these changes. """ self.automaton.reset_vars() self.automaton.reset_thinvars() scope_dict = { # Convert displayed scopes to values stored 'Local': LOCAL, # LOCAL = 'LOCAL_DATA' 'Input': INPUT, # INPUT = 'INPUT_DATA' 'Output': OUTPUT # OUTPUT = 'OUTPUT_DATA' } for i in range(0, self.var_index): name = (self.names[i].get()).strip() thin = self.thins[i].get() type_ = self.types[i].get() # Reserved word scope = scope_dict[self.scopes[i].get()] if not name: # Delete variables by erasing their name continue if thin: self.automaton.add_thinvar( Variable(name=name, type=type_, scope=scope)) else: self.automaton.add_var( Variable(name=name, type=type_, scope=scope)) Session.write("Variable Entry Confirmed.\n") self.changed = True self.destroy() return
def _init_widgets(self): Session.write("Initializing the Plot Tab") self.display = PlotDisplay(self) self.display.pack(expand=True, fill=tk.BOTH, side=tk.LEFT, anchor=tk.E) self.sidebar = PlotSidebar(self) self.sidebar.pack(expand=True, fill=tk.Y, side=tk.TOP, anchor=tk.E)
def _clear_model(self, event=None): """ Clear treeview display """ Session.write("Clearing model tree...") self.delete(*self.get_children()) Session.write(" Done.\n") return
def _cancel(self): """ Cancels changes made in popup """ Session.write("Variable Entry Canceled.") self.changed = False self.destroy() return
def _cancel(self): """ Cancels changes made in popup """ Session.write("Transition Entry Canceled.\n") self.changed = False self.destroy() return
def _confirm_edit(self): self.automaton.name = self.name.get() Session.write("Automaton Entry Confirmed.\n") self.changed = True self.destroy() return
def _confirm_add(self): self.hybrid.add_automaton(Automaton(self.name.get())) Session.write("Automaton Entry Confirmed.\n") self.changed = True self.destroy() return
def open_xml(self, event=None): self.editor.delete('1.0', 'end-1c') if not Session.file_path: return Session.write("Opening xml...") with open(Session.file_path, 'r') as f: self.editor.insert('end-1c', f.read()) Session.write(" Done.\n") return
def _init_widgets(self): Session.write("Initializing XML Editor...") self.editor = ScrolledText(self) self.editor.pack(expand=TRUE, fill=BOTH, side=TOP, anchor=E) self.feedback = Session.add_feedback_frame(self) self.feedback.pack(fill=X, side=BOTTOM, anchor=E) Session.write(" Done.\n") return
def _delete(self): if messagebox.askyesno("Delete Automaton", "Delete " + self.automaton.name + "?"): self.hybrid.remove_automaton(self.automaton) Session.write("Automaton Deleted.\n") self.changed = True else: Session.write("Automaton Deletion Canceled.\n") self.chagned = False self.destroy() return
def save(hyxml_text=None): if Session.file_path is None: Session.write("ERROR: SAVING WITH NO FILEPATH\n") if hyxml_text is None: FileHandler.save_tree() else: FileHandler.save_hyxml(hyxml_text) FileHandler.open_file(Session.file_path) Session.file_saved = True return
def plot_line(data_points, horizontal_index, vertical_indices, variable_list, mode_list, title, filename): Session.write("Generating simulation plot... ") bokeh_plot = figure(title=title) x_axis = [] y_axes = [] for i in range(len(vertical_indices)): y_axes.append([]) toggle = True plot_index = -1 for line in data_points: if float(line[0]) == 0: plot_index += 1 x_axis.append([]) for y_index in range(len(vertical_indices)): y_axes[y_index].append([]) toggle = True if toggle: x_axis[plot_index].append(float(line[horizontal_index])) for y_index, vert_index in enumerate(vertical_indices): y_axes[y_index][plot_index].append(float(line[vert_index])) toggle = False else: toggle = True for i in range(plot_index+1): for j, y_axis in enumerate(y_axes): bokeh_plot.line(x_axis[i], y_axis[i], line_width=2, color=PLOT_COLORS[j-1], legend_label=variable_list[vertical_indices[j]]) # X - axis bokeh_plot.xaxis.axis_label = variable_list[horizontal_index] # Y - axis y_axis_label = variable_list[vertical_indices[0]] for i in range(1, len(vertical_indices)): y_axis_label += ", " + variable_list[vertical_indices[i]] bokeh_plot.yaxis.axis_label = y_axis_label save(bokeh_plot, filename=filename+'.html', title=title) export_png(bokeh_plot, filename=filename+'.png' ) Session.write("Done.\n")
def _delete(self): """ Delete active Transiiton """ if messagebox.askyesno('Delete Transition', 'Delete ' + \ self.transition_str.get() + '?'): self.automaton.remove_transition(self.transition) Session.write("Transition Deleted.\n") self.changed = True else: Session.write("Transition Deletion Canceled.\n") self.changed = False self.destroy() return
def open_hyxml_properties(root): """ Load properties from hyxml Args: root: XML root Returns: List of Proerty() objects """ Session.write(" Loading hyxml properties...") prop_list = [] for prop in root.iterfind('property'): p = Property() p.name = prop.get('name') p.type = SAFETY p.initial_set_str = FileHandler.clean_eq(prop.get('initialSet')) p.unsafe_set_str = FileHandler.clean_eq(prop.get('unsafeSet')) # Handle properties parameters param = prop.find('parameters') if param is not None: time_step = param.get('timestep') if time_step is None: p.time_step = 0.0 else: p.time_step = float(time_step) time_horizon = param.get('timehorizon') if time_horizon is None: p.time_horizon = 0.0 else: p.time_horizon = float(time_horizon) k_value = param.get('kvalue') if k_value is None: p.k_value = 0.0 else: p.k_value = float(k_value) prop_list.append(p) Session.write(" Done.\n") return prop_list
def __init__(self, parent, hybrid, action, automaton=None): PopupEntry.__init__(self, parent) self.title_label.config(text="Automaton") if hybrid is not Session.hybrid: Session.write("ERROR: Attempting to edit non-Session hybrid.\n") self._cancel() self.parent = parent self.hybrid = hybrid self.automaton = automaton self.action = action self.changed = False self._init_widgets() if action == EDIT: self._load_session() if action == DELETE: self._disable_fields()
def _reload_xml(self, event=None): if not Session.file_path: print('No session filepath\n') return Session.write("Reloading xml...") file_path = Session.file_path file = FileHandler.open_file(file_path) if (HYXML_FILE in file_path): Session.write(" hyxml file reloaded.\n") Session.file_type = HYXML_FILE elif (MDL_FILE in file_path): Session.write(" mdl file opened\n") Session.file_type = MDL_FILE if file == None: print("File reload failed: No file\n") return # Obtain parsed results Session.hybrid = file['hybrid'] Session.prop_list = file['prop_list'] if (len(Session.prop_list) == 0): Session.prop_list.append(Property()) Session.file_opened = True self.open_xml() return
def plot_quad(data_points, horizontal_index, vertical_indices, variable_list, mode_list, title, filename): Session.write("Generating verification plot...") bokeh_plot = figure(title=title) for i, vertical_index in enumerate(vertical_indices): top = [] bottom = [] left = [] right = [] for j in range(1, len(data_points), 2): # Left and Right side defined by horizontal axis variable left.append(float(data_points[j-1][horizontal_index])) right.append(float(data_points[j][horizontal_index])) # Top and Bottom are defined by vertical axis variable bottom.append(min(float(data_points[j-1][vertical_index]), float(data_points[j][vertical_index]))) top.append(max(float(data_points[j-1][vertical_index]), float(data_points[j][vertical_index]))) bokeh_plot.quad(left=left, right=right, bottom=bottom, top=top, color=PLOT_COLORS[i], line_width=0, line_alpha=0.35, fill_alpha=0.35, legend_label=variable_list[vertical_indices[i]]) # X - axis bokeh_plot.xaxis.axis_label = variable_list[horizontal_index] # Y - axis y_axis_label = variable_list[vertical_indices[0]] for i in range(1, len(vertical_indices)): y_axis_label += ", " + variable_list[vertical_indices[i]] bokeh_plot.yaxis.axis_label = y_axis_label save(bokeh_plot, filename=filename + '.html', title=title) export_png(bokeh_plot, filename=filename + '.png') Session.write("Done.\n")
def _init_widgets(self): """ Initialize the Treeview and Property Editory """ self.sidebar = ModelSidebar(self) leftside = Frame(self) self.tree = TreeView(leftside, self.sidebar, selectmode='browse') self.feedback = Session.add_feedback_frame(leftside) self.tree.pack(expand=TRUE, fill=BOTH, side=TOP, anchor=E) self.feedback.pack(fill=X, side=BOTTOM, anchor=E) leftside.pack(expand=TRUE, fill=BOTH, side=LEFT, anchor=E) self.sidebar.pack(expand=TRUE, fill=Y, side=TOP, anchor=E) return
def _sim_ver(action): # Parse and Compose (HyIR.compose_all calss HyIR.parse_all) HyIR.compose_all(Session.hybrid) # if(not Session.cur_prop.is_valid()): # Session.write("Property invalid, abandoning operation...\n") # return None if not Session.hybrid.composed: Session.write("ERROR: System not composed, abandoning operation...\n") return None # Generate Simulator if (Session.simulator == CAPD): Session.hybrid.convertToCAPD('simulator') else: if (Session.simulator == ODEINT_FIX): st = 'constant' elif (Session.simulator == ODEINT_ADP): st = 'adaptive' path = '../work-dir/simulator.cpp' gen_simulator(path, Session.hybrid, step_type=st) Session.hybrid.printHybridSimGuardsInvariants() Session.hybrid.printBloatedSimGuardsInvariants() # Load JSON configuration with open('../config.json') as f: config = json.load(f) initialize_cpp_model(config, action) compile_executable(config) # Simulate selected model Session.write("Running simulate/verify...\n") Session.update() start_time = time.time() result = Session.cpp_model.simulate_verify() print("--- " + str(time.time() - start_time) + " seconds ---") result_str_dict = {1: "Safe", 0: "Unknown", -1: "Unsafe"} Session.write("RESULT: " + result_str_dict[result] + "\n") return result
def compose_all(cls, hybrid): cls.parse(hybrid) if not hybrid.parsed: Session.write("System not parsed. Exiting composition...\n") return Session.write("Composing System...\n") automata_list = hybrid.automata automata_list.reverse() while len(automata_list) > 1: automaton1 = automata_list.pop() automaton2 = automata_list.pop() automata_list.append(HyIR.compose(automaton1, automaton2)) hybrid.automata = automata_list hybrid.populateInvGuards() #hybrid.print_all() thinvarprop = "" thinvarlist = "" for var in hybrid.local_var_names: if var in hybrid.local_thinvar_names: thinvarlist += var + "\n" thinvarprop += "1\n" else: thinvarprop += "0\n" writer = open("../work-dir/ThinVarProp", "w") writer.write(thinvarprop) writer.close() writer = open("../work-dir/ThinVarList", "w") writer.write(thinvarlist) writer.close() cls.compose_properties(hybrid.automata[0], Session.hybrid.properties) hybrid.parsed = False cls.parse(hybrid) Session.hybrid = hybrid Session.hybrid.composed = True Session.write("Composition complete.") return
def _save_xml(self, event=None): if not Session.file_path: Session.write("No session filepath\n") return Session.write("Saving xml...") text = self.editor.get('1.0', 'end-1c') with open(Session.file_path, 'w') as f: f.write(text) Session.write("\n Saved as: " + Session.file_path + ".\n") self._reload_xml() return
def open_hyxml_model(root): """ Loads automata from input xml root Args: root: XML root Returns: List of Automaton() objects """ Session.write(" Loading hyxml model...") automata = [] for auto in root.iterfind("automaton"): name = auto.get("name") automaton = Automaton(name) for var in auto.iterfind("variable"): # Load variables v_name = var.get("name") v_scope = var.get("scope") v_type = var.get("type") v = Variable(name=v_name, type=v_type, scope=v_scope) automaton.add_var(v) for thinvar in auto.iterfind("thin_variable"): # Load thin variables v_name = thinvar.get("name") v_scope = thinvar.get("scope") v_type = thinvar.get("type") v = ThinVariable(name=v_name, type=v_type, scope=v_scope) automaton.add_thinvar(v) for mode in auto.iterfind("mode"): # Load modes mode_name = mode.get("name") mode_id = int(mode.get("id")) mode_init = (mode.get("initial") == "True") # if automaton.next_mode_id <= mode_id: # automaton.next_mode_id = mode_id + 1 mode_obj = Mode(name=mode_name, id=mode_id, initial=mode_init) for dai in mode.iterfind("dai"): # Load Flows raw_eq = dai.get("equation") mode_obj.add_dai(DAI(raw_eq)) for inv in mode.iterfind("invariant"): # Load Invariants raw_eq = inv.get("equation") # Equation 'cleaning' is needed for inequalities clean_eq = FileHandler.clean_eq(raw_eq) mode_obj.add_invariant(Invariant(clean_eq)) automaton.add_mode(mode_obj, mode_id) if not automaton.verify_mode_ids(): Session.write(" FILE READ ERROR: MODE IDS NOT UNIQUE\n") Session.write(" Automaton: " + automaton.name + "\n") if not automaton.verify_mode_names(): Session.write(" FILE READ ERROR: MODE NAMES NOT UNIQUE\n") Session.write(" Automaton: " + automaton.name + "\n") for tran in auto.iterfind("transition"): # Load transitions g = tran.find("guard") guard = Guard(FileHandler.clean_eq(g.get("equation"))) tran_id = int(tran.get("id")) tran_src = int(tran.get("source")) tran_dest = int(tran.get("destination")) # Actions actions = [] for act in tran.iterfind("action"): raw_eq = act.get("equation") clean_eq = FileHandler.clean_eq(raw_eq) actions.append(Action(clean_eq)) transition = Transition(guard, actions, tran_id, tran_src, tran_dest) automaton.add_transition(transition) if not automaton.verify_transition_src_dest(): Session.write( " FILE READ ERROR: TRANSITION SOURCE/DESTINATION IDS " + "NOT VALID MODE IDS\n") Session.write(" Automaton: " + automaton.name + "\n") automata.append(automaton) Session.write(" Done.\n") return automata
def parse(self): Session.write(" Parsing Automaton " + self.name + "...\n") errors = [] Session.write(" Parsing Modes...") if not self.verify_mode_names(): errors.append(('Mode', self, "Mode names not unique", None)) if not self.verify_mode_ids(): errors.append(('Mode', self, "Mode IDs not unique", None)) for mode in self.modes: errors += mode.parse() Session.write(" Modes Parsed.\n") Session.write(" Parsing Transitions...") if not self.verify_transition_src_dest(): errors.append( ('Transition', self, "Transition src/dest invalid", None)) for transition in self.transitions: errors += transition.parse() Session.write(" Transitions Parsed.\n") Session.write(" Automaton Parsed.\n") return errors
def _display_model(self, event=None): """ Display Session automata in Treeview """ Session.write("Displaying model tree...") hybrid = Session.hybrid self.automaton_dict = {} # dict[item_id] = automaton object self.mode_dict = {} # dict[item_id] = mode object self.trans_dict = {} # dict[item_id] = transition object for automaton in hybrid.automata: # Create automaton parent item automaton_id = self.insert('', 'end', text=automaton.name) self.item(automaton_id, open=TRUE) # Store automaton in dictionary self.automaton_dict[automaton_id] = automaton # Create variable parent and variable items var_id = self.insert(automaton_id, 'end', text=VARIABLES) var_str = ', '.join(automaton.variables.names) self.insert(var_id, 'end', text=var_str) self.item(var_id, open=TRUE) # Create thin variable parent and thin variable items if len(automaton.thinvariables.all) != 0: thin_var_id = self.insert(automaton_id, 'end', text="Thin Variables") thin_var_str = ', '.join(automaton.thinvariables.names) self.insert(thin_var_id, 'end', text=thin_var_str) self.item(thin_var_id, open=TRUE) # Create mode parent item modes_id = self.insert(automaton_id, 'end', text=MODES) self.item(modes_id, open=TRUE) # Create mode items for mode in automaton.modes: mode_str = mode.name + " (" + str(mode.id) + ")" mode_id = self.insert(modes_id, 'end', text=mode_str) self.mode_dict[mode_id] = mode automaton.mode_dict[mode.id] = mode.name # Create flow itmes flow_id = self.insert(mode_id, 'end', text="Flows") for dai in mode.dais: dai_str = dai.raw self.insert(flow_id, 'end', text=dai_str) # Create invariant items inv_id = self.insert(mode_id, 'end', text="Invariants") for inv in mode.invariants: self.insert(inv_id, 'end', text=inv.raw) # Create transition parent items trans_id = self.insert(automaton_id, 'end', text=TRANSITIONS) self.item(trans_id, open=TRUE) # Create transition items for tran in automaton.transitions: # Build transition string src, dest = automaton.mode_dict[ tran.source], automaton.mode_dict[tran.destination] tran_str = src + " -> " + dest tran_id = self.insert(trans_id, 'end', text=tran_str) self.trans_dict[tran_id] = tran # Source src_str = "Source: " + src + " (" + str(tran.source) + ")" self.insert(tran_id, 'end', text=src_str) # Destination dest_str = "Destination: " + dest + " (" \ + str(tran.destination) + ")" self.insert(tran_id, 'end', text=dest_str) # Guard guard_str = "Guards: " + (tran.guard.raw or "None") self.insert(tran_id, 'end', text=guard_str) # Actions act_id = self.insert(tran_id, 'end', text="Actions") for act in tran.actions: self.insert(act_id, 'end', text=act.raw) if self.sidebar.check_sim_ver_disable(): self.sidebar._disable_enable_button(1) else: self.sidebar._disable_enable_button(0) Session.write(" Done.\n") return
def save_model(hybrid, property_list, file_path): Session.write("Saving filepath: " + str(file_path) + "\n") Session.write("Saving...") hyxml = ET.Element("hyxml", {"type": "Model"}) for automaton in hybrid.automata: auto = ET.SubElement(hyxml, 'automaton', {"name": automaton.name}) # Variables for var in automaton.vars: ET.SubElement(auto, "variable", { "name": var.name, "scope": var.scope, "type": var.type }) # Thin Variables for thinvar in automaton.thinvars: ET.SubElement( auto, "thin_variable", { "name": thinvar.name, "scope": thinvar.scope, "type": thinvar.type }) # Modes for mode in automaton.modes: m = ET.SubElement( auto, "mode", { "id": str(mode.id), "initial": str(mode.initial), "name": mode.name }) for dai in mode.dais: #equ = dai.raw[3:-1] ET.SubElement(m, "dai", {"equation": dai.raw}) for inv in mode.invariants: ET.SubElement(m, "invariant", {"equation": inv.raw}) # Transitions for tran in automaton.transitions: t = ET.SubElement( auto, "transition", { "id": str(tran.id), "destination": str(tran.destination), "source": str(tran.source) }) ET.SubElement(t, "guard", {"equation": tran.guard.raw}) for act in tran.actions: ET.SubElement(t, "action", {"equation": act.raw}) # Composition #ET.SubElement(hyxml,"composition", {"automata":hybrid.automata[0].name}) # Properties for prop in property_list: if not prop.initial_set_str: continue pt1 = ET.SubElement( hyxml, "property", { "name": prop.name, "type": str(prop.type), "initialSet": prop.initial_set_str, "unsafeSet": prop.unsafe_set_str }) ET.SubElement( pt1, "parameters", { "timehorizon": str(prop.time_horizon), "timestep": str(prop.time_step), "kvalue": str(prop.k_value) }) tree = ET.ElementTree(hyxml) def indent(elem, level=0): i = "\n" + level * " " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: indent(elem, level + 1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i indent(hyxml) tree.write(file_path) Session.write(" Done.\n") return
def open_file(file_path): """ Loads a file and stores the model in Session.hybrid Args: file_path: The file path to load Returns: True/False status (True if file opened successfully) """ Session.write("Opening File...\n") base_name = os.path.basename(file_path) raw_name, ext = os.path.splitext(base_name) # Handle HyXML file if (ext == '.hyxml'): Session.file_type = HYXML_FILE # Get HyXML type and call corresponding function hyxml_tree = ET.parse(file_path) if (hyxml_tree == None): return False hyxml_root = hyxml_tree.getroot() hyxml_type = hyxml_root.get('type') thinvarprop = "" thinvarlist = "" if (hyxml_type == 'Model'): automata = FileHandler.open_hyxml_model(hyxml_root) properties = FileHandler.open_hyxml_properties(hyxml_root) else: return False # Handle MDL file elif (ext == '.mdl'): Session.file_type = MLD_FILE hybrid = FileHandler.open_mdl_model(file_path, raw_name) prop_list = [] # Handle all other extensions else: return False hybrid = HyIR(file_name=file_path) hybrid.automata = automata hybrid.properties = properties Session.hybrid = hybrid Session.cur_prop = properties[0] Session.write("File Opened.\n") return True