Commit bf607f76 authored by VIGNET Pierre's avatar VIGNET Pierre
Browse files

Ability to use an input file of final properties; Multiprocessing for it; better logging

parent 32fb779e
......@@ -7,6 +7,10 @@ import argparse
import re
import os
from functools import partial
import sys
# Multiprocessing
from concurrent.futures import ProcessPoolExecutor, as_completed
import multiprocessing as mp
# Custom imports
from cadbiom.models.clause_constraints.mcl.MCLAnalyser import MCLAnalyser
......@@ -117,7 +121,7 @@ def main2(chart_file, cam_file, cam_step_file, cam_complete_file, cam_strong_fil
# Add theese frontier places to set of previous ones
# (tuple is hashable)
previous_frontier_places.add(tuple(frontier_places))
LOGGER.debug("Prev frontier places: " + \
LOGGER.debug(final_prop + ":: Prev frontier places: " + \
str(previous_frontier_places))
# Compute the formula of the next start_property
......@@ -125,7 +129,8 @@ def main2(chart_file, cam_file, cam_step_file, cam_complete_file, cam_strong_fil
start_prop)
steps = min_steps
LOGGER.debug(
"Next start_prop formula: {} in {} steps".format(start_prop, steps)
final_prop +
":: Next start_prop formula: {} in {} steps".format(start_prop, steps)
)
......@@ -145,44 +150,44 @@ def find_mac(mcla,
if reacheable:
LOGGER.info(
"Property {} is reacheable in {} steps".format(
final_prop + ":: Property {} is reacheable in {} steps".format(
final_prop, min_step
)
)
else:
LOGGER.info(
"Property {} is NOT reacheable in {} steps".format(
final_prop + ":: Property {} is NOT reacheable in {} steps".format(
final_prop, min_step
)
)
LOGGER.info("STOP the search!")
LOGGER.info(final_prop + ":: STOP the search!")
exit()
# Find next MAC
next_mac_object = mcla.next_mac(query, min_step)
if next_mac_object:
LOGGER.debug("Next MAC object:\n{}".format(next_mac_object))
LOGGER.debug(final_prop + ":: Next MAC object:\n{}".format(next_mac_object))
# Save MAC and timings
LOGGER.debug("Save MAC and timings...")
LOGGER.debug(final_prop + ":: Save MAC and timings...")
with open(cam_complete_file, 'a') as file:
next_mac_object.save(file)
# Save MAC
next_mac = next_mac_object.activated_frontier
LOGGER.debug("Save next MAC: {}".format(next_mac))
LOGGER.debug(final_prop + ":: Save next MAC: {}".format(next_mac))
with open(cam_file, 'a') as file:
file.write('\t'.join(next_mac) + '\n')
# Save min steps
min_step = mcla.unfolder.get_current_step()
LOGGER.debug("Save minimal steps: {}".format(min_step))
min_step = mcla.unfolder.get_current_step() - 1 # Magic number !
LOGGER.debug(final_prop + ":: Save minimal steps: {}".format(min_step))
with open(cam_step_file, 'a') as file:
file.write(str(min_step)+'\n')
return next_mac, min_step
else:
LOGGER.info("STOP the search! No more MAC.")
LOGGER.info(final_prop + ":: STOP the search! No more MAC.")
exit()
......@@ -204,9 +209,9 @@ def detect_model_type(mclanalyser, filepath):
}
try:
extension = re.search('^.*(\.[bcx|xml|cal]{3})', filepath).group(1)
LOGGER.debug("Find '" + extension + "' extension")
LOGGER.debug("Find '" + extension + "' extension: " + filepath)
except:
LOGGER.error("Unauthorized file")
LOGGER.error("Unauthorized file: " + filepath)
exit()
return build_func[extension]
......@@ -304,14 +309,71 @@ def main(chart_file, cam_file, cam_step_file, cam_complete_file, cam_strong_file
return 1
def compute_macs(args):
def launch_researchs(args):
"""
"""
params = args_to_param(args)
if params['final_prop']:
compute_macs(params)
else:
with open(params['input_file'], 'r') as fd:
g = (line.rstrip('\n') for line in fd)
final_properties = [prop for prop in g if prop != '']
print(final_properties)
def change_args(prop):
d = params.copy()
d['final_prop'] = prop
return d
with ProcessPoolExecutor(max_workers=mp.cpu_count()) as e:
futures_and_output = {e.submit(compute_macs,
change_args(job_property)
):job_property \
for job_property in final_properties} # Job name
nb_errors = 0
nb_done = 0
for future in as_completed(futures_and_output):
job_name = futures_and_output[future]
# On affiche les résultats si les futures en contiennent.
# Si elles contiennent une exception, on affiche l'exception.
if future.exception() is not None:
LOGGER.error("{} generated an exception: \n{}".format(
job_name,
future.exception())
)
nb_errors += 1
else:
# The end
LOGGER.info("{}... \t\t[Done]".format(job_name))
nb_done += 1
LOGGER.info("Ending: {} errors, {} done\nbye.".format(
nb_errors,
nb_done)
)
def compute_macs(params):
"""Launch Cadbiom search of MACs (Minimal Activation Conditions)"""
# Limit recursion
import sys
sys.setrecursionlimit(10000)
params = args_to_param(args)
# params = args_to_param(args)
# QUERY PARAMETERS
# Todo beware with type of separators in path..
......@@ -360,7 +422,30 @@ def args_to_param(args):
return {k: v for k, v in vars(args).items() if k != 'func'}
class readable_dir(argparse.Action):
class ReadableFile(argparse.Action):
"""
http://stackoverflow.com/questions/11415570/directory-path-types-with-argparse
"""
def __call__(self, parser, namespace, values, option_string=None):
prospective_file = values
if not os.path.isfile(prospective_file):
raise argparse.ArgumentTypeError(
"readable_file:{0} is not a valid path".format(
prospective_file)
)
if os.access(prospective_file, os.R_OK):
setattr(namespace, self.dest, prospective_file)
else:
raise argparse.ArgumentTypeError(
"readable_file:{0} is not a readable file".format(
prospective_file)
)
class ReadableDir(argparse.Action):
"""
http://stackoverflow.com/questions/11415570/directory-path-types-with-argparse
"""
......@@ -370,13 +455,17 @@ class readable_dir(argparse.Action):
if not os.path.isdir(prospective_dir):
raise argparse.ArgumentTypeError(
"readable_dir:{0} is not a valid path".format(prospective_dir))
"readable_dir:{0} is not a valid path".format(
prospective_dir)
)
if os.access(prospective_dir, os.R_OK):
setattr(namespace, self.dest, prospective_dir)
else:
raise argparse.ArgumentTypeError(
"readable_dir:{0} is not a readable dir".format(prospective_dir))
"readable_dir:{0} is not a readable dir".format(
prospective_dir)
)
if __name__ == "__main__":
......@@ -397,14 +486,16 @@ if __name__ == "__main__":
parser_input_file = subparsers.add_parser('compute_macs',
help=compute_macs.__doc__)
parser_input_file.add_argument('chart_file')
parser_input_file.add_argument('final_prop')
# parser_input_file.add_argument('final_prop')
group = parser_input_file.add_mutually_exclusive_group()
group.add_argument('final_prop', nargs='?')
group.add_argument('--input_file', action=ReadableFile, nargs='?')
parser_input_file.add_argument('--steps', type=int, nargs='?', default=10)
parser_input_file.add_argument('--start_prop', nargs='?', default=None)
parser_input_file.add_argument('--inv_prop', nargs='?', default=None)
parser_input_file.add_argument('--output', action=readable_dir, nargs='?',
parser_input_file.add_argument('--output', action=ReadableDir, nargs='?',
default='result/')
parser_input_file.set_defaults(func=compute_macs)
parser_input_file.set_defaults(func=launch_researchs)
# get program args and launch associated command
args = parser.parse_args()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment