예제 #1
0
    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
예제 #2
0
파일: minizinc.py 프로젝트: raverkamp/pymzn
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
예제 #3
0
파일: minizinc.py 프로젝트: raverkamp/pymzn
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
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
    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