class StandardConsumer(multiprocessing.Process): def __init__(self, task_queue, result_queue, cfr, timeQueue, index, outputFileParentName, num_consumers, s, consumerConstraints): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue self.timeQueue = timeQueue self.cfr = cfr self.solver = s self.consumerConstraints = consumerConstraints self.index = index self.num_consumers = num_consumers self.clock = Clock() def run(self): num_solutions = 0 self.clock.tick("Consumer " + str(self.index)) while True: next_task = self.task_queue.get() try: if next_task == "Poison" or (num_solutions == Options.NUM_INSTANCES): self.task_queue.task_done() break except: pass self.solver.push() self.solver.add(self.consumerConstraints[int(next_task)]) self.clock.tick("Task " + str(next_task)) while self.solver.check( ) == Common.SAT and num_solutions != Options.NUM_INSTANCES: model = self.solver.model() self.result_queue.put(model_to_string(self.cfr, model)) num_solutions = num_solutions + 1 preventSameModel(self.cfr, self.solver, model) self.task_queue.task_done() self.clock.tock("Task " + str(next_task)) self.solver.pop() self.clock.tock("Consumer " + str(self.index)) self.timeQueue.put(self.clock) return 0
class StandardConsumer(multiprocessing.Process): def __init__(self, task_queue, result_queue, cfr, timeQueue, index, outputFileParentName, num_consumers, s, consumerConstraints): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue self.timeQueue = timeQueue self.cfr = cfr self.solver = s self.consumerConstraints = consumerConstraints self.index = index self.num_consumers = num_consumers self.clock = Clock() def run(self): num_solutions = 0 self.clock.tick("Consumer " + str(self.index)) while True: next_task = self.task_queue.get() try: if next_task == "Poison" or (num_solutions == Options.NUM_INSTANCES): self.task_queue.task_done() break except: pass self.solver.push() self.solver.add(self.consumerConstraints[int(next_task)]) self.clock.tick("Task " + str(next_task)) while self.solver.check() == Common.SAT and num_solutions != Options.NUM_INSTANCES: model = self.solver.model() self.result_queue.put(model_to_string(self.cfr, model)) num_solutions = num_solutions + 1 preventSameModel(self.cfr, self.solver, model) self.task_queue.task_done() self.clock.tock("Task " + str(next_task)) self.solver.pop() self.clock.tock("Consumer " + str(self.index)) self.timeQueue.put(self.clock) return 0
class ParSolver(): def __init__(self, cfr, module, solver, metrics_variables, metrics_objective_direction): self.cfr = cfr self.module = module self.solvers = replicateSolver(solver, Options.CORES) self.metrics_variables = metrics_variables self.metrics_objective_direction = metrics_objective_direction self.clock = Clock() self.consumerConstraints = self.splitter() def run(self): if not self.consumerConstraints: self.cfr.metric = Common.BOUND return [] mgr = multiprocessing.Manager() taskQueue = mgr.Queue() solutions = mgr.Queue() timeQueue = mgr.Queue() # Enqueue initial tasks for i in range(Options.NUM_SPLIT): taskQueue.put(i) for i in range(Options.CORES): taskQueue.put("Poison") # Start consumers #case: objectives if self.metrics_variables: self.consumers = [ Consumer.GIAConsumer(taskQueue, solutions, self.cfr, timeQueue, i, "out", Options.CORES, j, self.metrics_variables, self.metrics_objective_direction, self.consumerConstraints) for i,j in zip(range(Options.CORES), self.solvers)] #case: no objectives else: self.consumers = [ Consumer.StandardConsumer(taskQueue, solutions, self.cfr, timeQueue, i, "out", Options.CORES, j, self.consumerConstraints) for i,j in zip(range(Options.CORES), self.solvers)] self.clock.tick("ParSolver") for w in self.consumers: w.start() TERMINATED = False for w in self.consumers: if Options.TIME_OUT != 0: w.join(Options.TIME_OUT) else: w.join() if w.is_alive(): TERMINATED = True w.terminate() if TERMINATED: GeneralHeuristics.safe_raise_heuristic_failure_exception("Heuristic Timed Out") results = [] while not solutions.empty(): result = solutions.get() results.append(result) while not timeQueue.empty(): clock = timeQueue.get() self.clock = self.clock.combineClocks(clock) self.clock.tick("Merge") merged_results = self.merge(results) self.clock.tock("Merge") self.clock.tock("ParSolver") self.clock.getParallelStats(self.cfr) return merged_results def merge(self, results): if self.metrics_variables: results = self.removeDominatedAndEqual(results) return [i for (i,_) in results] else: return list(set(results)) def checkDominated(self, l, r): worseInOne = False betterInOne = False for i in range(len(l)): ml = l[i] mr = r[i] if self.metrics_objective_direction[i] == METRICS_MAXIMIZE: if ml < mr: worseInOne = True elif ml > mr: betterInOne = True elif self.metrics_objective_direction[i] == METRICS_MINIMIZE: if ml > mr: worseInOne = True elif ml < mr: betterInOne = True if (worseInOne and not betterInOne): return True return False def removeDominatedAndEqual(self, results): count = len(results) removalList = [False for _ in range(count)] for i in range(count): for j in range(count): if i != j: if self.checkDominated(results[i][1], results[j][1]): removalList[i] = True elif i < j and (results[i][0] == results[j][0] or results[i][1] == results[j][1]): removalList[i] = True nonDominated = [] for i in range(len(removalList)): if not removalList[i]: nonDominated.append(results[i]) return nonDominated def splitter(self): heuristic = GeneralHeuristics.heuristics[Options.SPLIT] return heuristic(self.cfr, self.module, Options.NUM_SPLIT)
class GIAConsumer(multiprocessing.Process): def __init__(self, task_queue, result_queue, cfr, timeQueue, index, outputFileParentName, num_consumers, s, metrics_variables, metrics_objective_direction, consumerConstraints): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue self.timeQueue = timeQueue self.cfr = cfr self.solver = s self.consumerConstraints = consumerConstraints self.index = index self.num_consumers = num_consumers self.ParetoFront = [] self.clock = Clock() self.GIAOptions = GuidedImprovementAlgorithmOptions(verbosity=0, \ incrementallyWriteLog=False, \ writeTotalTimeFilename="timefile.csv", \ writeRandomSeedsFilename="randomseed.csv", useCallLogs=False) self.GIAAlgorithm = GuidedImprovementAlgorithm(self.cfr, self.solver, metrics_variables, \ metrics_objective_direction, [], options=self.GIAOptions) def addParetoPoints(self, point): self.ParetoFront.append(point) def run(self): num_solutions = 0 self.clock.tick("Consumer " + str(self.index)) while True: next_task = self.task_queue.get() try: if next_task == "Poison" or (num_solutions == Options.NUM_INSTANCES): self.task_queue.task_done() break except: pass self.solver.push() self.solver.add(self.consumerConstraints[int(next_task)]) self.consumerConstraints[int(next_task)] self.clock.tick("Task " + str(next_task)) total_sat_calls = 0 total_unsat_time = 0 while True: if self.GIAAlgorithm.s.check( ) != Common.SAT or num_solutions == Options.NUM_INSTANCES: self.clock.tock("Task " + str(next_task)) self.task_queue.task_done() self.solver.pop() break else: prev_solution = self.GIAAlgorithm.s.model() self.GIAAlgorithm.s.push() NextParetoPoint, _local_count_unsat_calls, _local_count_unsat_calls = self.GIAAlgorithm.ranToParetoFront( prev_solution) self.addParetoPoints(NextParetoPoint) metric_values = self.GIAAlgorithm.get_metric_values( NextParetoPoint) self.result_queue.put( (model_to_string(self.cfr, NextParetoPoint), metric_values)) self.GIAAlgorithm.s.pop() tmpNotDominatedByNextParetoPoint = self.GIAAlgorithm.ConstraintNotDominatedByX( NextParetoPoint) self.GIAAlgorithm.s.add(tmpNotDominatedByNextParetoPoint) num_solutions = num_solutions + 1 self.clock.tock("Consumer " + str(self.index)) print("Total Sat Calls: " + total_sat_calls) print("Total Unsat Time: " + total_unsat_time) self.timeQueue.put(self.clock) return 0
class GIAConsumer(multiprocessing.Process): def __init__(self, task_queue, result_queue, cfr, timeQueue, index, outputFileParentName, num_consumers, s, metrics_variables, metrics_objective_direction, consumerConstraints): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue self.timeQueue = timeQueue self.cfr = cfr self.solver = s self.consumerConstraints = consumerConstraints self.index = index self.num_consumers = num_consumers self.ParetoFront = [] self.clock = Clock() self.GIAOptions = GuidedImprovementAlgorithmOptions(verbosity=0, \ incrementallyWriteLog=False, \ writeTotalTimeFilename="timefile.csv", \ writeRandomSeedsFilename="randomseed.csv", useCallLogs=False) self.GIAAlgorithm = GuidedImprovementAlgorithm(self.cfr, self.solver, metrics_variables, \ metrics_objective_direction, [], options=self.GIAOptions) def addParetoPoints(self, point): self.ParetoFront.append(point) def run(self): num_solutions = 0 self.clock.tick("Consumer " + str(self.index)) while True: next_task = self.task_queue.get() try: if next_task == "Poison" or (num_solutions == Options.NUM_INSTANCES): self.task_queue.task_done() break except: pass self.solver.push() self.solver.add(self.consumerConstraints[int(next_task)]) self.consumerConstraints[int(next_task)] self.clock.tick("Task " + str(next_task)) total_sat_calls = 0 total_unsat_time = 0 while True: if self.GIAAlgorithm.s.check() != Common.SAT or num_solutions == Options.NUM_INSTANCES: self.clock.tock("Task " + str(next_task)) self.task_queue.task_done() self.solver.pop() break else: prev_solution = self.GIAAlgorithm.s.model() self.GIAAlgorithm.s.push() NextParetoPoint, _local_count_unsat_calls, _local_count_unsat_calls = self.GIAAlgorithm.ranToParetoFront(prev_solution) self.addParetoPoints(NextParetoPoint) metric_values = self.GIAAlgorithm.get_metric_values(NextParetoPoint) self.result_queue.put((model_to_string(self.cfr, NextParetoPoint), metric_values)) self.GIAAlgorithm.s.pop() tmpNotDominatedByNextParetoPoint = self.GIAAlgorithm.ConstraintNotDominatedByX(NextParetoPoint) self.GIAAlgorithm.s.add(tmpNotDominatedByNextParetoPoint) num_solutions = num_solutions + 1 self.clock.tock("Consumer " + str(self.index)) print("Total Sat Calls: " + total_sat_calls) print("Total Unsat Time: " + total_unsat_time) self.timeQueue.put(self.clock) return 0
class ParSolver(): def __init__(self, cfr, module, solver, metrics_variables, metrics_objective_direction): self.cfr = cfr self.module = module self.solvers = replicateSolver(solver, Options.CORES) self.metrics_variables = metrics_variables self.metrics_objective_direction = metrics_objective_direction self.clock = Clock() self.consumerConstraints = self.splitter() def run(self): if not self.consumerConstraints: self.cfr.metric = Common.BOUND return [] mgr = multiprocessing.Manager() taskQueue = mgr.Queue() solutions = mgr.Queue() timeQueue = mgr.Queue() # Enqueue initial tasks for i in range(Options.NUM_SPLIT): taskQueue.put(i) for i in range(Options.CORES): taskQueue.put("Poison") # Start consumers #case: objectives if self.metrics_variables: self.consumers = [ Consumer.GIAConsumer(taskQueue, solutions, self.cfr, timeQueue, i, "out", Options.CORES, j, self.metrics_variables, self.metrics_objective_direction, self.consumerConstraints) for i, j in zip(range(Options.CORES), self.solvers) ] #case: no objectives else: self.consumers = [ Consumer.StandardConsumer(taskQueue, solutions, self.cfr, timeQueue, i, "out", Options.CORES, j, self.consumerConstraints) for i, j in zip(range(Options.CORES), self.solvers) ] self.clock.tick("ParSolver") for w in self.consumers: w.start() TERMINATED = False for w in self.consumers: if Options.TIME_OUT != 0: w.join(Options.TIME_OUT) else: w.join() if w.is_alive(): TERMINATED = True w.terminate() if TERMINATED: GeneralHeuristics.safe_raise_heuristic_failure_exception( "Heuristic Timed Out") results = [] while not solutions.empty(): result = solutions.get() results.append(result) while not timeQueue.empty(): clock = timeQueue.get() self.clock = self.clock.combineClocks(clock) self.clock.tick("Merge") merged_results = self.merge(results) self.clock.tock("Merge") self.clock.tock("ParSolver") self.clock.getParallelStats(self.cfr) return merged_results def merge(self, results): if self.metrics_variables: results = self.removeDominatedAndEqual(results) return [i for (i, _) in results] else: return list(set(results)) def checkDominated(self, l, r): worseInOne = False betterInOne = False for i in range(len(l)): ml = l[i] mr = r[i] if self.metrics_objective_direction[i] == METRICS_MAXIMIZE: if ml < mr: worseInOne = True elif ml > mr: betterInOne = True elif self.metrics_objective_direction[i] == METRICS_MINIMIZE: if ml > mr: worseInOne = True elif ml < mr: betterInOne = True if (worseInOne and not betterInOne): return True return False def removeDominatedAndEqual(self, results): count = len(results) removalList = [False for _ in range(count)] for i in range(count): for j in range(count): if i != j: if self.checkDominated(results[i][1], results[j][1]): removalList[i] = True elif i < j and (results[i][0] == results[j][0] or results[i][1] == results[j][1]): removalList[i] = True nonDominated = [] for i in range(len(removalList)): if not removalList[i]: nonDominated.append(results[i]) return nonDominated def splitter(self): heuristic = GeneralHeuristics.heuristics[Options.SPLIT] return heuristic(self.cfr, self.module, Options.NUM_SPLIT)