def solve(self, mzn_file, *dzn_files, data=None, include=None, timeout=None, all_solutions=False, output_mode='item', **kwargs): """Solve a MiniZinc/FlatZinc problem with Opturion CPX. Parameters ---------- mzn_file : str The path to the fzn file to solve. Returns ------- str The output of the solver in dzn format. """ log = logging.getLogger(__name__) args = [self.cmd] if all_solutions: args.append('-a') args.append(mzn_file) try: process = run(args) out = process.stdout except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out
def solns2out(soln_stream, ozn_file): """Wraps the solns2out utility, executes it on the solution stream, and then returns the output stream. Parameters ---------- soln_stream : str The solution stream returned by the solver. ozn_file : str The ozn file path produced by the mzn2fzn function. Returns ------- str Returns the output stream encoding the solution stream according to the provided ozn file. """ log = logging.getLogger(__name__) args = [config.get('solns2out', 'solns2out'), ozn_file] try: process = run(args, stdin=soln_stream) out = process.stdout except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out
def mzn2fzn(mzn_file, *dzn_files, data=None, keep_data=False, globals_dir=None, include=None, output_mode='item', no_ozn=False): """Flatten a MiniZinc model into a FlatZinc one. It executes the mzn2fzn utility from libminizinc to produce a fzn and ozn files from a mzn one. Parameters ---------- mzn_file : str The path to the minizinc problem file. *dzn_files A list of paths to dzn files to attach to the mzn2fzn execution, provided as positional arguments; by default no data file is attached. data : dict Additional data as a dictionary of variables assignments to supply to the mzn2fnz function. The dictionary is then automatically converted to dzn format by the ``pymzn.dict2dzn`` function. Notice that if the data provided is too large, a temporary dzn file will be produced. keep_data : bool Whether to write the inline data into a dzn file and keep it. Default is False. globals_dir : str The path to the directory for global included files. include : str or list One or more additional paths to search for included mzn files when running ``mzn2fzn``. output_mode : 'dzn', 'json', 'item' The desired output format. The default is 'item' which outputs a stream of strings as returned by the solns2out tool, formatted according to the output statement of the MiniZinc model. The 'dzn' and 'json' formats output a stream of strings formatted in dzn of json respectively. no_ozn : bool If True, the ozn file is not produced, False otherwise. Returns ------- tuple (str, str) The paths to the generated fzn and ozn files. If ``no_ozn=True``, the second argument is None. """ log = logging.getLogger(__name__) args = [config.get('mzn2fzn', 'mzn2fzn')] if globals_dir: args += ['-G', globals_dir] if no_ozn: args.append('--no-output-ozn') if output_mode and output_mode in ['dzn', 'json', 'item']: args += ['--output-mode', output_mode] if include: if isinstance(include, str): include = [include] elif not isinstance(include, list): raise TypeError('The path provided is not valid.') for path in include: args += ['-I', path] dzn_files = list(dzn_files) data, data_file = process_data(mzn_file, data, keep_data) if data: args += ['-D', data] elif data_file: dzn_files.append(data_file) args += [mzn_file] + dzn_files try: run(args) except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err if not keep_data: with contextlib.suppress(FileNotFoundError): if data_file: os.remove(data_file) log.debug('Deleting file: {}'.format(data_file)) mzn_base = os.path.splitext(mzn_file)[0] fzn_file = '.'.join([mzn_base, 'fzn']) fzn_file = fzn_file if os.path.isfile(fzn_file) else None ozn_file = '.'.join([mzn_base, 'ozn']) ozn_file = ozn_file if os.path.isfile(ozn_file) else None if fzn_file: log.debug('Generated file: {}'.format(fzn_file)) if ozn_file: log.debug('Generated file: {}'.format(ozn_file)) return fzn_file, ozn_file
def solve(self, mzn_file, *dzn_files, data=None, include=None, timeout=None, all_solutions=False, output_mode='item', **kwargs): """Solve a MiniZinc/FlatZinc problem with the G12 solver. Parameters ---------- mzn_file : str The path to the mzn file to solve. dzn_files A list of paths to dzn files. data : str A dzn string containing additional inline data to pass to the solver. include : str or [str] A path or a list of paths to included files. all_solutions : bool Whether to return all solutions. output_mode : 'dzn', 'json', 'item', 'dict' The output mode required. Returns ------- str The output of the solver. """ log = logging.getLogger(__name__) mzn = False args = [] if mzn_file.endswith('fzn'): if output_mode != 'dzn': raise ValueError('Only dzn output available with fzn input.') args.append(self.fzn_cmd) if self.backend: args += ['-b', self.backend] else: if output_mode != 'item': raise ValueError('Only item output available with mzn input.') mzn = True args += [self.mzn_cmd, '-G', self.globals_dir] if include: if isinstance(include, str): include = [include] for path in include: args += ['-I', path] if data: args += ['-D', data] if all_solutions: args.append('-a') args.append(mzn_file) if mzn and dzn_files: for dzn_file in dzn_files: args.append(dzn_file) try: process = run(args) out = process.stdout except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out
def solve(self, mzn_file, *dzn_files, data=None, include=None, timeout=None, all_solutions=False, output_mode='item', parallel=1, **kwargs): """Solve a MiniZinc/FlatZinc problem with a MIP Solver. Parameters ---------- mzn_file : str The path to the mzn file to solve. dzn_files A list of paths to dzn files. data : str A dzn string containing additional inline data to pass to the solver. include : str or [str] A path or a list of paths to included files. timeout : int The timeout for the solver. If None, no timeout given. all_solutions : bool Whether to return all solutions. output_mode : 'dzn', 'json', 'item', 'dict' The output mode required. parallel : int The number of threads to use to solve the problem; default is 1. Returns ------- str The output of the solver. """ log = logging.getLogger(__name__) mzn = False args = [self.cmd] if mzn_file.endswith('fzn') and output_mode not in ['dzn', 'json']: raise ValueError( 'Only dzn or json output available with fzn input.') else: mzn = True args += ['-G', self.globals_dir] if include: if isinstance(include, str): include = [include] for path in include: args += ['-I', path] if data: args += ['-D', data] if all_solutions: args += ['-a', '--unique'] if parallel != 1: args += ['-p', str(parallel)] if timeout and timeout > 0: args += ['--timeout', str(timeout)] args += ['--output-mode', output_mode, mzn_file] if mzn and dzn_files: for dzn_file in dzn_files: args.append(dzn_file) try: process = run(args) out = process.stdout except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out
def solve(self, mzn_file, *dzn_files, data=None, include=None, timeout=None, all_solutions=False, output_mode='item', seed=0, **kwargs): """Solve a MiniZinc/FlatZinc problem with Chuffed. Parameters ---------- mzn_file : str The path to the mzn file to solve. dzn_files A list of paths to dzn files. data : str A dzn string containing additional inline data to pass to the solver. include : str or [str] A path or a list of paths to included files. timeout : int The timeout for the solver. If None, no timeout given. all_solutions : bool Whether to return all solutions. output_mode : 'dzn', 'json', 'item', 'dict' The output mode required. seed : int Random seed. Returns ------- str The output of the solver. """ log = logging.getLogger(__name__) mzn = False args = [] if mzn_file.endswith('fzn'): if output_mode != 'dzn': raise ValueError('Only dzn output available with fzn input.') args.append(self.fzn_cmd) else: if output_mode != 'item': raise ValueError('Only item output available with mzn input.') mzn = True args += [self.mzn_cmd, '-G', self.globals_dir] if include: if isinstance(include, str): include = [include] for path in include: args += ['-I', path] if data: args += ['-D', data] fzn_flags = [] if all_solutions: args.append('-a') if timeout and timeout > 0: fzn_flags += ['--time-out', str(timeout)] if seed != 0: fzn_flags += ['--rnd-seed', str(seed)] if mzn and fzn_flags: args += ['--fzn-flags', '"{}"'.format(' '.join(fzn_flags))] else: args += fzn_flags args.append(mzn_file) if mzn and dzn_files: for dzn_file in dzn_files: args.append(dzn_file) try: process = run(args) out = process.stdout if process.stderr: raise RuntimeError(process.stderr) except CalledProcessError as err: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out
def solve(self, mzn_file, *dzn_files, data=None, include=None, timeout=None, all_solutions=False, output_mode='item', parallel=1, seed=0, suppress_segfault=False, **kwargs): """Solve a MiniZinc/FlatZinc problem with Gecode. Parameters ---------- mzn_file : str The path to the mzn file to solve. dzn_files A list of paths to dzn files. data : str A dzn string containing additional inline data to pass to the solver. include : str or [str] A path or a list of paths to included files. timeout : int The timeout for the solver. If None, no timeout given. all_solutions : bool Whether to return all solutions. output_mode : 'dzn', 'json', 'item', 'dict' The output mode required. parallel : int The number of threads to use to solve the problem (0 = #processing units); default is 1. seed : int Random seed. suppress_segfault : bool Whether to accept or not a solution returned when a segmentation fault has happened (this is unfortunately necessary sometimes due to some bugs in Gecode). Returns ------- str The output of the solver. """ log = logging.getLogger(__name__) mzn = False args = [] if mzn_file.endswith('fzn'): if output_mode != 'dzn': raise ValueError('Only dzn output available with fzn input.') args.append(self.fzn_cmd) else: if output_mode != 'item': raise ValueError('Only item output available with mzn input.') mzn = True args += [self.mzn_cmd, '-G', self.globals_dir] if include: if isinstance(include, str): include = [include] for path in include: args += ['-I', path] if data: args += ['-D', data] fzn_flags = [] if all_solutions: args.append('-a') if parallel != 1: fzn_flags += ['-p', str(parallel)] if timeout and timeout > 0: timeout = timeout * 1000 # Gecode takes milliseconds fzn_flags += ['-time', str(timeout)] if seed != 0: fzn_flags += ['-r', str(seed)] if mzn and fzn_flags: args += ['--fzn-flags', '{}'.format(' '.join(fzn_flags))] else: args += fzn_flags args.append(mzn_file) if mzn and dzn_files: for dzn_file in dzn_files: args.append(dzn_file) try: process = run(args) out = process.stdout except CalledProcessError as err: if suppress_segfault and len(err.stdout) > 0 \ and err.stderr.startswith('Segmentation fault'): log.warning('Gecode returned error code {} (segmentation ' 'fault) but a solution was found and returned ' '(suppress_segfault=True).'.format(err.returncode)) out = err.stdout else: log.exception(err.stderr) raise RuntimeError(err.stderr) from err return out