def get_solutions( self, num_solutions: int = 1, get_all_solutions: bool = False, selected_features: typing.Optional[typing.Tuple[str, int]] = None, ) -> typing.Optional[typing.Dict[str, int]]: instance = minizinc.Instance(self.solver, self.model) if selected_features: for feature_name, feature_value in selected_features: instance[feature_name] = feature_value if get_all_solutions: solutions = instance.solve(all_solutions=True).solution else: solutions = instance.solve(nr_solutions=num_solutions) if solutions: return [ { key: value for key, value in solution.__dict__.items() if key.startswith("feature") } for solution in solutions ] return None
def check_solution( model: minizinc.Model, result: minizinc.Result, solver: minizinc.Solver, solution_nrs: Optional[Sequence[int]] = None, ) -> bool: """Checks a solution to for a model using a given solver. Check the correctness of the solving process using a (different) solver configuration. An instance is branched and will be assigned all available values from a solution. The solver configuration is now used to confirm is assignment of the variables is correct. By default only the last solution will be checked. A sequence of solution numbers can be provided to check multiple solutions. Args: model (Model): To model for which the solution was provided result (Result): The solution to be checked solver (Solver): The solver configuration used to check the solutions. solution_nrs: The index set of solutions to be checked. (default: ``-1``) Returns: bool: True if the given solution are correctly verified. """ if solution_nrs is None: solution_nrs = [-1] instance = minizinc.Instance(solver, model) solutions = ( result.solution if isinstance(result.solution, list) else [result.solution] ) for i in solution_nrs: sol = solutions[i] with instance.branch() as child: for k, v in asdict(sol).items(): if k not in ("objective", "__output_item"): child[k] = v try: check = child.solve(timeout=timedelta(seconds=1)) if result.status != check.status: if check.status in [ minizinc.Status.SATISFIED, minizinc.Status.OPTIMAL_SOLUTION, ] and result.status in [ minizinc.Status.SATISFIED, minizinc.Status.OPTIMAL_SOLUTION, minizinc.Status.ALL_SOLUTIONS, ]: continue else: return False except minizinc.MiniZincError: if result.status != minizinc.Status.ERROR: return False return True
def __init__(self, quantite_objectif, liste_gallons): # Create a MiniZinc model self.model = mnz.Model() self.model.add_file("ProjSceau.mzn") # Transform Model into a instance gecode = mnz.Solver.lookup("gecode") self.inst = mnz.Instance(gecode, self.model) self.gallons = liste_gallons self.quantite_objectif = quantite_objectif self.inst["nbr_sceau"] = len(liste_gallons) self.inst["remplissage_final"] = quantite_objectif list_taille_sceau = [] list_remplissage_init = [] for g in self.gallons: list_taille_sceau.append(g.taille) list_remplissage_init.append(g.remplissage) self.inst["taille_sceau"] = list_taille_sceau self.inst["remplissage_initial"] = list_remplissage_init print("CONFIGURATION d'ORIGINE:") print("\tnombre sceaux : ", self.inst["nbr_sceau"]) print("\tremplissage_final : ", self.inst["remplissage_final"]) print("\ttaille_sceau : ", self.inst["taille_sceau"]) print("\tremplissage_initial : ", self.inst["remplissage_initial"])
async def run_instance(problem, model, data, config, timeout, stat_base, sol_file, stats_file): statistics = stat_base.copy() try: driver = minizinc.default_driver if config.minizinc is not None: driver = minizinc.CLI.CLIDriver(config.minizinc) instance = minizinc.Instance(config.solver, minizinc.Model(model), driver) if data is not None: instance.add_file(data, parse_data=False) is_satisfaction = instance.method == minizinc.Method.SATISFY for key, value in config.extra_data.items(): instance[key] = value start = time.perf_counter() with sol_file.open(mode="w") as file: async for result in instance.solutions( timeout=timeout, processes=config.processes, random_seed=config.random_seed, intermediate_solutions=True, free_search=config.free_search, optimisation_level=config.optimisation_level, **config.other_flags, ): solution = stat_base.copy() solution["status"] = str(result.status) if "time" in result.statistics: solution["time"] = result.statistics.pop( "time").total_seconds() if result.solution is not None: solution["solution"] = asdict(result.solution) solution["solution"].pop("_output_item", None) solution["solution"].pop("_checker", None) file.write(ruamel.yaml.dump([solution])) statistics.update(result.statistics) statistics["status"] = str(result.status) if result.solution is not None and not is_satisfaction: statistics["objective"] = result.solution.objective total_time = time.perf_counter() - start statistics["time"] = total_time except minizinc.MiniZincError as err: statistics["status"] = str(minizinc.result.Status.ERROR) statistics["error"] = str(err) for key, val in statistics.items(): if isinstance(val, timedelta): statistics[key] = val.total_seconds() ruamel.yaml.dump( statistics, stats_file.open(mode="w"), default_flow_style=False, )
def minizinc_model(): src = "float: a;\n" \ "var float: x;\n" \ "constraint x == a + 1;\n" \ "solve satisfy" model = minizinc.Model() model.add_string(src) solver = minizinc.Solver.lookup("cbc") inst = minizinc.Instance(solver, model) inst["a"] = 2 result = inst.solve() return result
def _solveOptimize(self, objstr:str, solver="gecode"): if not self.frozen: self.model.add_string(objstr) self.frozen = True gecode = mz.Solver.lookup(solver) instance = mz.Instance(gecode, self.model) for param, value in self.params.items(): instance[param] = value result = instance.solve() if result.solution is None: return None return self.postprocessSolution(result.solution)
def check_solution( model: minizinc.Model, solution: Union[DataClass, Dict[str, Any]], status: minizinc.Status, solver: minizinc.Solver, ) -> bool: """Checks a solution for a model using the given solver. Check the correctness of the solving process using a (different) solver configuration. A new model instance is created and will be assigned all available values from the given solution. The Instance.solve() method is then used to ensure that the same solution with the same expected status is reached. Note that this method will not check the optimality of a solution. Args: model (Model): To model for which the solution was provided solution (Union[DataClass, Dict[str, Any]]): The solution to be checked status (Status): The expected (compatible) MiniZinc status solver (Solver): The solver configuration used to check the solution. Returns: bool: True if the given solution are correctly verified. """ instance = minizinc.Instance(solver, model) if is_dataclass(solution): solution = asdict(solution) for k, v in solution.items(): if k not in ("objective", "__output_item"): instance[k] = v try: check = instance.solve(timeout=timedelta(seconds=5)) if status == check.status: return True elif check.status in [ minizinc.Status.SATISFIED, minizinc.Status.OPTIMAL_SOLUTION, ] and status in [ minizinc.Status.SATISFIED, minizinc.Status.OPTIMAL_SOLUTION, minizinc.Status.ALL_SOLUTIONS, ]: return True else: return False except minizinc.MiniZincError: if status == minizinc.Status.ERROR: return True return False
def minizinc_model(): src = "int: a;\n" \ "int: b;\n" \ "var -100..100: x;\n" \ "constraint a < x;\n" \ "constraint x < b;\n" \ "solve satisfy" model = minizinc.Model() model.add_string(src) gecode = minizinc.Solver.lookup("gecode") inst = minizinc.Instance(gecode, model) inst["a"] = 1 inst["b"] = 4 result = inst.solve(all_solutions=True) return result
def __init__(self, nombre_moutons): # Create a MiniZinc model self.model = mnz.Model() self.model.add_file("ProjSauteMouton.mzn") # Transform Model into a instance gecode = mnz.Solver.lookup("gecode") self.inst = mnz.Instance(gecode, self.model) self.nb_moutons = nombre_moutons self.inst["nbr_m"] = nombre_moutons self.moutons = [] '''
def solver_exists(self, solver): solver_exists = pytest.solver_cache.get(solver, None) if solver_exists is None: try: s = mzn.Solver.lookup(solver) empty_model = mzn.Model() empty_model.add_string("solve satisfy;") instance = mzn.Instance(s, empty_model) instance.solve() solver_exists = True except (mzn.MiniZincError, LookupError) as error: solver_exists = False finally: pytest.solver_cache[solver] = solver_exists return solver_exists
def run(self, mzn_file, solver, default_options={}): """ Runs this test case given an mzn file path, a solver name and some default options. Any options specified in this test case directly will override those provided in default options. Returns a tuple containing: - the model produced - the result of running the solver - a list of expected results - the actual obtained result Pass the actual obtained result to passed() to determine if the test case passed. """ options = {k: v for k, v in default_options.items()} options.update(self.options) file = pathlib.Path(mzn_file) extra_files = [ file.parent.joinpath(other) for other in self.extra_files ] try: model = mzn.Model([file] + extra_files) solver = mzn.Solver.lookup(solver) instance = mzn.Instance(solver, model) if self.type == "solve": instance.output_type = Solution result = instance.solve(**options) obtained = Result.from_mzn(result) elif self.type == "compile": with instance.flat(**options) as (fzn, ozn, stats): obtained = FlatZinc.from_mzn(fzn, file.parent) result = obtained elif self.type == "output-model": with instance.flat(**options) as (fzn, ozn, stats): obtained = OutputModel.from_mzn(ozn, file.parent) result = obtained else: raise NotImplementedError("Unknown test case type") except mzn.MiniZincError as error: result = error obtained = Error.from_mzn(result) required = self.expected if isinstance(self.expected, list) else [self.expected] return model, result, required, obtained
def minizinc_model(): src = "int: a;\n" \ "int: b;\n" \ "int: c;\n" \ "var -100..100: x;\n" \ "constraint ((((a * pow(x, 2)) + (b * x)) + c) = 0);\n" \ "solve satisfy" model = minizinc.Model() model.add_string(src) gecode = minizinc.Solver.lookup("gecode") inst = minizinc.Instance(gecode, model) inst["a"] = 1 inst["b"] = 4 inst["c"] = 0 result = inst.solve(all_solutions=True) return result
def _solve(self, *how_to_solve, all_solutions, result_as, verbose, solver): solver = minizinc.Solver.lookup(solver) model = minizinc.Model() src = self.compile(how_to_solve) if verbose: print(src) model.add_string(src) inst = minizinc.Instance(solver, model) for name, param in self._ir.pars.items(): inst[name] = param.value for e in self._ir.enums: inst[e.__name__] = e result: minizinc.Result = inst.solve(all_solutions=all_solutions) if result_as is None: return Result(result) else: return result_as(result)
def _model(self, model, solvername=None): import minizinc if solvername is None: # default solver solvername = "gecode" # from superclass mzn_txt = self.convert(model) # minizinc-python API # Create a MiniZinc model mznmodel = minizinc.Model() mznmodel.add_string(mzn_txt) # Transform Model into a instance slv = minizinc.Solver.lookup(solvername) return minizinc.Instance(slv, mznmodel)
def schedule_evs(num_days, num_periods_day, peak_periods, off_peak_periods, num_evs, max_charge, total_energy, prices_2d, loads_2d, network_tariff_peak, network_tariff_off_peak, model_file="scripts/ev-scheduling.mzn"): off_peak_periods2 = {i + 1 for i in off_peak_periods}.copy() if network_tariff_peak == network_tariff_off_peak: peak_periods2 = {i + 1 for i in range(num_periods_day)}.copy() network_tariff_off_peak = 0 else: # minizinc index starts from 1 peak_periods2 = {i + 1 for i in peak_periods}.copy() # build a MiniZinc model model = mzn.Model(model_file) solver = mzn.Solver.lookup("mip") ins = mzn.Instance(solver, model) ins["num_days"] = num_days ins["num_periods_day"] = num_periods_day ins["PEAK_PERIODS"] = peak_periods2 ins["OFF_PEAK_PERIODS"] = off_peak_periods2 ins["num_evs"] = num_evs ins["max_charge"] = max_charge ins["total_energy"] = total_energy ins["wholesale_prices"] = prices_2d ins["network_tariff_peak"] = network_tariff_peak ins["network_tariff_off_peak"] = network_tariff_off_peak ins["existing_loads"] = loads_2d result = ins.solve() # organise results charge_ev_day_period = result.solution.charge_strategy minizinc_outputs = ast.literal_eval(result.solution._output_item) minizinc_outputs["time (ms)"] = [ result.statistics['solveTime'].microseconds * 0.001 ] return charge_ev_day_period, minizinc_outputs
def schedule_evs(num_days, prices_2d, loads_2d, network_tariff_peak, network_tariff_off_peak): # build a MiniZinc model model = mzn.Model(model_file) solver = mzn.Solver.lookup("coin-bc") ins = mzn.Instance(solver, model) ins["num_days"] = num_days ins["num_periods_day"] = num_periods_day ins["num_evs"] = num_evs ins["max_charge"] = max_charge ins["total_energy"] = total_energy ins["wholesale_prices"] = prices_2d ins["network_tariff_peak"] = network_tariff_peak ins["network_tariff_off_peak"] = network_tariff_off_peak ins["existing_loads"] = loads_2d result = ins.solve() return result
def calcular(self, siCondicionesA): self.crearVarRegiones() self.kitsPorUnidad() self.Unidades() self.costosAdecuacion() if(siCondicionesA): self.condicionesAdicionales() self.poblacion() self.noNegatividad() self.funcionObjetivo() # desde aca se resilve el codigo en minizinc, en alguna parte desde aca iria la funcion de parar en X minutos # Create a MiniZinc model model = mz.Model() model.add_string(self.stringFinal) # Transform Model into a instance gecode = mz.Solver.lookup("gecode") inst = mz.Instance(gecode, model) # Solve the instance result = inst.solve() print("************************* RESULTADOS MINIZINC *************************") for regionX in self.listaDeRegiones: nombreRegionX = str(regionX.get_nombreCorto()) + " = " resultadoX = result[str(regionX.get_nombreCorto())] print(resultadoX) print(nombreRegionX, end = "") print(resultadoX) self.stringResultado = self.stringResultado + nombreRegionX + str(resultadoX) + "\n" self.stringResultado = self.stringResultado + "Beneficio = " + str(result["Beneficio"]) + "\n" print("Beneficio", end = " = ") print(result["Beneficio"]) print("\n************************* FIN DE PROGRAMA *************************")
def solveSatisfy(self, timeout=None, numSolutions:int=0, solver="gecode" ) -> list[solution_t]: if not self.frozen: self.model.add_string(f'solve satisfy;') self.frozen = True gecode = mz.Solver.lookup(solver) instance = mz.Instance(gecode, self.model) for param, value in self.params.items(): instance[param] = value if numSolutions == 0 or numSolutions == "all": numSolutions = None allSolutions = True else: allSolutions = False result = instance.solve(nr_solutions=numSolutions, timeout=timeout, all_solutions=allSolutions) if result.solution is None: return [] elif isinstance(result.solution, list): return [self.postprocessSolution(sol) for sol in result.solution] else: return [self.postprocessSolution(result.solution)]
async def flatten(ctx, options: commands.Greedy[Option], *, arg: str): response = await ctx.send(random.choice(running_messages)) await ctx.message.add_reaction("⌛") arg = arg.strip("` \t") arguments = { "solver": no_solver, "timeout": timedelta(seconds=30), } try: arguments = Option.process(options, arguments) instance = minizinc.Instance(arguments["solver"]) instance.add_string(arg) with instance.flat(arguments["timeout"]) as (fzn, ozn, statistics): flatzinc = Path(fzn.name).read_text() output = f"```{flatzinc}```" except (OptionError, minizinc.MiniZincError) as err: output = "```" + str(err) + "```" await response.edit(content=output) await ctx.message.remove_reaction("⌛", bot.user) await ctx.message.add_reaction("✅")
async def mzn(ctx, options: commands.Greedy[Option], *, arg: str): response = await ctx.send(random.choice(running_messages)) await ctx.message.add_reaction("⌛") arg = arg.strip("` \t") arguments = { "solver": chuffed, "timeout": timedelta(seconds=30), } try: arguments = Option.process(options, arguments) instance = minizinc.Instance(arguments["solver"]) instance.add_string(arg) result = await instance.solve_async(timeout=arguments["timeout"]) output = f"`{result.status}` in {result.statistics['time'].total_seconds()}s: {'```' + str(result.solution) + '```' if result.solution is not None else 'No Solution'}" except (OptionError, minizinc.MiniZincError) as err: output = "```" + str(err) + "```" await response.edit(content=output) await ctx.message.remove_reaction("⌛", bot.user) await ctx.message.add_reaction("✅")
def __init__(self, model): self.mzn_instance = minizinc.Instance(solver, model) self.nogoods = [] self.stayaway = [] self.staynear = []
import minizinc from minizinc import Model print("Hi there, excited to run MZN") # Create a MiniZinc model basic_voting_model = Model("base_model.mzn") gecode_solver = minizinc.Solver.lookup("gecode") instance = minizinc.Instance(gecode_solver, basic_voting_model) # set some parameters like this # instance["a"] = 1 # now solve result = instance.solve(all_solutions=True) for i in range(len(result)): print("x = {}, y = {}".format(result[i, "x"], result[i, "y"])) print(result[i])
def csp(blocks, sheets, matches): print('numblocks', len(blocks)) blocks = blocks[:] model = minizinc.Model() model.add_string(""" include "globals.mzn"; int: num_blocks; int: num_rows; int: num_cols; set of int: b=1..num_blocks; set of int: rows=1..num_rows; set of int: cols=1..num_cols; array[b] of cols: x1; array[b] of cols: x2; array[b] of rows: y1; array[b] of rows: y2; array[b] of int: w; array[b] of int: h; array[rows] of var int: rowsa; array[cols] of var int: colsa; int: num_left; int: num_above; set of int: l=1..num_left; set of int: t=1..num_above; array[l] of cols: left1; array[l] of cols: left2; array[t] of rows: above1; array[t] of rows: above2; int: num_left_equal; int: num_above_equal; set of int: le=1..num_left_equal; set of int: te=1..num_above_equal; array[le] of cols: left_equal1; array[le] of cols: left_equal2; array[te] of rows: above_equal1; array[te] of rows: above_equal2; int: max_col = sum(w) + 1; int: max_row = sum(h) + 1; array[b] of var bool: use_block; array[b] of var int: wf; array[b] of var int: hf; constraint forall(bl in b) ((use_block[bl] -> wf[bl] = w[bl]) /\ (not use_block[bl] -> wf[bl] = 0)); constraint forall(bl in b) ((use_block[bl] -> hf[bl] = h[bl]) /\ (not use_block[bl] -> hf[bl] = 0)); array[l] of var bool: use_left; array[t] of var bool: use_above; array[le] of var bool: use_left_equal; array[te] of var bool: use_above_equal; constraint forall(c in cols) (colsa[c] > 0 /\ colsa[c] <= max_col); constraint forall(r in rows) (rowsa[r] > 0 /\ rowsa[r] <= max_row); constraint diffn([colsa[x1[bl]] | bl in b], [rowsa[y1[bl]] | bl in b], [wf[bl] | bl in b], [hf[bl] | bl in b]); constraint forall(i in b) (colsa[x1[i]] + w[i] -1= colsa[x2[i]]); constraint forall(i in b) (rowsa[y1[i]] + h[i] -1= rowsa[y2[i]]); constraint forall(i in l) (use_left[i] <-> (colsa[left1[i]] < colsa[left2[i]])); constraint forall(i in t) (use_above[i] <-> (rowsa[above1[i]] < rowsa[above2[i]])); constraint forall(i in le) (use_left_equal[i] <-> (colsa[left_equal1[i]] = colsa[left_equal2[i]])); constraint forall(i in te) (use_above_equal[i] <-> (rowsa[above_equal1[i]] = rowsa[above_equal2[i]])); %solve satisfy; %solve minimize sum(rowsa) + sum(colsa); solve maximize sum(use_left) + sum(use_above) + sum(use_block) + sum(use_left_equal) + sum(use_above_equal); """) cols = sorted( list( set(block.x1 for block in blocks).union(set(block.x2 for block in blocks)))) rows = sorted( list( set(block.y1 for block in blocks).union(set(block.y2 for block in blocks)))) relative_left, relative_left_equals = _parse_indices(cols, matches) relative_above, relative_above_equals = _parse_indices(rows, matches) colsi = {col: i + 1 for i, col in enumerate(cols)} rowsi = {row: i + 1 for i, row in enumerate(rows)} left, above = _location_constraints(cols, rows, sheets, matches) left = [(l1, l2) for l1, l2 in left if l1 in cols and l2 in cols] + relative_left above = [(a1, a2) for a1, a2 in above if a1 in rows and a2 in rows] + relative_above print('blocks', blocks) ProjectedBlock = collections.namedtuple('ProjectedBlock', 'x1 y1 x2 y2 width height') pblocks = list( set( ProjectedBlock(block.x1, block.y1, block.x2, block.y2, block.width, block.height) for block in blocks)) for b in blocks: print(' ', b) print(len(blocks), len(pblocks)) for b in pblocks: print(' ', b) print('pblocks', len(pblocks), pblocks) print('colsi', colsi) print('rowsi', rowsi) gecode = minizinc.Solver.lookup("chuffed") minst = minizinc.Instance(gecode, model) inst = {} inst['num_blocks'] = len(pblocks) inst['num_rows'] = len(rows) inst['num_cols'] = len(cols) inst['x1'] = [colsi[block.x1] for block in pblocks] inst['x2'] = [colsi[block.x2] for block in pblocks] inst['y1'] = [rowsi[block.y1] for block in pblocks] inst['y2'] = [rowsi[block.y2] for block in pblocks] inst['w'] = [block.width for block in pblocks] inst['h'] = [block.height for block in pblocks] inst['num_left'] = len(left) inst['num_above'] = len(above) inst['left1'] = [colsi[l1] for l1, _ in left] inst['left2'] = [colsi[l2] for _, l2 in left] inst['above1'] = [rowsi[a1] for a1, _ in above] inst['above2'] = [rowsi[a2] for _, a2 in above] inst['num_left_equal'] = len(relative_left_equals) inst['num_above_equal'] = len(relative_above_equals) inst['left_equal1'] = [colsi[l1] for l1, _ in relative_left_equals] inst['left_equal2'] = [colsi[l2] for _, l2 in relative_left_equals] inst['above_equal1'] = [rowsi[a1] for a1, _ in relative_above_equals] inst['above_equal2'] = [rowsi[a2] for _, a2 in relative_above_equals] print(inst) for k, v in inst.items(): minst[k] = v # Solve the instance print('CSP') result = minst.solve(all_solutions=False) print('res', result) print(result['rowsa']) print(result['colsa']) assignment = {col: r for col, r in zip(cols, result['colsa'])} assignment.update(**{row: r for row, r in zip(rows, result['rowsa'])}) used_blocks = {} for block, used in zip(pblocks, result['use_block']): used_blocks[block] = used print(used) if not used: print('Warning not used:', block) for oblock in blocks: if oblock.x1 == block.x1 and oblock.y1 == block.y1 and oblock.x2 == block.x2 and oblock.y2 == block.y2: print('Original block:', oblock) print('assignment', assignment) return assignment
def run_minizinc_model(params): mdl_name, instance_name, timeout = params instance_path = os.path.join(INSTANCE_FOLDER, instance_name) if not os.path.isfile(mdl_name): raise Exception("ERROR: mdl_name not found: ", mdl_name) if not os.path.isfile(instance_path): raise Exception("ERROR: instance_name not found: ", instance_name) print("*** Processing model {} with instance {}".format(mdl_name, instance_name)) model = minizinc.Model([mdl_name]) instance = minizinc.Instance(SOLVER, model) with open(instance_path, 'r') as f: input_data = json.load(f) scenesLength, actorsToScenes, actorsCosts = input_data['scenesLength'],input_data['actorsToScenes'], input_data['actorsCosts'] num_scenes = len(scenesLength) num_actors = len(actorsCosts) if "1" in mdl_name: actorsToScenes_new = np.zeros((len(actorsCosts), len(scenesLength))) for actor, scenes in enumerate(actorsToScenes): actorsToScenes_new[actor, scenes] = 1 data = { "num_scenes": len(scenesLength), "num_actors": len(actorsCosts), "max_cost": max(actorsCosts), "duration": scenesLength, "actor_cost": actorsCosts, "actorsToScenes": actorsToScenes_new.astype(int).tolist() } else: actorsToScenes_new = [set([i + 1 for i in scenes]) for scenes in actorsToScenes] data = { "num_scenes": len(scenesLength), "num_actors": len(actorsCosts), "max_cost": max(actorsCosts), "max_SceneDuration": max(scenesLength), "max_ActorCost":max(actorsCosts), "duration": scenesLength, "cost": actorsCosts, "actorsToScenes": actorsToScenes_new } for key, val in data.items(): instance[key] = val msol = instance.solve(verbose=True, timeout=datetime.timedelta(seconds=timeout)) # output= { # # } if msol: results = [ msol.status.name, msol.solution.objective, msol.statistics['initTime'].total_seconds(), msol.statistics['solveTime'].total_seconds(), msol.statistics['variables']] if "1" in mdl_name: scene_order = msol['scene_order'] else: scene_order = msol['order'] success = True else: results = [msol.status.name if msol else "NOTFOUND"] success = False scene_order = None return success, mdl_name, instance_name, timeout, num_actors, num_scenes, scene_order, results
def partial_schedule(volunteers, vehicle_request): # create an array of preferredHours preferred_hours = [] for volunteer in volunteers: preferred_hours.append(volunteer["prefHours"]) # generates a list of shift lengths corresponding to each vehicle request shift_lengths = generate_shift_lengths(vehicle_request) # generates a 2d array of booleans for the model # each entry denotes the compatability of 1 volunteer to 1 request compatible = generate_compatibility(volunteers, vehicle_request) # generates a 2d array of booleans for the model # each entry denotes whether there is a clash (true) between the corresponding vehicle requests clashing = generate_clashes(vehicle_request) # the following codeblock generates 3 lists of booleans # if is_heavy(index) = true then vehicle_request(index) is a heavy tanker # if is_medium(index) = true then vehicle_request(index) is a medium tanker # if is_light(index) = true then vehicle_request(index) is a light unit is_heavy = [] is_medium = [] is_light = [] for request in vehicle_request: if request["assetClass"] == "heavyTanker": is_heavy.append(True) is_medium.append(False) is_light.append(False) if request["assetClass"] == "mediumTanker": is_heavy.append(False) is_medium.append(True) is_light.append(False) if request["assetClass"] == "lightUnit": is_heavy.append(False) is_medium.append(False) is_light.append(True) # the following codeblock generates 4 lists of booleans # if is_driver(index) = true then volunteer(index) is a driver # if is_crew_leader(index) = true then volunteer(index) is a crewleader # if is_advanced(index) = true then volunteer(index) is advanced # if is_basic(index) = true then volunteer(index) is basic is_driver = [] is_crew_leader = [] is_advanced = [] is_basic = [] for volunteer in volunteers: basic = False advanced = False crewLeader = False driver = False for qualification in volunteer["possibleRoles"]: if qualification == "basic": basic = True if qualification == "advanced": advanced = True if qualification == "crewLeader": crewLeader = True if qualification == "driver": driver = True is_basic.append(basic) is_advanced.append(advanced) is_crew_leader.append(crewLeader) is_driver.append(driver) # we are using the gecode optimiser gecode = minizinc.Solver.lookup("gecode") # create the model model = minizinc.Model() # the following string generates the minizinc model for a full solve model.add_string(""" int: V; int: S; set of int: volunteers = 1..V; set of int: Shifts = 1..S; array[Shifts,volunteers] of bool: compatible; array[Shifts,Shifts] of bool: clashing; array[Shifts,volunteers] of var bool: assignments; array[volunteers] of int: preferredHours; array[Shifts] of int: shiftLength; array[Shifts] of bool: is_heavy; array[Shifts] of bool: is_medium; array[Shifts] of bool: is_light; array[volunteers] of bool: is_basic; array[volunteers] of bool: is_advanced; array[volunteers] of bool: is_crew_leader; array[volunteers] of bool: is_driver; array[Shifts] of var 0..V: seat1; array[Shifts] of var 0..V: seat2; array[Shifts] of var 0..V: seat3; array[Shifts] of var 0..V: seat4; array[Shifts] of var 0..V: seat5; array[volunteers,Shifts] of var int: hoursOnAssignment; array[volunteers] of var int: totalHours; %volunteer availability check constraint forall(s in Shifts)(forall(v in volunteers)(if compatible[s,v] == false then assignments[s,v] == false endif)); %volunteers cannot be assigned to 2 shifts at once constraint forall(s1 in Shifts)(forall(s2 in Shifts)(forall(v in volunteers)(if clashing[s1,s2] /\ assignments[s1,v] then assignments[s2,v] == false endif))); %all vehicles are (at most) filled. This allows for partial fills constraint forall(s in Shifts)(if is_heavy[s] then sum(v in volunteers)(assignments[s,v]) <= 5 endif); constraint forall(s in Shifts)(if is_medium[s] then sum(v in volunteers)(assignments[s,v]) <= 3 endif); constraint forall(s in Shifts)(if is_light[s] then sum(v in volunteers)(assignments[s,v]) <= 2 endif); %Seat1 Requirements constraint forall(s in Shifts)(forall(v in volunteers) (if seat1[s] == v then assignments[s,v] = true endif)); constraint forall(s in Shifts)(forall(v in volunteers)(if seat1[s] == v then is_driver[v] = true endif)); constraint forall(s in Shifts)(if is_light[s] then forall(v in volunteers)(if seat1[s] == v then is_crew_leader[v] = true endif) endif); %seat2 Requirements constraint forall(s in Shifts)(forall(v in volunteers) (if seat2[s] == v then assignments[s,v] = true endif)); constraint forall(s in Shifts)(if is_light[s] then forall(v in volunteers)(if seat2[s] == v then is_advanced[v] = true endif) endif); constraint forall(s in Shifts)(if is_medium[s] then forall(v in volunteers)(if seat2[s] == v then is_crew_leader[v] = true endif) endif); constraint forall(s in Shifts)(if is_heavy[s] then forall(v in volunteers)(if seat2[s] == v then is_crew_leader[v] = true endif) endif); %seat3 Requirements constraint forall(s in Shifts)(forall(v in volunteers) (if seat3[s] == v then assignments[s,v] = true endif)); constraint forall(s in Shifts)(if is_light[s] then seat3[s] == seat2[s] endif); constraint forall(s in Shifts)(if is_medium[s] then forall(v in volunteers)(if seat3[s] == v then is_basic[v] = true endif) endif); constraint forall(s in Shifts)(if is_heavy[s] then forall(v in volunteers)(if seat3[s] == v then is_advanced[v] = true endif) endif); %seat4 Requirements constraint forall(s in Shifts)(forall(v in volunteers) (if seat4[s] == v then assignments[s,v] = true endif)); constraint forall(s in Shifts)(if is_light[s] then seat4[s] == seat2[s] endif); constraint forall(s in Shifts)(if is_medium[s] then seat4[s] == seat3[s] endif); constraint forall(s in Shifts)(if is_heavy[s] then forall(v in volunteers)(if seat4[s] == v then is_advanced[v] = true endif) endif); %seat5 Requirements constraint forall(s in Shifts)(forall(v in volunteers) (if seat5[s] == v then assignments[s,v] = true endif)); constraint forall(s in Shifts)(if is_light[s] then seat5[s] == seat2[s] endif); constraint forall(s in Shifts)(if is_medium[s] then seat5[s] == seat3[s] endif); constraint forall(s in Shifts)(if is_heavy[s] then forall(v in volunteers)(if seat5[s] == v then is_basic[v] = true endif) endif); %if a volunteer is not on any seats of a shift, they are not on the shift constraint forall(s in Shifts)(forall(v in volunteers) (if seat5[s] != v /\ seat4[s] != v /\ seat3[s] != v /\ seat2[s] != v /\ seat1[s] != v then assignments[s,v] = false endif)); %maps shifts to hours worked constraint forall(v in volunteers)(forall(s in Shifts)(if assignments[s,v] then hoursOnAssignment[v,s] = shiftLength[s] else hoursOnAssignment[v,s] = 0 endif)); %defines total hours for each volunteer constraint forall(v in volunteers)(totalHours[v] == sum(s in Shifts)(hoursOnAssignment[v,s])); %ensures no one is overworked constraint forall(v in volunteers)(totalHours[v] <= preferredHours[v]); %maximise for number of volunteers assigned solve maximize sum(s in Shifts)(sum(v in volunteers)(assignments[s,v])) """) # initialise all the variables in the minizinc model from the variables we previously created instance = minizinc.Instance(gecode, model) instance["V"] = len(volunteers) instance["S"] = len(vehicle_request) instance["preferredHours"] = preferred_hours instance["shiftLength"] = shift_lengths instance["compatible"] = compatible instance["clashing"] = clashing instance["is_heavy"] = is_heavy instance["is_medium"] = is_medium instance["is_light"] = is_light instance["is_basic"] = is_basic instance["is_advanced"] = is_advanced instance["is_crew_leader"] = is_crew_leader instance["is_driver"] = is_driver # solve the model result = instance.solve() # if there is a valid solution, format it and output if result.solution: output = [] for i in range(len(vehicle_request)): vehicle_dict = {} vehicle_dict["shiftID"] = vehicle_request[i]["shiftID"] vehicle_dict["assetClass"] = vehicle_request[i]["assetClass"] vehicle_dict["timeframe"] = vehicle_request[i]["timeframe"] seats = [] seats.append(result["seat1"]) seats.append(result["seat2"]) seats.append(result["seat3"]) seats.append(result["seat4"]) seats.append(result["seat5"]) if vehicle_dict["assetClass"] == "lightUnit": volunteers = add_light_unit_to_output(seats, i, volunteers) if vehicle_dict["assetClass"] == "mediumTanker": volunteers = add_medium_tanker_to_output(seats, i, volunteers) if vehicle_dict["assetClass"] == "heavyTanker": volunteers = add_heavy_tanker_to_output(seats, i, volunteers) vehicle_dict["volunteers"] = volunteers output.append(vehicle_dict) # if there is no valid model, output an empty list else: print("No partial fill possible") output = [] return output
model_file = "rect_packing.mzn" import minizinc from minizinc import Model, Status square_packing_model = Model(model_file) solver = minizinc.Solver.lookup("chuffed") # number of squares we want to pack widths = [5, 6, 4, 3, 2, 4, 3, 1, 2, 1, 7, 3] heights = [1, 2, 3, 2, 1, 2, 4, 6, 5, 1, 1, 2] n = len(widths) inst = minizinc.Instance(solver, square_packing_model) inst["n"] = n inst["widths"] = widths inst["heights"] = heights inst.add_string("constraint sq_width > sq_height;") inst.add_string("constraint sq_width >= 10;") inst.add_string("constraint sq_height >= 10;") result = inst.solve() # coordinates pos_x = [] curr_x = 0 for i in range(1, n + 1): pos_x.append(curr_x) curr_x += widths[i - 1]
[1, 0, 1, 0, 0], [1, 1, 0, 0, 0]] lastT = 14 nTasks = 3 dur = [[5, 2, 3], [4, 5, 1], [3, 4, 2]] nMachines = 3 taskToMach = [[1, 2, 3], [2, 1, 3], [2, 3, 1]] # prettier output for slots datetime_object = datetime.datetime.strptime('14:00', '%H:%M') date_list = [ datetime_object + datetime.timedelta(minutes=15 * x) for x in range(0, nSlots) ] print_dates = [d.strftime('%H:%M') for d in date_list] inst = minizinc.Instance(solver, model) inst["nOptions"] = nOptions inst["nCarConfigs"] = nCarConfigs inst["nTasks"] = nTasks inst["at_most"] = at_most inst["per_slots"] = per_slots inst["demand"] = demand inst["requires"] = requires # for example, first slot should be a config 1 #inst.add_string("constraint line[1] = 3;") result = inst.solve() if result.status == Status.SATISFIED or result.status == Status.OPTIMAL_SOLUTION: print("sounds good")