Exemplo n.º 1
0
    def _autIsNonTrivial(self):
        """
        Check for a) empty automaton, or b) trivial initial-state automaton
         with no transitions
        (This can indicate unsatisfiable system initial conditions (case a),
         or an unsat environment (case b).)

        TODO: Do this in the Java code; it's super inefficient to
        load the whole aut just to check this.
        """

        proj_copy = deepcopy(self.proj)
        proj_copy.rfi = self.parser.proj.rfi
        proj_copy.sensor_handler = None
        proj_copy.actuator_handler = None
        proj_copy.h_instance = None

        aut = fsa.Automaton(proj_copy)

        aut.loadFile(self.proj.getFilenamePrefix() + ".aut",
                     self.proj.enabled_sensors, self.proj.enabled_actuators,
                     self.proj.all_customs)

        nonTrivial = any([len(s.transitions) > 0 for s in aut.states])

        return nonTrivial
Exemplo n.º 2
0
    def loadAutFile(self, filename):
        logging.info("Loading automaton...")

        aut = fsa.Automaton(self.proj)

        success = aut.loadFile(
            filename, self.proj.enabled_sensors, self.proj.enabled_actuators,
            self.proj.all_customs + self.proj.internal_props)

        return aut if success else None
Exemplo n.º 3
0
    def _coreFinding(self, to_highlight, unsat, badInit):
        #returns list of formulas that cause unsatisfiability/unrealizability (based on unsat flag).
        #takes as input sentences marked for highlighting, and formula describing bad initial states
        #from JTLV.

        #find number of states in automaton/counter for unsat/unreal core max unrolling depth ("recurrence diameter")
        proj_copy = deepcopy(self.proj)
        proj_copy.rfi = self.parser.proj.rfi
        proj_copy.sensor_handler = None
        proj_copy.actuator_handler = None
        proj_copy.h_instance = None

        num_bits = int(
            numpy.ceil(numpy.log2(len(self.parser.proj.rfi.regions)))
        )  # Number of bits necessary to encode all regions
        region_props = ["bit" + str(n) for n in xrange(num_bits)]

        aut = fsa.Automaton(proj_copy)
        aut.loadFile(
            self.proj.getFilenamePrefix() + ".aut",
            self.proj.enabled_actuators + self.proj.all_customs + region_props,
            self.proj.enabled_sensors, [])

        #find deadlocked states in the automaton (states with no out-transitions)
        deadStates = [s for s in aut.states if not s.transitions]
        #find states that can be forced by the environment into the deadlocked set
        forceDeadStates = [(s, e) for s in aut.states for e in deadStates
                           if e in s.transitions]
        #LTL representation of these states and the deadlock-causing environment move in the next time step
        forceDeadlockLTL = map(
            lambda
            (s, e): " & ".join([stateToLTL(s),
                                stateToLTL(e, 1, 1, True)]), forceDeadStates)

        #find livelocked goal and corresponding one-step propositional formula (by stripping LTL operators)
        desiredGoal = [
            h_item[2] for h_item in to_highlight if h_item[1] == "goals"
        ]

        if desiredGoal:
            desiredGoal = desiredGoal[0]
            #Don't actually need LTL
            #desiredGoalLTL = stripLTLLine(self.ltlConjunctsFromBadLines([h_item for h_item in to_highlight if h_item[1] == "goals"], False)[0],True)

        def preventsDesiredGoal(s):
            rank_str = s.transitions[0].rank
            m = re.search(r"\(\d+,(-?\d+)\)", rank_str)
            if m is None:
                logging.error(
                    "Error parsing jx in automaton.  Are you sure the spec is unrealizable?"
                )
                return
            jx = int(m.group(1))
            return (jx == desiredGoal)

        #find livelocked states in the automaton (states with desired sys rank)
        livelockedStates = filter(preventsDesiredGoal,
                                  [s for s in aut.states if s.transitions])
        #find states that can be forced by the environment into the livelocked set
        forceLivelockedStates = [(fro, to) for fro in aut.states
                                 for to in livelockedStates
                                 if to in s.transitions]

        #LTL representation of these states and the livelocked goal
        #forceLivelockLTL = map(lambda s: " & ".join([stateToLTL(s), desiredGoalLTL]), livelockedStates) ###Don't actually need to add goal -- will be added in 'conjuncts'
        forceLivelockLTL = map(
            lambda (s1, s2): " & ".join(
                [stateToLTL(s1, 1, 1),
                 stateToLTL(s2, 1, 0, True)]), forceLivelockedStates)
        #forceLivelockLTL = map(stateToLTL, livelockedStates)

        numStates = len(aut.states)
        numRegions = len(self.parser.proj.rfi.regions)

        if forceDeadlockLTL:
            deadlockFlag = True
            badStatesLTL = forceDeadlockLTL
        else:
            #this means livelock
            deadlockFlag = False
            badStatesLTL = forceLivelockLTL

        #################################
        #                               #
        # get conjuncts to be minimized #
        #                               #
        #################################

        #topology
        topo = self.spec['Topo'].replace('\n', '')
        topo = topo.replace('\t', '')

        #have to use all initial conditions if no single bad initial state given
        useInitFlag = badInit is None

        #other highlighted LTL formulas
        conjuncts = self.ltlConjunctsFromBadLines(to_highlight, useInitFlag)

        #filter out props that are actually used
        #self.propList = [p for p in self.propList if [c for c in conjuncts if p in c] or [c for c in badStatesLTL if p in c and not unsat] or p in topo]

        cmd = self._getPicosatCommand()

        if unsat:
            guilty = self.unsatCores(cmd, topo, badInit, conjuncts, 15,
                                     15)  #returns LTL
        else:
            guilty = self.unrealCores(cmd, topo, badStatesLTL, conjuncts,
                                      deadlockFlag)  #returns LTL
        return guilty
