From a0d2356700712d26a4bf6cc5778c8628b2d7464e Mon Sep 17 00:00:00 2001 From: VIGNET Pierre <pierre.vignet@irisa.fr> Date: Mon, 25 Nov 2019 20:19:36 +0100 Subject: [PATCH] [cmd] Implement & Refactor the conversion of previous frontier places to numerical values => big perf gain --- command_line/cadbiom_cmd/solution_search.py | 63 ++++++++++++++------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/command_line/cadbiom_cmd/solution_search.py b/command_line/cadbiom_cmd/solution_search.py index 8a44852..71456bb 100644 --- a/command_line/cadbiom_cmd/solution_search.py +++ b/command_line/cadbiom_cmd/solution_search.py @@ -130,6 +130,20 @@ def make_logical_formula(previous_frontier_places, start_prop): return add_start_prop('') +def get_dimacs_start_properties(mcla, previous_frontier_places): + """Translate frontier places to their numerical values + thanks to the current unfolder. + + It's much more efficient than using the ANTLR grammar to parse formulas + for each new query. + """ + dimacs_start = list() + [dimacs_start.append( + [-mcla.unfolder.var_dimacs_code(place) for place in frontier_places] + ) + for frontier_places in previous_frontier_places] + + def main2(chart_file, mac_file, mac_step_file, mac_complete_file, mac_strong_file, steps, final_prop, start_prop, inv_prop, all_macs, continue_run, limit): """ @@ -207,19 +221,15 @@ def main2(chart_file, mac_file, mac_step_file, mac_complete_file, mac_strong_fil try: ## TODO: see docstring of read_mac_file previous_frontier_places = read_mac_file(mac_file) - current_start_prop = make_logical_formula(previous_frontier_places, - start_prop) LOGGER.info("%s:: Reload previous frontier places: %s", final_prop, len(previous_frontier_places)) except IOError: LOGGER.warning("%s:: mac file not found!", final_prop) previous_frontier_places = set() - current_start_prop = start_prop else: # New run previous_frontier_places = set() - current_start_prop = start_prop # Compute the number of previously computed frontier places @@ -231,25 +241,30 @@ def main2(chart_file, mac_file, mac_step_file, mac_complete_file, mac_strong_fil final_prop) return - - ## Find macs in an optimized way with find_macs() (see the docstring for more info) - LOGGER.info("%s:: Start property: %s", final_prop, current_start_prop) + ## Find macs in an optimized way with find_macs() (see the doc for more info) + LOGGER.info("%s:: Start property: %s", final_prop, start_prop) # with PyCallGraph(output=GraphvizOutput()): find_macs(mcla, mac_file, mac_step_file, mac_complete_file, - steps, final_prop, current_start_prop, inv_prop, limit, current_nb_sols) + steps, final_prop, start_prop, inv_prop, limit, current_nb_sols, + previous_frontier_places) return - - ## Alternative and deprecated way + ############################################################################ + ############################################################################ + ## Alternative and deprecated less efficient way ## Find mac one by one with find_mac() (see the docstring for more info) while True: + # Compute the formula of the next start_property + current_start_prop = make_logical_formula(previous_frontier_places, + start_prop) LOGGER.info("%s:: Start property: %s", final_prop, current_start_prop) ret = \ find_mac(mcla, mac_file, mac_step_file, mac_complete_file, - steps, final_prop, current_start_prop, inv_prop) + steps, final_prop, start_prop, inv_prop, + previous_frontier_places) if not ret: # No new solution/not satisfiable @@ -264,10 +279,6 @@ def main2(chart_file, mac_file, mac_step_file, mac_complete_file, mac_strong_fil final_prop, previous_frontier_places) - # Compute the formula of the next start_property - current_start_prop = make_logical_formula(previous_frontier_places, - start_prop) - # If set to True (not default), search all macs with # less or equal the maxium of steps defined with the argument `steps`. # If all_macs == True: The limit is always the maximal number given @@ -283,15 +294,13 @@ def main2(chart_file, mac_file, mac_step_file, mac_complete_file, mac_strong_fil final_prop) return - LOGGER.debug("%s:: Next start_prop formula: %s in %s steps", - final_prop, - current_start_prop, - steps) + LOGGER.debug("%s:: Next solution will be in %s steps", final_prop, steps) def find_macs(mcla, mac_file, mac_step_file, mac_complete_file, - steps, final_prop, start_prop, inv_prop, limit, current_nb_sols): + steps, final_prop, start_prop, inv_prop, limit, current_nb_sols, + previous_frontier_places): """Search for many solutions, save timings, and save frontiers. For every new solution, the system is NOT reinitialized, and a satisfiability @@ -307,12 +316,17 @@ def find_macs(mcla, :param limit: Limit the number of solutions. :param current_nb_sols: The current number of solutions already found. This number is used to limit the number of searched solutions. + :param previous_frontier_places: Set of frontier places tuples from previous + solutions. These tuples will be banned from the future solutions. :type limit: <int> :type current_nb_sols: <int> + :type previous_frontier_places: <set <tuple <str>>> :return: None """ # Build query query = MCLSimpleQuery(start_prop, inv_prop, final_prop) + # Translate frontier places to their numerical values + query.dim_start = get_dimacs_start_properties(mcla, previous_frontier_places) # Iterate on solutions for i, frontier_sol in enumerate(mcla.mac_search(query, steps), current_nb_sols): @@ -348,9 +362,9 @@ def find_macs(mcla, def find_mac(mcla, mac_file, mac_step_file, mac_complete_file, - steps, final_prop, start_prop, inv_prop): + steps, final_prop, start_prop, inv_prop, previous_frontier_places): """Search for 1 solution, save timings, save frontiers, and return it with - the current step. + the current step (deprecated, see find_macs()). For every new solution, the system is reinitialized, and a satisfiability test is made on a new query to evaluate the minimal number of steps for @@ -361,11 +375,16 @@ def find_mac(mcla, the previous solutions for example) in text format is very expensive because realized by the grammar ANTLR. + :param previous_frontier_places: Set of frontier places tuples from previous + solutions. These tuples will be banned from the future solutions. + :type previous_frontier_places: <set <tuple <str>>> :return: A tuple of activated frontiers and the current step. None if there is no new Solution or if problem is not satisfiable. """ # Build query query = MCLSimpleQuery(start_prop, inv_prop, final_prop) + # Translate frontier places to their numerical values + query.dim_start = get_dimacs_start_properties(mcla, previous_frontier_places) # Is the property reacheable ? reacheable = mcla.sq_is_satisfiable(query, steps) -- GitLab