def make_instance(cls, module, metamodule=None, semantics_module=None, preds_module=None): """Make an instance of the semantics for the given problem""" # Use the default semantics and predicates module if not specified if semantics_module is None: semantics_module = cls.SEMANTICS_MODULE if preds_module is None: preds_module = cls.PREDS_MODULE # Load the opsem.maude file if not already done if maude.getModule(semantics_module) is None: with get_resource_path('opsem.maude') as templog_path: if not maude.load(str(templog_path)): usermsgs.print_error( 'Error loading the small-step operational semantics' 'of the strategy language (opsem.maude).') return None # Instantiate the semantics for the given module maude.input( cls.get_instantiation(module, metamodule, semantics_module, preds_module)) osmod = maude.getCurrentModule() if osmod is None: usermsgs.print_error( 'Error instantiating the small-step operational semantics.') return None return cls(osmod, module)
def __init__(self): super().__init__('maude_listener') self.subscription = self.create_subscription(String, 'maude_msgs', self.listener_callback, 10) self.subscription # prevent unused variable warning self.maude_nat = maude.getModule('NAT')
def build_instance(filename, initial_txt, strategy_txt, module_txt=None, semantics_module='NOP-SEMANTICS'): """Build the model for the logic""" maude.load(filename) # Target module targetmod = maude.getCurrentModule( ) if module_txt is None else maude.getModule(module_txt) # Operational semantics module maude.input( INSTANTIATION.format(targetmod=targetmod, semanticsmod=semantics_module)) osmod = maude.getCurrentModule() # Create the helper class to handle the instance instance = OpSemInstance(osmod, targetmod) # Initial term initial_term = targetmod.parseTerm(initial_txt) if initial_term is None: sys.exit(1) initial_term.reduce() initial_metaterm = osmod.upTerm(initial_term) # Strategy expression strategy = targetmod.parseStrategy(strategy_txt) if strategy is None: sys.exit(1) strategy_metaterm = osmod.upStrategy(strategy) # Construct the terms in the semantics t = instance.stack_state(initial_metaterm, strategy_metaterm) return instance, t
def __init__(self, module_name, sorts_names): self.module_name = module_name self.module = maude.getModule(module_name) self.sorts_names = sorts_names self.vcs = []
def __init__(self, initial, strategy=None, filename=None, module=None, metamodule=None, opaque=(), biased_matchrew=True, already_loaded=False, single_use=False): """ Generate a Maude model for model-checking. :param initial: Initial term :type initial: str or maude.Term :param strategy: Strategy to control rewriting :type strategy: str or maude.StrategyExpression or None :param filename: Name of the file to be loaded :type filename: str or None :param module: Module where to model check :type module: str or maude.Module or None :param metamodule: Metarepresentation of the module where to model check (parsed in module) :type metamodule: str or maude.Term or None :param opaque: List of opaque strategies :type opaque: list of str :param biased_matchrew: Whether the biased matchrew feature is enabled :param biased_matchrew: bool :param already_loaded: Whether the file should not be loaded again :param already_loaded: bool :param single_use: Whether a single use of the model with the graph method is intended. Otherwise, graphs will be cached between calls to check :param single_use: bool """ # File name self.filename = filename needs_loading = not isinstance(module, maude.Module) \ and not isinstance(initial, maude.Term) \ and not already_loaded if needs_loading: if self.filename is None: raise ValueError( 'filename must not be empty if not already loaded') else: maude.load(self.filename) # Module if module is None: if isinstance(initial, maude.Term) and metamodule is None: self.module = initial.symbol().getModule() else: self.module = maude.getCurrentModule() self.module_str = str(self.module) elif isinstance(module, str): self.module = maude.getModule(module) self.module_str = module elif isinstance(module, maude.Module): self.module = module self.module_str = str(module) else: raise TypeError( f"unexpected type '{type(module).__name__}' for module") # Metamodule if isinstance(metamodule, str): self.metamodule = self.module.parseTerm(metamodule) self.module = maude.downModule(metamodule) elif isinstance(metamodule, maude.Term): self.metamodule = metamodule self.module = maude.downModule(metamodule) else: self.metamodule = None # Initial term if isinstance(initial, str): self.initial = self.module.parseTerm(initial) self.initial_str = initial elif isinstance(initial, maude.Term): self.initial = initial self.initial_str = str(initial) else: raise TypeError( f"unexpected type '{type(module).__name__}' for term") # Strategy expression if isinstance(strategy, str): self.strategy = self.module.parseStrategy(strategy) self.strategy_str = strategy elif isinstance(strategy, maude.StrategyExpression): self.strategy = strategy self.strategy_str = str(strategy) else: self.strategy = None self.strategy_str = None # Opaque strategies and biased_matchrew self.opaque = opaque self.biased_matchrew = biased_matchrew # Build the parser self.parser = _formulae.Parser() self.parser.set_module(self.module, metamodule=self.metamodule) # Look for the Formula sort formula_sort = self.module.findSort('Formula') if formula_sort is None: raise ValueError( 'the given module is not prepared for model checking') self.formula_kind = self.module.findSort('Formula').kind() # Graphs (wrapped or not) if self.strategy is None: self.graph = maude.RewriteGraph(self.initial) else: self.graph = maude.StrategyRewriteGraph(self.initial, self.strategy, self.opaque, self.biased_matchrew) self.wgraphs = {} self.single_use = single_use
def load(self): """Load and check the extension""" # The module defining the extension and the required functions self.extension = maude.getModule(self.view) makeSlangGrammar_name = 'makeSlangGrammar' makeMetaSlang_name = 'makeMetaSlang' if self.extension is None: view = maude.getView(self.view) if view is None: show_error('Not a module or view: ' + args.view) return False # Instantiating a view is not simple because the library does not offer many # tools for this, and because views may have been defined using op-to-term # mappings and the expected symbols may not be present in the module # Except the last two modules, this can be done once for all modid = uuid.uuid1() makeSlangGrammar_name = f'{modid}-makeSlangGrammar' makeMetaSlang_name = f'{modid}-makeMetaSlang' # Create a strategy module where the functions makeSlangGrammar # and makeMetaSlang are properly defined maude.input(f'''smod MOD-{modid}{{X :: SLANG-EXTENSION}} is op {modid}-makeSlangGrammar : Module -> Module . op {modid}-makeMetaSlang : Module -> Module . var M : Module . eq {modid}-makeSlangGrammar(M) = makeSlangGrammar(M) . eq {modid}-makeMetaSlang(M) = makeMetaSlang(M) . endsm''') # Instantiate the view maude.input(f'''smod INST-{modid} is protecting MOD-{modid}{{{self.view}}} . protecting SMOD-PARSE{{{self.view}}} . endsm''') self.extension = maude.getModule(f'INST-{modid}') module_kind = self.extension.findSort('Module').kind() self.makeSlangGrammar = self.extension.findSymbol(makeSlangGrammar_name, [module_kind], module_kind) self.makeMetaSlang = self.extension.findSymbol(makeMetaSlang_name, [module_kind], module_kind) if self.makeSlangGrammar is None or self.makeMetaSlang is None: show_error('Cannot find the expected operators in the extension module.') return False # Find the parseModule symbol (but do not fail if not found) string_kind = self.extension.findSort('String').kind() self.stratModule_sort = self.extension.findSort('StratModule') self.parseModule = self.extension.findSymbol('parseModule', [string_kind], module_kind) self.flatModule = self.extension.findSymbol('flatModule', [module_kind], module_kind) return True
# Load the Maude specifications of the extension and the model maude.init(advise=False) if not os.path.isfile(args.extension): show_error('Cannot find strategy language extension file: ' + args.extension) sys.exit(1) if not os.path.isfile(args.file): show_error('Cannot find Maude file: ' + args.file) sys.exit(1) maude.load(args.extension) maude.load(args.file) # The module where the extended strategies will be used... base_module = maude.getCurrentModule() if args.module is None else maude.getModule(args.module) # ...unless a metamodule is specified if args.metamodule is not None: metamodule = args.metamodule metamod_term = base_module.parseTerm(metamodule) module = maude.downModule(metamod_term) metamodule = str(metamod_term) elif args.extmodule is None: metamodule = f"upModule('{str(base_module)}, true)" module = base_module # Load the strategy language extension extension = SlangExtension(args.view)
def __init__(self): super().__init__('maude_publisher') self.publisher_ = self.create_publisher(String, 'maude_msgs', 10) timer_period = 1.5 # seconds self.timer = self.create_timer(timer_period, self.timer_callback) self.maude_nat = maude.getModule('NAT')
def __init__(self, implementation='a*', map_in_python=True): super().__init__('maude_planner_action_server' ) # Node name, could be changed to fit the BT maude.init() maude.load(self.ASTAR_MAUDE_PATH[implementation]) self.astar_module = maude.getModule('ASTAR') if self.astar_module is None: self.get_logger().fatal( 'Cannot find Maude ASTAR module in {}'.format( self.ASTAR_MAUDE_PATH[implementation])) else: self.get_logger().info('Maude planner node is ready') self.occupancy_grid = None # It will be read and updated from the map topic self.maude_map = None self.amcl_pose = None # It will be read and updated from the topic /amcl_pose # Configures the action server to respond to ComputePathToPose actions self._action_server = ActionServer(self, ComputePathToPose, 'ComputePathToPose', self.action_callback) # Listen to map topic self._map_subscription = self.create_subscription( OccupancyGrid, 'global_costmap/costmap', self.map_callback, 10) # Queue size # Listen to topic /amcl_pose self._amcl_pose_subscription = self.create_subscription( PoseWithCovarianceStamped, 'amcl_pose', self.amcl_pose_callback, 10) # Queue size # Plan publisher (so that it is represented in the view) self._plan_publisher = self.create_publisher(Path, '/plan', 10) # Connect the Maude special operator to the map self.map_in_python = map_in_python if map_in_python: if implementation == 'a*': self.map_hook = MapProvider(self, self.astar_module) maude.connectEqHook('open2?', self.map_hook) else: self.map_hook = MapProviderGet(self) maude.connectEqHook('get', self.map_hook) # Find sorts and operators needed to construct the a* term # (once for all) m = self.astar_module pose_kind = m.findSort('Pose').kind() costmap_kind = m.findSort('CostMap').kind() float_kind = m.findSort('Float').kind() path_kind = m.findSort('Path').kind() int_kind = m.findSort('IntList').kind() # Init Goal NumRow NumCol # op a* : Pose Pose CostMap Float Float -> Path . self.astar_symb = m.findSymbol( self.ASTAR_OPNAME[implementation], [pose_kind, pose_kind, costmap_kind, float_kind, float_kind], path_kind) self.intlist_symb = m.findSymbol('_`,_', [int_kind] * 2, int_kind) self.cmap_symb = m.findSymbol('`{_`}', [int_kind], costmap_kind) # Constants that will be used multiple times self.zero_term = m.parseTerm('0') self.one_term = m.parseTerm('1') self.mtIL_term = m.parseTerm('mtIL')
def __init__(self, test_path, obtain_navfn=True): with open(test_path, 'r') as ftest: lines = ftest.readlines() self.w, self.h = lines[0].strip().split() self.w = int(self.w) self.h = int(self.h) self.map_bin_file = lines[1].strip() # Filename relative to the test case self.map_data = [0] * (self.w * self.h) # Avoid appending test_full_path = os.path.abspath(ftest.name) test_dir = os.path.dirname(test_full_path) map_full_map_path = os.path.join(test_dir, self.map_bin_file) self.map_bin_file = map_full_map_path # Full path with open(self.map_bin_file, 'rb') as fmap: for i in range(self.w * self.h): cell = fmap.read(1) self.map_data[i] = int.from_bytes(cell, 'big') # It's one byte, it doesn't matter big or little endian self.test_cases = list() for test in lines[3:]: if test.strip().startswith('-1'): continue x0, y0, x1, y1 = [float(c) for c in test.strip().split()] self.test_cases.append(((x0, y0, 0.0), (x1, y1, 0.0))) # Orientation 0 degrees maude.init() maude.load(self.ASTAR_MAUDE_PATH) # Find sorts and operators needed to construct the a* term self.m = maude.getModule('ASTAR') pose_kind = self.m.findSort('Pose').kind() costmap_kind = self.m.findSort('CostMap').kind() float_kind = self.m.findSort('Float').kind() path_kind = self.m.findSort('Path').kind() int_kind = self.m.findSort('IntList').kind() nat_kind = self.m.findSort('Nat').kind() potential_kind = self.m.findSort('Potential').kind() gradient_kind = self.m.findSort('Gradient').kind() # We need it to solve an ambiguity later self.pose_kind = pose_kind # Use different functions whether obtaining the potential or not if not obtain_navfn: self.astar = self.m.findSymbol('a*', [pose_kind, pose_kind, costmap_kind] + [nat_kind] * 4, path_kind) self.get_potential = None self.compute_path = None else: self.astar = None # op getPotential : Pose Pose CostMap Nat Nat Nat -> Potential . self.get_potential = self.m.findSymbol('getPotential', [pose_kind, pose_kind, costmap_kind, nat_kind, nat_kind, nat_kind], potential_kind) # op computePath : CostMap Potential Pose Pose Float Gradient Nat Nat Nat -> Path . self.compute_path = self.m.findSymbol('computePath', [potential_kind, pose_kind, pose_kind, float_kind, gradient_kind, nat_kind, nat_kind, nat_kind], path_kind) intlist = self.m.findSymbol('_`,_', [int_kind] * 2, int_kind) cmap = self.m.findSymbol('`{_`}', [int_kind], costmap_kind) self.pattern = self.m.parseTerm('{ X:Float, Y:Float, Z:Float } O:Nat') self.mod = self.m # Constants that will be used multiple times zero = self.m.parseTerm('0') one = self.m.parseTerm('1') mtIL = self.m.parseTerm('mtIL') self.noPath = self.m.parseTerm('noPath') self.empyList = self.m.parseTerm('nil') # Dictionary with Maude integer terms from 0 to 255 to avoid parsing # when constructing the map_list in Maude int_terms = dict() for i in range(0,256): int_terms[i] = self.m.parseTerm(str(i)) # Build the IntList with the costmap data map_list = mtIL # There is no need to build the map, because it will be read from the hook # for c in self.map_data: # map_list = intlist(map_list, int_terms[c]) cycles = str(max(int(self.w * self.h / 20), self.w + self.h)) # Same number of cycles as ROS path_cycles = str(4 * self.w) self.static_args = [ cmap(map_list), self.m.parseTerm(str(int(self.w))), self.m.parseTerm(str(int(self.h))), self.m.parseTerm(cycles), self.m.parseTerm(path_cycles), ] # Hook for "op get : CostMap Nat Nat Nat -> Float" class MapHook(maude.Hook): def __init__(self, parent): super().__init__() self.parent = parent # DirectProfiler object to access attributes as the map or the Maude module for parsing self.cache = dict() # Dictionary int in [0..255] -> Maude term representing the corresponding Float for i in range(0, 256): self.cache[i] = self.parent.m.parseTerm(str(float(i))) def run(self, term, data): try: _, x, y, ncols = [int(arg) for arg in term.arguments()] cell_value = self.parent.map_data[y * ncols + x] ret_term = self.cache[cell_value] # print(f'FAST {term} --> {ret_term}') return ret_term except Exception as e: print('hook:', e) self.mapHook = MapHook(self) maude.connectEqHook('get', self.mapHook)
def parse_initial_data(args): """Inits Maude and parse common initial data of a model-checking problem""" maude.init(advise=args.advise) data = InitialData() # Checks whether the file exists data.filename = find_maude_file(args.file) if data.filename is None: usermsgs.print_error('No such file.') return None if not maude.load(args.file): usermsgs.print_error('Error loading file') return None # Loads the module if args.module is None: data.module = maude.getCurrentModule() if data.module is None: usermsgs.print_error('No last module.') return None else: data.module = maude.getModule(args.module) if data.module is None: usermsgs.print_error(f'Module {args.module} does not exist.') return None # Loads a metamodule (if required) if args.metamodule is not None: mt = data.module.parseTerm(args.metamodule) if mt is None: usermsgs.print_error('Bad parse for metamodule term.') return None data.metamodule = mt data.module = maude.downModule(mt) if data.module is None: usermsgs.print_error('Bad metamodule.') return None # Parse the initial term data.term = data.module.parseTerm(args.initial) if data.term is None: usermsgs.print_error('Bad parse for initial term') return None # Parse the strategy if args.strategy is not None: data.strategy = data.module.parseStrategy(args.strategy) if data.strategy is None: usermsgs.print_error('Bad parse for strategy') return None else: data.strategy = None # Opaque strategies and full matchrew data.opaque = [] if args.opaque == '' else args.opaque.split(',') data.full_matchrew = args.full_matchrew return data
## ## Model checking ## # Load Maude maude.init(advise=False) # Construct the module where to model check membrane systems maude.load(args.file) if args.module is None: args.module = str(maude.getCurrentModule()) maude.load('multistrat') ms_external = maude.getModule('MULTISTRAT-EXTERNAL') if ms_external is None: print( 'Error: cannot find multistrategy infraestructure (multistrat.maude).') sys.exit(1) term_kind = ms_external.findSort('Term').kind() module_kind = ms_external.findSort('Module').kind() strategy_kind = ms_external.findSort('StrategyList').kind() ms_context = ms_external.findSort('MSContext').kind() ms_threadset = ms_external.findSort('MSThreadSet').kind() result_pair = ms_external.findSort('ResultPair') strategy_sort = ms_external.findSort('Strategy') ms_formula = ms_external.findSort('Formula').kind()
# Try to open the membrane specification file and prepare it try: with open(args.file, 'r') as membf: membs = membf.read() except FileNotFoundError as fnfe: print(fnfe) sys.exit(1) # Escape line breaks and other to make this a Maude string membs = membs.replace('\n', '\\n').replace('"', '\\"').replace('\t', ' ') # Construct the module where to model check membrane systems maude.load('memparse') membrane_external = maude.getModule('MEMBRANE-EXTERNAL') module_term = membrane_external.parseTerm(f'makeMMCModule("{membs}", {"false" if args.priority == "weak" else "true"}, {args.objbound})') nrewrites = module_term.reduce() if args.verbose: print(f'Rewriting model generated from membrane specification ({nrewrites} rewrites)') # The rewrite theory for the membrane system as a Module object mmc_module = maude.downModule(module_term) if mmc_module is None: print('Error when computing the Maude module for the membrane system.') sys.exit(1) # Parse the initial membrane t = mmc_module.parseTerm(args.membrane)