Exemplo n.º 4
0
    def __init__(self, *args, **kwds):
        # begin wxGlade: MopsyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.window_1 = wx.SplitterWindow(self,
                                          -1,
                                          style=wx.SP_3D | wx.SP_BORDER)
        self.window_1_pane_2 = wx.Panel(self.window_1, -1)
        self.window_1_pane_1 = wx.Panel(self.window_1, -1)
        self.mopsy_frame_statusbar = self.CreateStatusBar(1, 0)
        self.history_grid = wx.grid.Grid(self.window_1_pane_1, -1, size=(1, 1))
        self.panel_1 = wx.Panel(self.window_1_pane_2,
                                -1,
                                style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL)
        self.label_5 = wx.StaticText(self.window_1_pane_2, -1,
                                     "Current environment state:")
        self.label_6 = wx.StaticText(self.window_1_pane_2, -1,
                                     "Please choose your response:")
        self.label_movingto = wx.StaticText(self.window_1_pane_2, -1,
                                            "Moving to XXX ...")
        self.label_8 = wx.StaticText(self.window_1_pane_2, -1,
                                     "Actuator states:")
        self.label_9 = wx.StaticText(self.window_1_pane_2, -1,
                                     "Internal propositions:")
        self.label_violation = wx.StaticText(self.window_1_pane_2, -1, "")
        self.button_next = wx.Button(self.window_1_pane_2, -1,
                                     "Execute Move >>")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.onButtonNext, self.button_next)
        # end wxGlade

        self.dest_region = None
        self.current_region = None
        self.regionsToHide = []
        self.actuatorStates = {}
        self.sensorStates = {}

        self.panel_1.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.mapBitmap = None

        # Load in the project and map
        self.proj = project.Project()
        self.proj.loadProject(sys.argv[1])
        self.proj.rfi = self.proj.loadRegionFile(decomposed=True)
        self.Bind(wx.EVT_SIZE, self.onResize, self)
        self.panel_1.Bind(wx.EVT_PAINT, self.onPaint)
        self.panel_1.Bind(wx.EVT_ERASE_BACKGROUND, self.onEraseBG)
        self.panel_1.Bind(wx.EVT_LEFT_DOWN, self.onMapClick)
        self.onResize()

        self.proj.determineEnabledPropositions()

        # Load in automatons
        self.sysDummySensorHandler = SysDummySensorHandler(self)
        self.envDummySensorHandler = EnvDummySensorHandler(self)
        self.sysDummyActuatorHandler = SysDummyActuatorHandler()
        self.envDummyActuatorHandler = EnvDummyActuatorHandler(self)
        self.dummyMotionHandler = DummyMotionHandler()
        self.proj.sensor_handler, self.proj.actuator_handler, self.proj.h_instance = [
            None
        ] * 3

        print "Loading safety constraints..."
        self.safety_aut = fsa.Automaton(self.proj)
        self.safety_aut.sensor_handler = self.sysDummySensorHandler
        self.safety_aut.actuator_handler = self.sysDummyActuatorHandler
        self.safety_aut.motion_handler = self.dummyMotionHandler

        self.safety_aut.loadFile(self.proj.getFilenamePrefix() + "_safety.aut",
                                 self.proj.enabled_sensors,
                                 self.proj.enabled_actuators,
                                 self.proj.all_customs)

        print "Loading environment counter-strategy..."
        self.num_bits = int(numpy.ceil(numpy.log2(len(self.proj.rfi.regions)))
                            )  # Number of bits necessary to encode all regions
        region_props = ["bit" + str(n) for n in xrange(self.num_bits)]

        self.env_aut = fsa.Automaton(self.proj)
        self.env_aut.sensor_handler = self.envDummySensorHandler
        self.env_aut.actuator_handler = self.envDummyActuatorHandler
        self.env_aut.motion_handler = self.dummyMotionHandler
        # We are being a little tricky here by just reversing the sensor and actuator propositions
        # to create a sort of dual of the usual automaton
        self.env_aut.loadFile(
            self.proj.getFilenamePrefix() + ".aut",
            self.proj.enabled_actuators + self.proj.all_customs + region_props,
            self.proj.enabled_sensors, [])

        # Force initial state to state #0 in counter-strategy
        self.env_aut.current_region = None
        self.env_aut.current_state = self.env_aut.states[0]
        # Internal aut housekeeping (ripped from chooseInitialState; hacky)
        self.env_aut.last_next_states = []
        self.env_aut.next_state = None
        self.env_aut.next_region = None

        #self.env_aut.dumpStates([self.env_aut.current_state])

        # Set initial sensor values
        self.env_aut.updateOutputs()

        # Figure out what actuator/custom-prop settings the system should start with
        for k, v in self.env_aut.current_state.inputs.iteritems():
            # Skip any "bitX" region encodings
            if re.match('^bit\d+$', k): continue
            self.actuatorStates[k] = int(v)

        # Figure out what region the system should start from (ripped from regionFromState)
        self.current_region = 0
        for bit in range(self.num_bits):
            if (int(self.env_aut.current_state.inputs["bit" + str(bit)]) == 1):
                # bit0 is MSB
                self.current_region += int(2**(self.num_bits - bit - 1))

        self.dest_region = self.current_region

        # Create all the sensor/actuator buttons
        self.env_buttons = []  # This will later hold our buttons
        self.act_buttons = []  # This will later hold our buttons
        self.cust_buttons = []  # This will later hold our buttons

        actprops = copy.deepcopy(self.actuatorStates)
        for s in self.proj.all_customs:
            del (actprops[s])
        custprops = copy.deepcopy(self.actuatorStates)
        for s in self.proj.enabled_actuators:
            del (custprops[s])

        self.populateToggleButtons(self.sizer_env, self.env_buttons,
                                   self.sensorStates)
        self.populateToggleButtons(self.sizer_act, self.act_buttons, actprops)
        self.populateToggleButtons(self.sizer_prop, self.cust_buttons,
                                   custprops)

        # Make the env buttons not clickable (TODO: maybe replace with non-buttons)
        for b in self.env_buttons:
            b.Enable(False)

        # Set up the logging grid
        colheaders = self.proj.enabled_sensors + [
            "Region"
        ] + self.proj.enabled_actuators + self.proj.all_customs
        self.history_grid.CreateGrid(0, len(colheaders))
        for i, n in enumerate(colheaders):
            self.history_grid.SetColLabelValue(i, " " + n + " ")
            self.history_grid.SetColSize(i, -1)  # Auto-size
        self.history_grid.EnableEditing(False)

        # Put initial condition into log
        self.appendToHistory()

        # Find the appropriate starting state in the sys safety aut
        init_outputs = [
            o for o in self.actuatorStates.keys()
            if (self.actuatorStates[o] == 1)
        ]

        if self.safety_aut.chooseInitialState(self.current_region,
                                              init_outputs) is None:
            print "Counterstrategy initial state not found in system safety automaton. Something's off."
            return

        # Start initial environment move
        # All transitionable states have the same env move, so just use the first
        if (len(self.env_aut.current_state.transitions) >= 1):
            self.env_aut.updateOutputs(
                self.env_aut.current_state.transitions[0])

        self.label_movingto.SetLabel(
            "Stay in region " +
            self.safety_aut.getAnnotatedRegionName(self.current_region))
        self.applySafetyConstraints()
