-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finding diverse solution for MiniZinc instances (#87)
* Initial commit on diversity * Fix the formatting and types * Make MznAnalyse.find consistent with Driver.find * Simplify the assignment of previous solutions * Remove the requirement of numpy * Remove unused argument MznAnalyse.run * Refactor code to be in more logical places * Additional refactoring of diverse_solutions function * Change Instance.diverse_solutions to be async * Add a more programmatic interface for the mzn-analyse tool * Add solver argument for Instance.diverse_solutions * Change solution assertions in Instance.diverse_solutions to early return * Add initial diversity library file * Diversity MZN: Added description of annotations. Removed unused annotations. * Diversity MZN: more description to annotations * Diversity: Added documentation entry for diversity functionality * Move diversity.mzn file into the MiniZinc standard library * Fix typing issues --------- Co-authored-by: Jip J. Dekker <[email protected]> Co-authored-by: Kevin Leo <[email protected]>
- Loading branch information
1 parent
33f7deb
commit 0dad82c
Showing
6 changed files
with
488 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,4 +50,5 @@ | |
"Result", | ||
"Solver", | ||
"Status", | ||
"Diversity", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
import json | ||
import os | ||
import platform | ||
import shutil | ||
import subprocess | ||
from enum import Enum, auto | ||
from pathlib import Path | ||
from typing import Any, Dict, List, Optional, Union | ||
|
||
from .driver import MAC_LOCATIONS, WIN_LOCATIONS | ||
from .error import ConfigurationError, MiniZincError | ||
|
||
|
||
class InlineOption(Enum): | ||
DISABLED = auto() | ||
NON_LIBRARY = auto() | ||
ALL = auto() | ||
|
||
|
||
class MznAnalyse: | ||
"""Python interface to the mzn-analyse executable | ||
This tool is used to retrieve information about or transform a MiniZinc | ||
instance. This is used, for example, to diverse solutions to the given | ||
MiniZinc instance using the given solver configuration. | ||
""" | ||
|
||
_executable: Path | ||
|
||
def __init__(self, executable: Path): | ||
self._executable = executable | ||
if not self._executable.exists(): | ||
raise ConfigurationError( | ||
f"No MiniZinc data annotator executable was found at '{self._executable}'." | ||
) | ||
|
||
@classmethod | ||
def find( | ||
cls, path: Optional[List[str]] = None, name: str = "mzn-analyse" | ||
) -> Optional["MznAnalyse"]: | ||
"""Finds the mzn-analyse executable on default or specified path. | ||
The find method will look for the mzn-analyse executable to create an | ||
interface for MiniZinc Python. If no path is specified, then the paths | ||
given by the environment variables appended by default locations will be | ||
tried. | ||
Args: | ||
path: List of locations to search. name: Name of the executable. | ||
Returns: | ||
Optional[MznAnalyse]: Returns a MznAnalyse object when found or None. | ||
""" | ||
|
||
if path is None: | ||
path = os.environ.get("PATH", "").split(os.pathsep) | ||
# Add default MiniZinc locations to the path | ||
if platform.system() == "Darwin": | ||
path.extend(MAC_LOCATIONS) | ||
elif platform.system() == "Windows": | ||
path.extend(WIN_LOCATIONS) | ||
|
||
# Try to locate the MiniZinc executable | ||
executable = shutil.which(name, path=os.pathsep.join(path)) | ||
if executable is not None: | ||
return cls(Path(executable)) | ||
return None | ||
|
||
def run( | ||
self, | ||
mzn_files: List[Path], | ||
inline_includes: InlineOption = InlineOption.DISABLED, | ||
remove_litter: bool = False, | ||
get_diversity_anns: bool = False, | ||
get_solve_anns: bool = True, | ||
output_all: bool = True, | ||
mzn_output: Optional[Path] = None, | ||
remove_anns: Optional[List[str]] = None, | ||
remove_items: Optional[List[str]] = None, | ||
) -> Dict[str, Any]: | ||
# Do not change the order of the arguments 'inline-includes', 'remove-items:output', 'remove-litter' and 'get-diversity-anns' | ||
tool_run_cmd: List[Union[str, Path]] = [ | ||
str(self._executable), | ||
"json_out:-", | ||
] | ||
|
||
for f in mzn_files: | ||
tool_run_cmd.append(str(f)) | ||
|
||
if inline_includes == InlineOption.ALL: | ||
tool_run_cmd.append("inline-all_includes") | ||
elif inline_includes == InlineOption.NON_LIBRARY: | ||
tool_run_cmd.append("inline-includes") | ||
|
||
if remove_items is not None and len(remove_items) > 0: | ||
tool_run_cmd.append(f"remove-items:{','.join(remove_items)}") | ||
if remove_anns is not None and len(remove_anns) > 0: | ||
tool_run_cmd.append(f"remove-anns:{','.join(remove_anns)}") | ||
|
||
if remove_litter: | ||
tool_run_cmd.append("remove-litter") | ||
if get_diversity_anns: | ||
tool_run_cmd.append("get-diversity-anns") | ||
|
||
if mzn_output is not None: | ||
tool_run_cmd.append(f"out:{str(mzn_output)}") | ||
else: | ||
tool_run_cmd.append("no_out") | ||
|
||
# Extract the diversity annotations. | ||
proc = subprocess.run( | ||
tool_run_cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE | ||
) | ||
if proc.returncode != 0: | ||
raise MiniZincError(message=str(proc.stderr)) | ||
return json.loads(proc.stdout) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.