Exemplo n.º 5
0
        message = "BG:" + proj.getFilenamePrefix() + ".spec"
        UDPSockTo.sendto(message, addrTo)

        # Redirect all output to the log
        redir = RedirectText(UDPSockTo, addrTo)

        sys.stdout = redir
        sys.stderr = redir

    #######################
    # Load automaton file #
    #######################

    print "Loading automaton..."

    FSA = fsa.Automaton(proj)

    success = FSA.loadFile(aut_file, proj.enabled_sensors,
                           proj.enabled_actuators, proj.all_customs)
    if not success: return

    #############################
    # Begin automaton execution #
    #############################

    last_gui_update_time = 0

    ### Wait for the initial start command

    if show_gui:
        while not runFSA:
Exemplo n.º 6
0
    def __init__(self, *args, **kwds):
        # begin wxGlade: MopsyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.mopsy_frame_statusbar = self.CreateStatusBar(1, 0)
        self.window_1 = wx.SplitterWindow(self,
                                          wx.ID_ANY,
                                          style=wx.SP_3D | wx.SP_BORDER)
        self.window_1_pane_1 = wx.Panel(self.window_1, wx.ID_ANY)
        self.history_grid = wx.grid.Grid(self.window_1_pane_1,
                                         wx.ID_ANY,
                                         size=(1, 1))
        self.window_1_pane_2 = wx.Panel(self.window_1, wx.ID_ANY)
        self.panel_1 = wx.Panel(self.window_1_pane_2,
                                wx.ID_ANY,
                                style=wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL)
        self.label_1 = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                     "Your goal:")
        self.label_goal = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                        "Wait patiently for Mopsy to load")
        self.label_5 = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                     "Current environment state:")
        self.label_6 = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                     "Please choose your response:")
        self.label_movingto = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                            "Moving to XXX ...")
        self.label_8 = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                     "Actuator states:")
        self.label_9 = wx.StaticText(self.window_1_pane_2, wx.ID_ANY,
                                     "Internal propositions:")
        self.label_violation = wx.StaticText(self.window_1_pane_2,
                                             wx.ID_ANY,
                                             "",
                                             style=wx.ST_NO_AUTORESIZE)
        self.button_next = wx.Button(self.window_1_pane_2, wx.ID_ANY,
                                     "Execute Move >>")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.onButtonNext, self.button_next)
        # end wxGlade

        self.coreCalculationLock = threading.Lock()
        self.dest_region = None
        self.current_region = None
        self.regionsToHide = []
        self.actuatorStates = {}
        self.sensorStates = {}

        self.panel_1.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.mapBitmap = None

        # Load in the project and map
        self.mopsy_frame_statusbar.SetStatusText("Loading project...", 0)
        self.compiler = SpecCompiler(sys.argv[1])
        self.proj = copy.deepcopy(self.compiler.proj)
        self.proj.rfi = self.proj.loadRegionFile(decomposed=True)
        self.Bind(wx.EVT_SIZE, self.onResize, self)
        self.panel_1.Bind(wx.EVT_PAINT, self.onPaint)
        self.panel_1.Bind(wx.EVT_ERASE_BACKGROUND, self.onEraseBG)
        self.panel_1.Bind(wx.EVT_LEFT_DOWN, self.onMapClick)
        self.onResize()

        self.proj.determineEnabledPropositions()

        # Parse specification so we can give feedback
        self.mopsy_frame_statusbar.SetStatusText("Parsing specification...", 0)
        self.compiler._decompose()
        self.spec, self.tracebackTree, response = self.compiler._writeLTLFile()
        self.compiler._writeSMVFile()  # to update propList

        if self.proj.compile_options["parser"] == "slurp":
            # Add SLURP to path for import
            p = os.path.dirname(os.path.abspath(__file__))
            sys.path.append(os.path.join(p, "..", "etc", "SLURP"))
            global chunks_from_gentree, line_to_chunks
            from ltlbroom.specgeneration import chunks_from_gentree, line_to_chunks
            self.tracebackChunks = chunks_from_gentree(self.tracebackTree)

        # Load in counter-strategy automaton
        self.envDummySensorHandler = EnvDummySensorHandler(self)
        self.envDummyActuatorHandler = EnvDummyActuatorHandler(self)
        self.dummyMotionHandler = DummyMotionHandler()
        self.proj.sensor_handler, self.proj.actuator_handler, self.proj.h_instance = [
            None
        ] * 3

        self.mopsy_frame_statusbar.SetStatusText(
            "Loading environment counter-strategy...", 0)
        self.num_bits = int(numpy.ceil(numpy.log2(len(self.proj.rfi.regions)))
                            )  # Number of bits necessary to encode all regions
        region_props = ["bit" + str(n) for n in xrange(self.num_bits)]

        self.env_aut = fsa.Automaton(self.proj)
        self.env_aut.sensor_handler = self.envDummySensorHandler
        self.env_aut.actuator_handler = self.envDummyActuatorHandler
        self.env_aut.motion_handler = self.dummyMotionHandler
        # We are being a little tricky here by just reversing the sensor and actuator propositions
        # to create a sort of dual of the usual automaton
        self.env_aut.loadFile(
            self.proj.getFilenamePrefix() + ".aut",
            self.proj.enabled_actuators + self.proj.all_customs +
            self.compiler.proj.internal_props + region_props,
            self.proj.enabled_sensors, [])

        self.env_aut.current_region = None

        # Find first state in counterstrategy that seeks to falsify the given liveness
        if len(sys.argv) > 2:
            desired_jx = int(sys.argv[2])

            for s in self.env_aut.states:
                if s.transitions:
                    rank_str = s.transitions[0].rank
                    m = re.search(r"\(\d+,(-?\d+)\)", rank_str)
                    if m is None:
                        print "ERROR: Error parsing jx in automaton.  Are you sure the spec is unrealizable?"
                        return
                    jx = int(m.group(1))

                    if jx == desired_jx:
                        self.env_aut.current_state = s
                        break

            if self.env_aut.current_state is None:
                print "ERROR: could not find state in counterstrategy to falsify sys goal #{}".format(
                    desired_jx)
                return
        else:
            self.env_aut.current_state = self.env_aut.states[0]

        # Internal aut housekeeping (ripped from chooseInitialState; hacky)
        self.env_aut.last_next_states = []
        self.env_aut.next_state = None
        self.env_aut.next_region = None

        #self.env_aut.dumpStates([self.env_aut.current_state])

        # Set initial sensor values
        self.env_aut.updateOutputs()

        # Figure out what actuator/custom-prop settings the system should start with
        for k, v in self.env_aut.current_state.inputs.iteritems():
            # Skip any "bitX" region encodings
            if re.match('^bit\d+$', k): continue
            self.actuatorStates[k] = int(v)

        # Figure out what region the system should start from
        self.current_region = self.regionFromEnvState(
            self.env_aut.current_state)
        self.dest_region = self.current_region

        # Create all the sensor/actuator buttons
        self.env_buttons = []  # This will later hold our buttons
        self.act_buttons = []  # This will later hold our buttons
        self.cust_buttons = []  # This will later hold our buttons

        actprops = dict((k, v) for k, v in self.actuatorStates.iteritems()
                        if k in self.proj.enabled_actuators)
        custprops = dict(
            (k, v) for k, v in self.actuatorStates.iteritems()
            if k in self.proj.all_customs + self.compiler.proj.internal_props)

        self.populateToggleButtons(self.sizer_env, self.env_buttons,
                                   self.sensorStates)
        self.populateToggleButtons(self.sizer_act, self.act_buttons, actprops)
        self.populateToggleButtons(self.sizer_prop, self.cust_buttons,
                                   custprops)

        # Make the env buttons not clickable (TODO: maybe replace with non-buttons)
        #for b in self.env_buttons:
        #    b.Enable(False)

        # Set up the logging grid
        self.history_grid.SetDefaultCellFont(
            wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
        self.history_grid.SetLabelFont(
            wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))

        colheaders = self.proj.enabled_sensors + [
            "Region"
        ] + self.proj.enabled_actuators + self.proj.all_customs + self.compiler.proj.internal_props
        self.history_grid.CreateGrid(0, len(colheaders))
        for i, n in enumerate(colheaders):
            self.history_grid.SetColLabelValue(i, " " + n + " ")
            self.history_grid.SetColSize(i, -1)  # Auto-size
        self.history_grid.EnableEditing(False)

        # Decide whether to enable core-finding
        self.coreFindingEnabled = self.compiler._getPicosatCommand(
        ) is not None

        # Put initial condition into log
        self.appendToHistory()

        # Start initial environment move
        # All transitionable states have the same env move, so just use the first
        if (len(self.env_aut.current_state.transitions) >= 1):
            self.env_aut.updateOutputs(
                self.env_aut.current_state.transitions[0])

        self.label_movingto.SetLabel(
            "Stay in region " +
            self.env_aut.getAnnotatedRegionName(self.current_region))

        self.showCurrentGoal()
        self.applySafetyConstraints()