1
0

Squashed 'software/minizinc/' changes from 4f10c82056..93be33a6c2

93be33a6c2 Add complete predicate
REVERT: 4f10c82056 Merge branch 'MiniZinc:master' into feature/on_restart
REVERT: 0848ce7ec7 Add changelog for 2.5.5
REVERT: 44e2f770d5 Add test for insertion of ArrayLits into CSE
REVERT: 8a68d3dea8 Don't insert par expressions into CSE map unless they're an ArrayLit
REVERT: 6bf6f1180f Increase version number of development build
REVERT: dcaac92a74 Make min/max on array of opt vars return non-optional var. This is consistent with other functions on optional arrays like sum, product, exists, forall.
REVERT: 32aa288884 Update changelog
REVERT: a4edf0669f Fix flattening of all-par set literals
REVERT: 8c1c9605f6 Fix chain compressor, needs to ignore par constants
REVERT: 0cad1c6306 Use file_path on include paths to ensure separator consistency
REVERT: 05ad7d1931 Update changelog
REVERT: 22f5e2557b Define HAVE_CONFIG_H only for UNIX
REVERT: 81c7778d55 Define HAVE_CONFIG_H for CBC
REVERT: 1f56608e10 mzn-test: don't check symmetry breaking constraints
REVERT: 1a9767457e mzn-test: fix parsing %%%mzn-stat: ... output
REVERT: a41533fd54 MIP: report CPU time in %%%mzn-stat: solveTime=
REVERT: 9d490acd52 Updated docs on OR-Tools v8 installation
REVERT: c513f6599f Add changelog for 2.5.4
REVERT: b2eef2772b Follow ids to declarations when flattening par arrays. Fixes #448.
REVERT: c5c846d426 Check if result of flattening rhs of a vardecl is par.
REVERT: c496052767 Escape strings when pretty printing include items
REVERT: 9e379c995e Canonicalise file names before adding include items into "already seen" list
REVERT: d5d5d0d88c Use generic flattening inside generators. Fixes #451.
REVERT: dc8630a6e9 Small fix to multi-pass library change: use original include path if it is absolute
REVERT: 79c6092bd8 Strip library paths from includes in multi-pass compilation. Fixes #455.
REVERT: 897875d6d7 Compile infinite domains with holes into constraints. Fixes #457.
REVERT: b4e700dc67 Don't create copies of global declarations when creating par versions of functions
REVERT: 0e8cc42bb1 Fix typechecker to coerce bool to int in the objective.
REVERT: e05523b344 Add test for dzn output of arrays
REVERT: 1e0269000e Don't evaluate output_only arrays when generating dzn output.
REVERT: 57018c31d6 Fix matrix transposition in lex2 globals
REVERT: 2617c0c829 Fix output variables in lex_chain tests
REVERT: ef1a250c98 another efort to fix tests
REVERT: c00e199dfd Fix test globals_lex_chain.mzn
REVERT: b5c997d045 Fix code analysis
REVERT: 3352cf0bd5 SCIP constraint handler for lex_chain_..._orbitope
REVERT: 4e71a2cc97 Globals lex_chain_..., including lex_chain_..._orbitope
REVERT: d807428baf Move test specifcation into the correct folder
REVERT: 5be74bc74d MIP decompositions for lex_less_(bool, int, float)
REVERT: 36a554ba40 Don't modify infinte domain of optional variables. Fixes #456.
REVERT: f9e5306d75 Run clang-format
REVERT: 4b57667608 Fix comment reference to relevant test case
REVERT: 648f2ab36d Fix equality of indirection annotations
REVERT: ef7be5fd78 MIP decompositions for lex_lesseq_(bool=int, float)
REVERT: 6511b14e73 Propagate cv flag correctly.
REVERT: 6f27ecf1c0 Never insert par expressions into the CSE map.
REVERT: 7414f3ca0f Fix cplex id in example configuration
REVERT: 7ad7cec506 Update strictly_decreasing with documentation and opt version
REVERT: 8029f6e957 Support undefined enums in type checker.
REVERT: 79e0f0f546 Revert using mzn_in_symmetry_breaking_constraint() for SCIP's orbisack
REVERT: e88efda76c Fix format
REVERT: 4802031dc1 Added test mzn_in_symmetry_breaking_constraint()
REVERT: e21cc2515a More format fixes 02 ...
REVERT: 5bbd67c130 More format fixes...
REVERT: d5f9b777ea Format fixes
REVERT: 43757a09a0 Remove MIP-specific fzn_less(eq)_bool(_reif).mzn
REVERT: c93b5736a3 SCIP: orbisack constraint handler 'fzn_lex_lesseq__orbisack'
REVERT: 4516bb4e2c mzn-test.py: add OR-Tools as checker
REVERT: e2176f017d Add fix and test for crash with empty enum.
REVERT: ac7db35951 Fix documentation bugs.
REVERT: 47ba245832 Fix the incorrect renaming of key in model output interface
REVERT: 925796ed20 Fail on empty var domains in agenda
REVERT: 1ec19d7025 Fix error messages in CMake FindGurobi, FindCPlex
REVERT: 6d169475c1 mzn-test.py: Use -i for intermediate solutions
REVERT: df2f3e423a Allow coercion of JSON lists to enum definitions
REVERT: 2b0b8165e5 Fix clang-tidy errors
REVERT: 6597bc1920 Change the CI build image location
REVERT: 360c988452 Remove illegal duplicate keys in .gitlab-ci.yml
REVERT: 6a5d69c64b Add missing par opt versions of coercion functions
REVERT: 63014e3d8f Don't propagate annotations into annotation calls. Avoids infinite recursion.
REVERT: 54b19428ab Don't use GRB_INT_PAR_NONCONVEX if it's undefined
REVERT: a5bb56c47d Added piecewise_linear for non-continuous intervals

git-subtree-dir: software/minizinc
git-subtree-split: 93be33a6c254e54be7cd38abb7ebd6a6022f0c46
This commit is contained in:
Jip J. Dekker 2021-07-12 20:08:41 +10:00
parent fad1b07018
commit 2c8ad0004a
123 changed files with 1217 additions and 2475 deletions

View File

@ -8,7 +8,7 @@ stages:
- sh download.sh vendor master vendor:${MZNARCH} vendor.zip
- unzip -q vendor.zip
.download_vendor_win: &download_vendor_win
.download_vendor: &download_vendor_win
- curl -o download.sh --location --header "PRIVATE-TOKEN:%ACCESS_TOKEN%" --silent https://gitlab.com/api/v4/snippets/1796163/raw
- dos2unix download.sh
- sh download.sh vendor master vendor:%MZNARCH% vendor.zip
@ -19,7 +19,7 @@ stages:
- sh download.sh vendor master bundle:${MZNARCH} vendor.zip
- unzip -q vendor.zip
.download_bundle_win: &download_bundle_win
.download_bundle: &download_bundle_win
- curl -o download.sh --location --header "PRIVATE-TOKEN:%ACCESS_TOKEN%" --silent https://gitlab.com/api/v4/snippets/1796163/raw
- dos2unix download.sh
- sh download.sh vendor master bundle:%MZNARCH% vendor.zip
@ -51,7 +51,7 @@ default:
build:linux:
extends: .build
image: minizinc/build-environment:cpp
image: dekker1/minibuild:cpp
variables:
MZNARCH: "linux"
CMAKE_ARCH: "Ninja"
@ -59,7 +59,7 @@ build:linux:
build:musl:
extends: .build
image: minizinc/build-environment:alpine
image: dekker1/minibuild:alpine
variables:
MZNARCH: "musl"
CMAKE_ARCH: "Ninja"
@ -118,7 +118,7 @@ build:wasm_minimal:
test:format:
stage: test
image: minizinc/build-environment:clang-format
image: dekker1/minibuild:clang-format
script:
- cmake -S . -B build -GNinja -DCLANG_FORMAT_EXECUTABLE="run-clang-format" -DCLANG_FORMAT_FLAGS="--color always"
- cmake --build build --target format
@ -134,7 +134,7 @@ test:format:
test:analyse:
extends: .build
stage: test
image: minizinc/build-environment:clang-tidy
image: dekker1/minibuild:clang-tidy
variables:
MZNARCH: "linux"
CMAKE_ARCH: "Ninja"
@ -158,7 +158,7 @@ test:analyse:
before_script:
- *download_bundle
# TODO: Add gecode configuration to the Gecode solver
- 'echo ''{"id":"org.gecode.gecode","name":"Gecode","description":"Gecode FlatZinc executable","version":"6.1.1","mznlib":"share/gecode/mznlib","executable":"bin/fzn-gecode","tags":["cp","int","float","set","restart"],"stdFlags":["-a","-f","-n","-p","-r","-s","-t"],"extraFlags":[["-c-d","Recomputation commit distance","int","8"],["-a-d","Recomputation adaption distance","int","2"],["-decay","Decay factor","float","0.99"],["-node","Node cutoff","int","0"],["-fail","Failure cutoff","int","0"],["-restart","Restart sequence type","opt:none:constant:linear:luby:geometric","none"],["-restart-base","Base for geometric restart sequence","float","1.5"],["-restart-scale","Scale factor for restart sequence","int","250"],["-nogoods","Use no-goods from restarts","bool","false"],["-nogoods-limit","Depth limit for no-good extraction","int","128"]],"supportsMzn":false,"supportsFzn":true,"needsSolns2Out":true,"needsMznExecutable":false,"needsStdlibDir":false,"isGUIApplication":false}'' > vendor/gecode/gecode.msc'
- "echo '{\"id\":\"org.gecode.gecode\",\"name\":\"Gecode\",\"description\":\"Gecode FlatZinc executable\",\"version\":\"6.1.1\",\"mznlib\":\"share/gecode/mznlib\",\"executable\":\"bin/fzn-gecode\",\"tags\":[\"cp\",\"int\",\"float\",\"set\",\"restart\"],\"stdFlags\":[\"-a\",\"-f\",\"-n\",\"-p\",\"-r\",\"-s\",\"-t\"],\"extraFlags\":[[\"-c-d\",\"Recomputation commit distance\",\"int\",\"8\"],[\"-a-d\",\"Recomputation adaption distance\",\"int\",\"2\"],[\"-decay\",\"Decay factor\",\"float\",\"0.99\"],[\"-node\",\"Node cutoff\",\"int\",\"0\"],[\"-fail\",\"Failure cutoff\",\"int\",\"0\"],[\"-restart\",\"Restart sequence type\",\"opt:none:constant:linear:luby:geometric\",\"none\"],[\"-restart-base\",\"Base for geometric restart sequence\",\"float\",\"1.5\"],[\"-restart-scale\",\"Scale factor for restart sequence\",\"int\",\"250\"],[\"-nogoods\",\"Use no-goods from restarts\",\"bool\",\"false\"],[\"-nogoods-limit\",\"Depth limit for no-good extraction\",\"int\",\"128\"]],\"supportsMzn\":false,\"supportsFzn\":true,\"needsSolns2Out\":true,\"needsMznExecutable\":false,\"needsStdlibDir\":false,\"isGUIApplication\":false}' > vendor/gecode/gecode.msc"
- export PATH=$CI_PROJECT_DIR/minizinc/bin:$PATH
- minizinc --solvers
- cd tests
@ -170,7 +170,7 @@ test:analyse:
artifacts:
when: always
paths:
- tests/output
- tests/output
reports:
junit: tests/output/junit*.xml
cache:
@ -213,7 +213,7 @@ test:analyse:
- call env\Scripts\activate.bat
- pip install -r requirements.txt
after_script:
- "echo Test results at https://minizinc.gitlab.io/-/minizinc/-/jobs/%CI_JOB_ID%/artifacts/tests/output/report.html"
- 'echo Test results at https://minizinc.gitlab.io/-/minizinc/-/jobs/%CI_JOB_ID%/artifacts/tests/output/report.html'
tags: [win64]
dependencies: ["build:win64"]
needs: ["build:win64"]

View File

@ -5,7 +5,7 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment ver
# -- Project information and versioning.
project(libminizinc
VERSION 2.5.5
VERSION 2.5.4
LANGUAGES CXX C)
if(NOT BUILD_REF)

View File

@ -4,110 +4,6 @@ MiniZinc Change Log
For detailed bug reports consult the issue tracker at
https://github.com/MiniZinc/libminizinc/issues.
.. _v2.5.5:
`Version 2.5.5 <https://github.com/MiniZinc/MiniZincIDE/releases/tag/2.5.5>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(released 19 March 2021)
Changes:
^^^^^^^^
- Make min/max on an array of optional variables return a non-optional var,
behaving as if absent values are not in the array.
Bug fixes:
^^^^^^^^^^
- Insert par array literals in the common subexpression elimination map, fixing
a FlatZinc code bloat issue (:bugref:`458`).
Changes in the IDE:
^^^^^^^^^^^^^^^^^^^
- Fix editing of custom string parameters so they don't get converted to
floats.
- Fix crash on Windows caused when the ``PATH`` environment contains unicode
characters.
.. _v2.5.4:
`Version 2.5.4 <https://github.com/MiniZinc/MiniZincIDE/releases/tag/2.5.4>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(released 16 March 2021)
Changes:
^^^^^^^^
- Allow empty arrays in global cardinality constraints (:bugref:`440`).
- Add piecewise_linear for non-continuous intervals.
- Fail on empty variable domains in agenda.
- Allow coercion of JSON lists to enum definitions (:bugref:`441`).
- Update strictly_decreasing with documentation and opt version (:bugref:`454`).
- Remove MIP-specific ``fzn_less(eq)_bool(_reif).mzn``.
- Add ``mzn_in_symmetry_breaking_constraint()`` for internal use.
- Add MIP decompositions for ``lex_less[eq]_*``.
- Add ``lex_chain_*`` globals, and use them in ``lex2[_strict]``.
- Improve detection of variable declarations which are actually par to allow
more use of overloaded par versions of predicates.
- Update documentation on installation of OR-Tools.
- Report CPU time in ``solveTime`` statistic for MIP solvers.
Bug fixes:
^^^^^^^^^^
- Fix handling of bad Xpress licenses when collecting extra flags.
- Don't propagate annotations into annotation calls to infinite recursion.
- Add missing par opt versions of coercion functions.
- Revert incorrect renaming of ``has_output_item`` to ``has_outputItem`` in
model interface output.
- Fix incorrect grammar specification in documentation (:bugref:`453`).
- Fix crash when defining enums with no members (:bugref:`443`, :bugref:`444`).
- Support undefined enums in the type checker.
- Fix CPLEX solver ID in documentation.
- Never insert par expressions in the common subexpression elimination map.
- Fix cv flag propagation when the body of a let or function is cv.
- Fix equality test for annotations involving indirection.
- Don't modify the infinite domain of optional variables (:bugref:`456`).
- Don't immediately evaluate output_only arrays when generating dzn output.
- Coerce boolean objectives to integers.
- Don't create copies of global declarations when creating par versions of
functions.
- Compile infinite domains with holes into constraints (:bugref:`457`).
- Use generic flattening inside generators, disallowing free boolean variables
inside ``in`` expressions (:bugref:`451`).
- Strip library paths from includes in multi-pass compilation (:bugref:`455`).
- Canonicalise file names of includes to ensure the same file is not included
multiple times.
- Escape paths in printed ``include`` items, fixing backslash problems on
Windows.
- Follow ids to declarations when flattening par arrays (:bugref:`448`).
- Ignore par constants during chain compression.
- Fix flattening of all-par set literals.
Changes in the IDE:
^^^^^^^^^^^^^^^^^^^
- Fix possible crash due to incorrect use of WriteFile on Windows.
- Ensure Gecode Gist dependencies are present in the Linux bundle and AppImage
(:idebugref:`132`).
- Fix crash when stopping solver during exit.
- Don't show irrelevant context menu entries in the project explorer.
- Add support for HTTP/S links in the output pane.
- Fix crash when saving CP Profiler executions where there is no info
associated with a node.
- Show a warning when there are open files which are not part of a MOOC
submission.
- Fix double spinbox precision issues (:idebugref:`134`).
- Include Gecode Gist and CP Profiler dependencies in Snap package.
- Allow opening of multiple files through the open file menu option.
- Ensure file dialogs save last path when opening files.
- Make the escape key close the find/replace dialog when focussed on any child
widget.
- Allow setting MOOC submission items as mandatory.
.. _v2.5.3:
`Version 2.5.3 <https://github.com/MiniZinc/MiniZincIDE/releases/tag/2.5.3>`__

View File

@ -61,7 +61,7 @@ find_package_handle_standard_args(CPlex
FOUND_VAR CPLEX_FOUND
REQUIRED_VARS CPLEX_INCLUDE CPLEX_LIBRARY
VERSION_VAR CPLEX_VERSION
FAIL_MESSAGE "Could NOT find CPlex, use CPlex_ROOT to hint its location"
FAIL_MESSAGE "Could NOT find CPlex, use CPLEX_ROOT to hint its location"
)
if(CPLEX_PLUGIN AND HAS_WINDOWS_H AND NOT HAS_DLFCN_H)

View File

@ -69,7 +69,7 @@ find_package_handle_standard_args(Gurobi
FOUND_VAR GUROBI_FOUND
REQUIRED_VARS GUROBI_INCLUDE GUROBI_LIBRARY
VERSION_VAR GUROBI_VERSION
FAIL_MESSAGE "Could NOT find Gurobi, use Gurobi_ROOT to hint its location"
FAIL_MESSAGE "Could NOT find Gurobi, use GUROBI_ROOT to hint its location"
)
if(GUROBI_PLUGIN AND HAS_WINDOWS_H AND NOT HAS_DLFCN_H)

View File

@ -13,9 +13,6 @@ if(OSICBC_FOUND)
)
target_include_directories(minizinc_osicbc PRIVATE ${OSICBC_INCLUDE_DIRS})
add_dependencies(minizinc_osicbc minizinc_mip)
if (UNIX AND NOT WIN32)
target_compile_definitions(minizinc_osicbc PRIVATE HAVE_CONFIG_H)
endif()
### Setup correct compilation into the MiniZinc library
target_compile_definitions(mzn PRIVATE HAS_OSICBC)

View File

@ -73,7 +73,7 @@ author = 'Peter J. Stuckey, Kim Marriott, Guido Tack'
# The short X.Y version.
version = '2.5'
# The full version, including alpha/beta/rc tags.
release = '2.5.5'
release = '2.5.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -511,8 +511,8 @@ Here is a sample configuration file:
{
"mzn_solver_path": ["/usr/share/choco"],
"tagDefaults": [["cp","org.choco-solver.choco"],["mip","org.minizinc.mip.cplex"],["","org.gecode.gecode"]],
"solverDefaults": [["org.minizinc.mip.cplex","--cplex-dll","/opt/CPLEX_Studio128/cplex/bin/x86-64_sles10_4.1/libcplex128.so"]]
"tagDefaults": [["cp","org.choco-solver.choco"],["mip","org.minizinc.cplex"],["","org.gecode.gecode"]],
"solverDefaults": [["org.minizinc.cplex","--cplex-dll","/opt/CPLEX_Studio128/cplex/bin/x86-64_sles10_4.1/libcplex128.so"]]
}
Configuration values in the user-specific configuration file override the global values, except for solver default arguments, which are only overridden if the name of the option is the same, and otherwise get added to the command line.

View File

@ -73,7 +73,7 @@ author = 'Peter J. Stuckey, Kim Marriott, Guido Tack'
# The short X.Y version.
version = '2.5'
# The full version, including alpha/beta/rc tags.
release = '2.5.5'
release = '2.5.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -35,7 +35,7 @@
<assign-item> ::= <ident> "=" <expr>
% Constraint items
<constraint-item> ::= "constraint" [ <string-annotation> ] <expr>
<constraint-item> ::= "constraint" <string-annotation> <expr>
% Solve item
<solve-item> ::= "solve" <annotations> "satisfy"
@ -80,7 +80,7 @@
| <base-type>
| <ti-variable-expr-tail>
| "ann"
| "{" <expr> "," ... "}"
| { <expr> "," ... }
| <num-expr> ".." <num-expr>
% Type-inst variables

View File

@ -86,16 +86,14 @@ OR Tools
You can install the OR-Tools FlatZinc module as binary or obtain the source code from GitHub (https://github.com/google/or-tools).
You can find detailed compilation instructions for OR-Tools on https://developers.google.com/optimization/.
Since version 8, `cmake` is supported, see the instructions. Previously, to compile the FlatZinc module from source,
run the following in a terminal (from within the OR-Tools source code directory):
To compile the FlatZinc module from source, run the following in a terminal (from within the OR-Tools source code directory):
.. code-block:: bash
make fz -j8
make test_fz
Since version 8, `cmake --build . --target install` puts a solver configuration file in `/usr/share/minizinc`, so the MiniZinc finds
OR-Tools automatically. With earlier versions, in order to use OR-Tools with MiniZinc, you have to create an appropriate solver configuration file.
In order to use OR-Tools with MiniZinc, you have to create an appropriate solver configuration file.
Add a file ``ortools.msc`` in an appropriate location (see :ref:`sec-cmdline-conffiles`) containing the following,
where you replace ``<INSTALLATION_PREFIX>`` with the actual installation path and update the version number if necessary:

View File

@ -143,11 +143,7 @@ The following parameters can be given on the command line or modified in ``share
-DfIndConstr=true -DfMIPdomains=false %% Use solver's indicator constraints, see below
-DMinMaxGeneral=true %% Send min/max constraints to the solver (Gurobi only)
-DQuadrFloat=false -DQuadrInt=false %% Not forward float/integer multiplications for MIQCP backends, see below
-DUseCumulative=false %% Not forward cumulative with fixed durations/resources (SCIP only)
-DUseOrbisack=false %% Not forward lex_lesseq for binary/bool vectors (SCIP only)
-DOrbisackAlwaysModelConstraint=true %% lex_lesseq ignores being in symmetry_breaking_constraint() (SCIP only)
%% Required for SCIP 7.0.2, or use patch: http://listserv.zib.de/pipermail/scip/2021-February/004213.html
-DUseOrbitope=false %% Not forward lex_chain_lesseq for binary/bool matrices (SCIP only)
-DCumulative=false %% Not forward cumulative with fixed durations/resources (SCIP only)
--no-half-reifications %% Turn off halfreification (full reification was until v2.2.3)
Some Solver Options and Changed Default Values

View File

@ -22,23 +22,23 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#define MZN_MIPD_assert_soft(c, e) \
#define MZN_MIPD__assert_soft(c, e) \
do { \
static int nn = 0; \
if (!(c)) \
if (++nn <= 1) std::cerr << e << std::endl; /* NOLINT(bugprone-macro-parentheses) */ \
} while (0)
#define MZN_MIPD_assert_hard(c) MZN_ASSERT_HARD(c)
#define MZN_MIPD_assert_hard_msg(c, e) MZN_ASSERT_HARD_MSG(c, e)
#define MZN_MIPD_FLATTENING_ERROR_IF_NOT(cond, envi, loc, msg) \
do { \
if (!(cond)) { \
std::ostringstream oss; \
oss << msg; /* NOLINT(bugprone-macro-parentheses) */ \
throw FlatteningError(envi, loc, oss.str()); \
} \
#define MZN_MIPD__assert_hard(c) MZN_ASSERT_HARD(c)
#define MZN_MIPD__assert_hard_msg(c, e) MZN_ASSERT_HARD_MSG(c, e)
#define MZN_MIPD__FLATTENING_ERROR__IF_NOT(cond, envi, loc, msg) \
do { \
if (!(cond)) { \
std::ostringstream oss; \
oss << msg; /* NOLINT(bugprone-macro-parentheses) */ \
throw FlatteningError(envi, loc, oss.str()); \
} \
} while (0)
#define MZN_MIPD_ASSERT_FOR_SAT(cond, envi, loc, msg) \
#define MZN_MIPD__ASSERT_FOR_SAT(cond, envi, loc, msg) \
do { \
if (!(cond)) { \
std::ostringstream oss; \

View File

@ -1838,8 +1838,6 @@ public:
ASTString set_card; // NOLINT(readability-identifier-naming)
ASTString pow;
ASTString mzn_set_in_internal; // NOLINT(readability-identifier-naming)
ASTString introduced_var; // NOLINT(readability-identifier-naming)
ASTString anonEnumFromStrings;
} ids;

View File

@ -87,8 +87,6 @@ class EvalBase {
public:
/// Evaluate bool expression that may contain variables
static bool evalBoolCV(EnvI& env, Expression* e);
/// Flatten expression that may contain variables
static KeepAlive flattenCV(EnvI& env, Expression* e);
};
template <class Eval>
@ -124,7 +122,7 @@ void eval_comp_set(EnvI& env, Eval& eval, Comprehension* e, int gen, int id, Int
KeepAlive nextin;
Expression* gen_in = e->in(gen + 1);
if (gen_in->type().isvar() || gen_in->type().cv()) {
gen_in = eval.flattenCV(env, e->in(gen + 1))();
gen_in = eval.flatten(env, e->in(gen + 1));
}
if (gen_in->type().dim() == 0) {
GCLock lock;
@ -156,12 +154,8 @@ void eval_comp_array(EnvI& env, Eval& eval, Comprehension* e, int gen, int id, I
CallStackItem csi(env, e->decl(gen, id)->id(), i);
if (in() == nullptr) {
// this is an assignment generator
Expression* asn;
if (e->where(gen)->type().isvar() || e->where(gen)->type().cv()) {
asn = eval.flattenCV(env, e->where(gen))();
} else {
asn = eval_par(env, e->where(gen));
}
Expression* asn = e->where(gen)->type().isPar() ? eval_par(env, e->where(gen))
: eval.flatten(env, e->where(gen));
e->decl(gen, id)->e(asn);
e->rehash();
} else {
@ -184,7 +178,7 @@ void eval_comp_array(EnvI& env, Eval& eval, Comprehension* e, int gen, int id, I
KeepAlive nextin;
Expression* gen_in = e->in(gen + 1);
if (gen_in->type().isvar() || gen_in->type().cv()) {
gen_in = eval.flattenCV(env, e->in(gen + 1))();
gen_in = eval.flatten(env, e->in(gen + 1));
}
if (gen_in->type().dim() == 0) {
GCLock lock;
@ -269,8 +263,8 @@ std::vector<typename Eval::ArrayVal> eval_comp(EnvI& env, Eval& eval, Comprehens
in = new SetLit(Location(), eval_intset(env, e->in(0)));
}
} else {
if (e->in(0)->type().isvar() || e->in(0)->type().cv()) {
in = eval_array_lit(env, eval.flattenCV(env, e->in(0))());
if (e->in(0)->type().isvar()) {
in = eval_array_lit(env, eval.flatten(env, e->in(0)));
} else {
in = eval_array_lit(env, e->in(0));
}

View File

@ -109,7 +109,6 @@ public:
std::vector<int> modifiedVarDecls;
std::unordered_set<std::string> deprecationWarnings;
int inRedundantConstraint;
int inSymmetryBreakingConstraint;
int inMaybePartial;
struct {
int reifConstraints;

View File

@ -36,7 +36,7 @@ void finalise_output(EnvI& e);
/// Remove all links to variables in flat model from output model in \a env
void cleanup_output(EnvI& env);
ArrayLit* create_json_output(EnvI& env, bool outputObjective, bool includeOutputItem,
bool hasChecker);
ArrayLit* create__json_output(EnvI& env, bool outputObjective, bool includeOutputItem,
bool hasChecker);
} // namespace MiniZinc

View File

@ -9,7 +9,8 @@
* 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/. */
#pragma once
#ifndef __MINIZINC_PARAM_CONFIG_HH__
#define __MINIZINC_PARAM_CONFIG_HH__
#include <minizinc/ast.hh>
#include <minizinc/solver_config.hh>
@ -56,3 +57,5 @@ public:
const char* what() const throw() override { return "MiniZinc: solver parameter error"; }
};
} // namespace MiniZinc
#endif

View File

@ -75,9 +75,9 @@ struct ParseWorkItem {
class ParserState {
public:
ParserState(const std::string& f, const std::string& b, std::ostream& err0,
const std::vector<std::string>& includePaths0, std::vector<ParseWorkItem>& files0,
std::map<std::string, Model*>& seenModels0, MiniZinc::Model* model0, bool isDatafile0,
bool isFlatZinc0, bool isSTDLib0, bool parseDocComments0)
std::vector<ParseWorkItem>& files0, std::map<std::string, Model*>& seenModels0,
MiniZinc::Model* model0, bool isDatafile0, bool isFlatZinc0, bool isSTDLib0,
bool parseDocComments0)
: filename(f.c_str()),
buf(b.c_str()),
pos(0),
@ -85,7 +85,6 @@ public:
lineStartPos(0),
nTokenNextStart(1),
hadNewline(false),
includePaths(includePaths0),
files(files0),
seenModels(seenModels0),
model(model0),
@ -106,7 +105,6 @@ public:
int nTokenNextStart;
bool hadNewline;
const std::vector<std::string>& includePaths;
std::vector<ParseWorkItem>& files;
std::map<std::string, Model*>& seenModels;
MiniZinc::Model* model;
@ -150,8 +148,6 @@ public:
pos += num;
return num;
}
std::string canonicalFilename(const std::string& f) const;
};
Model* parse(Env& env, const std::vector<std::string>& filename,

View File

@ -13,6 +13,7 @@
#include <minizinc/solver.hh>
const auto SolverInstance__ERROR = MiniZinc::SolverInstance::ERROR; // before windows.h
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>

View File

@ -76,7 +76,7 @@ public:
const char* const searchCompleteMsgDef = "==========";
/// Output values
std::string solutionSeparator = solutionSeparatorDef;
std::string solutionComma;
std::string solutionComma = "";
std::string unsatisfiableMsg = unsatisfiableMsgDef;
std::string unboundedMsg = unboundedMsgDef;
std::string unsatorunbndMsg = unsatorunbndMsgDef;

View File

@ -33,6 +33,6 @@ public:
enum StatusReason { SR_OK = -5, SR_TIME, SR_MEMORY, SR_LIMIT, SR_ERROR };
};
const SolverInstance::Status SolverInstanceError = SolverInstance::ERROR; // just in case...
const SolverInstance::Status SolverInstance__ERROR = SolverInstance::ERROR; // just in case...
} // namespace MiniZinc

View File

@ -21,7 +21,6 @@
#include <scip/scipdefplugins.h>
#ifndef _WIN32
// NOLINTNEXTLINE(bugprone-reserved-identifier)
#define __stdcall
#endif
@ -106,25 +105,6 @@ public:
SCIP_RETCODE(__stdcall* SCIPcreateConsBasicCumulative)
(SCIP* scip, SCIP_CONS** cons, const char* name, int nvars, SCIP_VAR** vars, int* durations,
int* demands, int capacity);
// NOLINTNEXTLINE(readability-identifier-naming)
SCIP_RETCODE(__stdcall* SCIPcreateConsBasicOrbisack)
(SCIP* scip, SCIP_CONS** cons, const char* name, SCIP_VAR** vars1, SCIP_VAR** vars2, int nrows,
SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons);
// NOLINTNEXTLINE(readability-identifier-naming)
SCIP_RETCODE(__stdcall* SCIPcreateConsBasicOrbitope)
(SCIP* scip, /**< SCIP data structure */
SCIP_CONS** cons, /**< pointer to hold the created constraint */
const char* name, /**< name of constraint */
SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
SCIP_ORBITOPETYPE orbitopetype, /**< type of orbitope constraint */
int nspcons, /**< number of set partitioning/packing constraints <=> p */
int nblocks, /**< number of symmetric variable blocks <=> q */
SCIP_Bool resolveprop, /**< should propagation be resolved? */
SCIP_Bool ismodelcons /**< whether the orbitope is a model constraint */
);
// NOLINTNEXTLINE(readability-identifier-naming)
SCIP_Longint(__stdcall* SCIPgetNSolsFound)(SCIP* scip);
// NOLINTNEXTLINE(readability-identifier-naming)
@ -379,13 +359,6 @@ public:
void addCumulative(int nnz, int* rmatind, double* d, double* r, double b,
const std::string& rowName = "") override;
/// Lex-lesseq binary, currently SCIP only
void addLexLesseq(int nnz, int* rmatind1, int* rmatind2, bool isModelCons,
const std::string& rowName = "") override;
void addLexChainLesseq(int m, int n, int* rmatind, int nOrbitopeType, bool resolveprop,
bool isModelCons, const std::string& rowName = "") override;
/// Times constraint: var[x]*var[y] == var[z]
void addTimes(int x, int y, int z, const std::string& rowName = "") override;

View File

@ -544,7 +544,7 @@ void MIPSolverinstance<MIPWrapper>::printStatistics() {
};
env.outstream.setf(std::ios::fixed);
env.outstream.precision(4);
env.outstream << "%%%mzn-stat: solveTime=" << _mipWrapper->getCPUTime() << std::endl;
env.outstream << "%%%mzn-stat: solveTime=" << _mipWrapper->getWallTimeElapsed() << std::endl;
;
env.outstream.copyfmt(oldState);
@ -979,6 +979,8 @@ template <class MIPWrapper>
void p_cumulative(SolverInstanceBase& si, const Call* call) {
auto& gi = dynamic_cast<MIPSolverinstance<MIPWrapper>&>(si);
std::unique_ptr<SECCutGen> pCG(new SECCutGen(gi.getMIPWrapper()));
assert(call->argCount() == 4);
std::vector<MIPSolver::Variable> startTimes;
@ -994,42 +996,6 @@ void p_cumulative(SolverInstanceBase& si, const Call* call) {
make_constraint_name("p_cumulative_", (gi.getMIPWrapper()->nAddedRows++), call));
}
template <class MIPWrapper>
void p_lex_lesseq_binary(SolverInstanceBase& si, const Call* call) {
auto& gi = dynamic_cast<MIPSolverinstance<MIPWrapper>&>(si);
assert(call->argCount() == 3);
std::vector<MIPSolver::Variable> vec1;
std::vector<MIPSolver::Variable> vec2;
gi.exprToVarArray(call->arg(0), vec1);
gi.exprToVarArray(call->arg(1), vec2);
auto isModelCons = gi.exprToConst(call->arg(2));
MZN_ASSERT_HARD(vec1.size() == vec2.size());
gi.getMIPWrapper()->addLexLesseq(
vec1.size(), vec1.data(), vec2.data(), (bool)isModelCons,
make_constraint_name("p_lex_lesseq__orbisack_", (gi.getMIPWrapper()->nAddedRows++), call));
}
template <class MIPWrapper>
void p_lex_chain_lesseq_binary(SolverInstanceBase& si, const Call* call) {
auto& gi = dynamic_cast<MIPSolverinstance<MIPWrapper>&>(si);
assert(call->argCount() == 5);
std::vector<MIPSolver::Variable> vars;
gi.exprToVarArray(call->arg(0), vars);
auto m = gi.exprToConst(call->arg(1));
auto orbitopeType = gi.exprToConst(call->arg(2));
auto resolveprop = gi.exprToConst(call->arg(3));
auto isModelCons = gi.exprToConst(call->arg(4));
gi.getMIPWrapper()->addLexChainLesseq(
m, vars.size() / m, vars.data(), orbitopeType, (bool)resolveprop, (bool)isModelCons,
make_constraint_name("p_lex_lesseq__orbisack_", (gi.getMIPWrapper()->nAddedRows++), call));
}
/// The XBZ cut generator
template <class MIPWrapper>
void p_xbz_cutgen(SolverInstanceBase& si, const Call* call) {
@ -1153,12 +1119,6 @@ void MIPSolverinstance<MIPWrapper>::registerConstraints() {
_constraintRegistry.add("fzn_cumulative_fixed_d_r", SCIPConstraints::p_cumulative<MIPWrapper>);
_constraintRegistry.add("fzn_lex_lesseq__orbisack",
SCIPConstraints::p_lex_lesseq_binary<MIPWrapper>);
_constraintRegistry.add("fzn_lex_chain_lesseq__orbitope",
SCIPConstraints::p_lex_chain_lesseq_binary<MIPWrapper>);
_constraintRegistry.add("bounds_disj", SCIPConstraints::p_bounds_disj<MIPWrapper>);
_constraintRegistry.add("fzn_array_float_minimum", SCIPConstraints::p_array_minimum<MIPWrapper>);

View File

@ -54,7 +54,7 @@ public:
/// Lazy cut. Can cut off otherwise feasible integer solutions.
/// Callback should be able to produce previously generated cuts again if needed [Gurobi]
static const int MaskConsType_Lazy = 4;
enum Status { OPT, SAT, UNSAT, UNBND, UNSATorUNBND, UNKNOWN, ERROR_STATUS };
enum Status { OPT, SAT, UNSAT, UNBND, UNSATorUNBND, UNKNOWN, __ERROR };
/// Search strategy for the solver
enum SearchType { FIXED_SEARCH = 0, FREE_SEARCH = 1, UNIFORM_SEARCH = 2 };
@ -102,7 +102,7 @@ public:
LinConType sense = LQ;
double rhs = 0.0;
int mask = 0; // need to know what type of cuts are registered before solve() TODO
std::string rowName;
std::string rowName = "";
void addVar(int i, double c) {
rmatind.push_back(i);
rmatval.push_back(c);
@ -282,19 +282,6 @@ public:
const std::string& rowName = "") {
throw std::runtime_error("Cumulative constraints not supported. ");
}
/// Lex-lesseq binary, currently SCIP only
virtual void addLexLesseq(int nnz, int* rmatind1, int* rmatind2, bool isModelCons,
const std::string& rowName = "") {
throw std::runtime_error("MIP: lex_lesseq built-in not supported. ");
}
/// Lex-chain-lesseq binary, currently SCIP only
virtual void addLexChainLesseq(int m, int n, int* rmatind, int nOrbitopeType, bool resolveprop,
bool isModelCons, const std::string& rowName = "") {
throw std::runtime_error("MIP: lex_chain_lesseq built-in not supported. ");
}
/// 0: model-defined level, 1: free, 2: uniform search
virtual int getFreeSearch() { return SearchType::FREE_SEARCH; }
/// Return 0 if ignoring searches

View File

@ -38,15 +38,15 @@ public:
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSsetlogfile)(XPRSprob prob, const char* logname);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSsetintcontrol)(XPRSprob prob, int index, int ivalue);
int(XPRS_CC* XPRSsetintcontrol)(XPRSprob prob, int _index, int _ivalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSsetdblcontrol)(XPRSprob prob, int index, double dvalue);
int(XPRS_CC* XPRSsetdblcontrol)(XPRSprob prob, int _index, double _dvalue);
// NOLINTNEXTLINE(readability-identifier-naming)
double(XB_CC* XPRBgetsol)(struct Xbvar* var);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetintattrib)(XPRSprob prob, int index, int* ivalue);
int(XPRS_CC* XPRSgetintattrib)(XPRSprob prob, int _index, int* _ivalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetdblattrib)(XPRSprob prob, int index, double* dvalue);
int(XPRS_CC* XPRSgetdblattrib)(XPRSprob prob, int _index, double* _dvalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XB_CC* XPRBbegincb)(struct Xbprob* prob, struct xo_prob_struct* optprob);
// NOLINTNEXTLINE(readability-identifier-naming)
@ -95,20 +95,20 @@ public:
int(XPRS_CC* XPRSgetcontrolinfo)(XPRSprob prob, const char* sCaName, int* iHeaderId,
int* iTypeinfo);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetintcontrol)(XPRSprob prob, int index, int* ivalue);
int(XPRS_CC* XPRSgetintcontrol)(XPRSprob prob, int _index, int* _ivalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetintcontrol64)(XPRSprob prob, int index, XPRSint64* ivalue);
int(XPRS_CC* XPRSgetintcontrol64)(XPRSprob prob, int _index, XPRSint64* _ivalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetdblcontrol)(XPRSprob prob, int index, double* dvalue);
int(XPRS_CC* XPRSgetdblcontrol)(XPRSprob prob, int _index, double* _dvalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetstrcontrol)(XPRSprob prob, int index, char* svalue);
int(XPRS_CC* XPRSgetstrcontrol)(XPRSprob prob, int _index, char* _svalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSsetintcontrol64)(XPRSprob prob, int index, XPRSint64 ivalue);
int(XPRS_CC* XPRSsetintcontrol64)(XPRSprob prob, int _index, XPRSint64 _ivalue);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSgetstringcontrol)(XPRSprob prob, int index, char* svalue, int svaluesize,
int* controlsize);
int(XPRS_CC* XPRSgetstringcontrol)(XPRSprob prob, int _index, char* _svalue, int _svaluesize,
int* _controlsize);
// NOLINTNEXTLINE(readability-identifier-naming)
int(XPRS_CC* XPRSsetstrcontrol)(XPRSprob prob, int index, const char* svalue);
int(XPRS_CC* XPRSsetstrcontrol)(XPRSprob prob, int _index, const char* _svalue);
private:
void loadDll();
@ -130,8 +130,8 @@ public:
int msgLevel = 0;
int timeout = 0;
int numSolutions = 0;
std::string logFile;
std::string writeModelFile;
std::string logFile = "";
std::string writeModelFile = "";
std::string writeModelFormat = "lp";
double absGap = 0;
double relGap = 0.0001;

View File

@ -41,27 +41,27 @@ inline long long int round_to_longlong(double v) {
namespace MiniZinc {
// #define MZN_PRINTATONCE_
#ifdef MZN_PRINTATONCE_
#define MZN_PRINT_SRCLOC(e1, e2) \
// #define __MZN_PRINTATONCE__
#ifdef __MZN_PRINTATONCE__
#define __MZN_PRINT_SRCLOC(e1, e2) \
std::cerr << '\n' \
<< __FILE__ << ": " << __LINE__ << " (" << __func__ << "): not " << e1 << ": " \
<< std::flush; \
std::cerr << e2 << std::endl
#else
#define MZN_PRINT_SRCLOC(e1, e2)
#define __MZN_PRINT_SRCLOC(e1, e2)
#endif
#define MZN_ASSERT_HARD(c) \
do { \
if (!(c)) { \
MZN_PRINT_SRCLOC(#c, ""); \
throw InternalError(#c); \
} \
#define MZN_ASSERT_HARD(c) \
do { \
if (!(c)) { \
__MZN_PRINT_SRCLOC(#c, ""); \
throw InternalError(#c); \
} \
} while (0)
#define MZN_ASSERT_HARD_MSG(c, e) \
do { \
if (!(c)) { \
MZN_PRINT_SRCLOC(#c, e); \
__MZN_PRINT_SRCLOC(#c, e); \
std::ostringstream oss; \
oss << "not " << #c << ": " << e; /* NOLINT(bugprone-macro-parentheses) */ \
throw MiniZinc::InternalError(oss.str()); \

File diff suppressed because it is too large Load Diff

View File

@ -1592,7 +1592,6 @@ Constants::Constants() {
ids.set_subset = ASTString("set_subset");
ids.set_card = ASTString("set_card");
ids.pow = ASTString("pow");
ids.mzn_set_in_internal = ASTString("mzn_set_in_internal");
ids.introduced_var = ASTString("__INTRODUCED");
ids.anonEnumFromStrings = ASTString("anon_enum");
@ -1832,7 +1831,6 @@ void Constants::mark(MINIZINC_GC_STAT_ARGS) {
ids.set_subset.mark();
ids.set_card.mark();
ids.pow.mark();
ids.mzn_set_in_internal.mark();
ids.assert.mark();
ids.mzn_deprecate.mark();

View File

@ -1619,10 +1619,6 @@ std::string b_logstream(EnvI& env, Call* call) { return env.logstream.str(); }
bool b_in_redundant_constraint(EnvI& env, Call* /*call*/) { return env.inRedundantConstraint > 0; }
bool b_in_symmetry_breaking_constraint(EnvI& env, Call* /*call*/) {
return env.inSymmetryBreakingConstraint > 0;
}
Expression* b_set2array(EnvI& env, Call* call) {
assert(call->argCount() == 1);
GCLock lock;
@ -1789,7 +1785,7 @@ std::string b_show_json(EnvI& env, Call* call) {
}
Expression* b_output_json(EnvI& env, Call* call) {
return create_json_output(env, false, false, false);
return create__json_output(env, false, false, false);
}
Expression* b_output_json_parameters(EnvI& env, Call* call) {
std::vector<Expression*> outputVars;
@ -3181,10 +3177,6 @@ void register_builtins(Env& e) {
rb(env, m, ASTString("mzn_in_redundant_constraint"), std::vector<Type>(),
b_in_redundant_constraint);
}
{
rb(env, m, ASTString("mzn_in_symmetry_breaking_constraint"), std::vector<Type>(),
b_in_symmetry_breaking_constraint);
}
{
std::vector<Type> t_length(1);
t_length[0] = Type::optvartop(-1);

View File

@ -1,4 +1,4 @@
set(lexer_lxx_md5_cached "6346180a9a94e9f5218239f10ce67a32")
set(parser_yxx_md5_cached "95616f87b6ecbe14f80175ec8369e696")
set(parser_yxx_md5_cached "dca3042b18c4db1f1e625d1d46bdb3d1")
set(regex_lexer_lxx_md5_cached "8906a52bfa0c5ae26354cb272348e656")
set(regex_parser_yxx_md5_cached "68ec070becef5e161c3b97d085b0810e")

View File

@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.7.4. */
/* A Bison parser, made by GNU Bison 3.6.4. */
/* Bison interface for Yacc-like parsers in C
@ -35,8 +35,8 @@
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_BUILD_XCODE_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED
# define YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_BUILD_XCODE_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED
#ifndef YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_DEVELOP_BUILD_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED
# define YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_DEVELOP_BUILD_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
@ -234,4 +234,4 @@ struct YYLTYPE
int mzn_yyparse (void *parm);
#endif /* !YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_BUILD_XCODE_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED */
#endif /* !YY_MZN_YY_USERS_TACK_PROGRAMMING_MINIZINC_LIBMZN_DEVELOP_BUILD_INCLUDE_MINIZINC_PARSER_TAB_HH_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@ -64,10 +64,8 @@ bool ImpCompressor::trackItem(Item* i) {
auto* positive = c->arg(0)->cast<ArrayLit>();
auto* negative = c->arg(1)->cast<ArrayLit>();
if (positive->length() == 1 && negative->length() == 1) {
auto* var = (*negative)[0]->dynamicCast<Id>();
if (var != nullptr) {
storeItem(var->decl(), i);
}
auto* var = (*negative)[0]->cast<Id>();
storeItem(var->decl(), i);
return true;
}
} else if (c->id() == "mzn_reverse_map_var") {
@ -77,11 +75,9 @@ bool ImpCompressor::trackItem(Item* i) {
return true;
// pred_imp(..., b); i.e. b -> pred(...)
} else if (c->id().endsWith("_imp")) {
auto* control = c->arg(c->argCount() - 1)->dynamicCast<Id>();
if (control != nullptr) {
assert(control->type().isvarbool());
storeItem(control->decl(), i);
}
auto* control = c->arg(c->argCount() - 1)->cast<Id>();
assert(control->type().isvarbool());
storeItem(control->decl(), i);
return true;
}
}
@ -125,42 +121,40 @@ void ImpCompressor::compress() {
auto* c = ci->e()->cast<Call>();
if (c->id() == constants().ids.clause) {
auto* positive = c->arg(0)->cast<ArrayLit>();
auto* var = (*positive)[0]->dynamicCast<Id>();
if (var != nullptr) {
bool output_var = var->decl()->ann().contains(constants().ann.output_var);
auto usages = _env.varOccurrences.usages(var->decl());
output_var = output_var || usages.second;
int occurrences = usages.first;
unsigned long lhs_occurences = count(var->decl());
auto* var = (*positive)[0]->cast<Id>();
bool output_var = var->decl()->ann().contains(constants().ann.output_var);
auto usages = _env.varOccurrences.usages(var->decl());
output_var = output_var || usages.second;
int occurrences = usages.first;
unsigned long lhs_occurences = count(var->decl());
// Compress if:
// - There is one occurrence on the RHS of a clause and the others are on the LHS of a
// clause
// - There is one occurrence on the RHS of a clause, that Id is a reified forall that has
// no other occurrences
// - There is one occurrence on the RHS of a clause, that Id is a reification in a
// positive context, and all other occurrences are on the LHS of a clause
bool compress = !output_var && lhs_occurences > 0;
if ((var->decl()->e() != nullptr) && (var->decl()->e()->dynamicCast<Call>() != nullptr)) {
auto* call = var->decl()->e()->cast<Call>();
if (call->id() == constants().ids.forall) {
compress = compress && (occurrences == 1 && lhs_occurences == 1);
} else {
compress = compress && (occurrences == lhs_occurences);
}
// Compress if:
// - There is one occurrence on the RHS of a clause and the others are on the LHS of a
// clause
// - There is one occurrence on the RHS of a clause, that Id is a reified forall that has no
// other occurrences
// - There is one occurrence on the RHS of a clause, that Id is a reification in a positive
// context, and all other occurrences are on the LHS of a clause
bool compress = !output_var && lhs_occurences > 0;
if ((var->decl()->e() != nullptr) && (var->decl()->e()->dynamicCast<Call>() != nullptr)) {
auto* call = var->decl()->e()->cast<Call>();
if (call->id() == constants().ids.forall) {
compress = compress && (occurrences == 1 && lhs_occurences == 1);
} else {
compress = compress && (occurrences == lhs_occurences + 1);
compress = compress && (occurrences == lhs_occurences);
}
if (compress) {
rhs = var->decl();
auto* negative = c->arg(1)->cast<ArrayLit>();
lhs = (*negative)[0]->isa<Id>() ? (*negative)[0]->cast<Id>()->decl() : nullptr;
if (lhs == rhs) {
continue;
}
}
// TODO: Detect equivalences for output variables.
} else {
compress = compress && (occurrences == lhs_occurences + 1);
}
if (compress) {
rhs = var->decl();
auto* negative = c->arg(1)->cast<ArrayLit>();
lhs = (*negative)[0]->cast<Id>()->decl();
if (lhs == rhs) {
continue;
}
}
// TODO: Detect equivalences for output variables.
}
}
@ -195,9 +189,8 @@ bool ImpCompressor::compressItem(Item* i, VarDecl* newLHS) {
// Given (x -> y) /\ (y -> z), produce x -> z
if (c->id() == constants().ids.clause) {
auto* positive = c->arg(0)->cast<ArrayLit>();
VarDecl* positiveDecl =
(*positive)[0]->isa<Id>() ? (*positive)[0]->cast<Id>()->decl() : nullptr;
if (positiveDecl != newLHS) {
auto* rhs = (*positive)[0]->cast<Id>();
if (rhs->decl() != newLHS) {
ConstraintI* nci = constructClause(positive, newLHS->id());
_boolConstraints.push_back(addItem(nci));
}
@ -219,9 +212,9 @@ bool ImpCompressor::compressItem(Item* i, VarDecl* newLHS) {
if (c->id() == constants().ids.forall) {
auto* exprs = c->arg(0)->cast<ArrayLit>();
for (int j = 0; j < exprs->size(); ++j) {
VarDecl* rhsDecl = (*exprs)[j]->isa<Id>() ? (*exprs)[j]->cast<Id>()->decl() : nullptr;
if (rhsDecl != newLHS) {
ConstraintI* nci = constructClause((*exprs)[j], newLHS->id());
auto* rhs = (*exprs)[j]->cast<Id>();
if (rhs->decl() != newLHS) {
ConstraintI* nci = constructClause(rhs, newLHS->id());
_boolConstraints.push_back(addItem(nci));
}
}
@ -260,10 +253,8 @@ ConstraintI* ImpCompressor::constructClause(Expression* pos, Expression* neg) {
args[1]->type(Type::varbool(1));
}
// NEVER CREATE (a -> a)
assert(!(*args[0]->cast<ArrayLit>())[0]->isa<Id>() ||
!(*args[1]->cast<ArrayLit>())[0]->isa<Id>() ||
(*args[0]->cast<ArrayLit>())[0]->cast<Id>()->decl() !=
(*args[1]->cast<ArrayLit>())[0]->cast<Id>()->decl());
assert((*args[0]->dynamicCast<ArrayLit>())[0]->dynamicCast<Id>()->decl() !=
(*args[1]->dynamicCast<ArrayLit>())[0]->dynamicCast<Id>()->decl());
auto* nc = new Call(MiniZinc::Location().introduce(), constants().ids.clause, args);
nc->type(Type::varbool());
nc->decl(_env.model->matchFn(_env, nc, false));

View File

@ -103,21 +103,15 @@ bool EvalBase::evalBoolCV(EnvI& env, Expression* e) {
return eval_bool(env, e);
};
KeepAlive EvalBase::flattenCV(EnvI& env, Expression* e) {
GCLock lock;
Ctx ctx;
ctx.i = C_MIX;
ctx.b = (e->type().bt() == Type::BT_BOOL) ? C_MIX : C_ROOT;
EE ee = flat_exp(env, ctx, e, nullptr, constants().varTrue);
return ee.r;
}
class EvalIntLit : public EvalBase {
public:
typedef IntLit* Val;
typedef Expression* ArrayVal;
static IntLit* e(EnvI& env, Expression* e) { return IntLit::a(eval_int(env, e)); }
static Expression* exp(IntLit* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalIntVal : public EvalBase {
public:
@ -134,6 +128,9 @@ public:
}
}
}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalFloatVal : public EvalBase {
public:
@ -150,6 +147,9 @@ public:
}
}
}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalFloatLit : public EvalBase {
public:
@ -157,6 +157,9 @@ public:
typedef Expression* ArrayVal;
static FloatLit* e(EnvI& env, Expression* e) { return FloatLit::a(eval_float(env, e)); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalString : public EvalBase {
public:
@ -165,6 +168,9 @@ public:
static std::string e(EnvI& env, Expression* e) { return eval_string(env, e); }
static Expression* exp(const std::string& e) { return new StringLit(Location(), e); }
static void checkRetVal(EnvI& env, const Val& v, FunctionI* fi) {}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalStringLit : public EvalBase {
public:
@ -174,6 +180,9 @@ public:
return new StringLit(Location(), eval_string(env, e));
}
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalBoolLit : public EvalBase {
public:
@ -181,6 +190,9 @@ public:
typedef Expression* ArrayVal;
static BoolLit* e(EnvI& env, Expression* e) { return constants().boollit(eval_bool(env, e)); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalBoolVal : public EvalBase {
public:
@ -188,6 +200,9 @@ public:
static bool e(EnvI& env, Expression* e) { return eval_bool(env, e); }
static Expression* exp(bool e) { return constants().boollit(e); }
static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalArrayLit : public EvalBase {
public:
@ -195,6 +210,9 @@ public:
typedef Expression* ArrayVal;
static ArrayLit* e(EnvI& env, Expression* e) { return eval_array_lit(env, e); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalArrayLitCopy : public EvalBase {
public:
@ -273,6 +291,9 @@ public:
}
}
}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalIntSet : public EvalBase {
public:
@ -290,6 +311,9 @@ public:
}
}
}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalFloatSet : public EvalBase {
public:
@ -307,6 +331,9 @@ public:
}
}
}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalBoolSet : public EvalBase {
public:
@ -318,6 +345,9 @@ public:
return sl;
}
static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalSetLit : public EvalBase {
public:
@ -325,6 +355,9 @@ public:
typedef Expression* ArrayVal;
static SetLit* e(EnvI& env, Expression* e) { return eval_set_lit(env, e); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalFloatSetLit : public EvalBase {
public:
@ -332,6 +365,9 @@ public:
typedef Expression* ArrayVal;
static SetLit* e(EnvI& env, Expression* e) { return new SetLit(e->loc(), eval_floatset(env, e)); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalBoolSetLit : public EvalBase {
public:
@ -343,6 +379,9 @@ public:
return sl;
}
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalCopy : public EvalBase {
public:
@ -350,6 +389,9 @@ public:
typedef Expression* ArrayVal;
static Expression* e(EnvI& env, Expression* e) { return copy(env, e, true); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
class EvalPar : public EvalBase {
public:
@ -358,6 +400,9 @@ public:
static Expression* e(EnvI& env, Expression* e) { return eval_par(env, e); }
static Expression* exp(Expression* e) { return e; }
static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {}
static Expression* flatten(EnvI& /*env*/, Expression* /*e*/) {
throw InternalError("evaluating var assignment generator inside par expression not supported");
}
};
void check_dom(EnvI& env, Id* arg, IntSetVal* dom, Expression* e) {
@ -1199,9 +1244,7 @@ bool eval_bool(EnvI& env, Expression* e) {
return false;
}
} else if (bo->op() == BOT_EQ && lhs->type().isAnn()) {
// follow ann id to value, since there might be indirection (e.g. func argument, see
// test_equality_of_indirect_annotations.mzn)
return Expression::equal(follow_id_to_value(lhs), follow_id_to_value(rhs));
return Expression::equal(lhs, rhs);
} else if (bo->op() == BOT_EQ && lhs->type().dim() > 0 && rhs->type().dim() > 0) {
try {
ArrayLit* al0 = eval_array_lit(env, lhs);

View File

@ -681,7 +681,6 @@ EnvI::EnvI(Model* model0, std::ostream& outstream0, std::ostream& errstream0)
ignoreUnknownIds(false),
maxCallStack(0),
inRedundantConstraint(0),
inSymmetryBreakingConstraint(0),
inMaybePartial(0),
inReverseMapVar(false),
counters({0, 0, 0, 0}),
@ -737,9 +736,6 @@ EnvI::~EnvI() {
}
long long int EnvI::genId() { return _ids++; }
void EnvI::cseMapInsert(Expression* e, const EE& ee) {
if (e->type().isPar() && !e->isa<ArrayLit>()) {
return;
}
KeepAlive ka(e);
_cseMap.insert(ka, WW(ee.r(), ee.b()));
Call* c = e->dynamicCast<Call>();
@ -857,11 +853,6 @@ void EnvI::annotateFromCallStack(Expression* e) {
bool allCalls = true;
for (int i = static_cast<int>(callStack.size()) - 1; i >= prev; i--) {
Expression* ee = callStack[i]->untag();
if (ee->type().isAnn()) {
// If we are inside an annotation call, don't annotate it again with
// anything from outside the call
break;
}
allCalls = allCalls && (i == callStack.size() - 1 || ee->isa<Call>() || ee->isa<BinOp>());
for (ExpressionSetIter it = ee->ann().begin(); it != ee->ann().end(); ++it) {
EE ee_ann = flat_exp(*this, Ctx(), *it, nullptr, constants().varTrue);
@ -1113,9 +1104,6 @@ CallStackItem::CallStackItem(EnvI& env0, Expression* e) : env(env0) {
if (e->isa<Call>() && e->cast<Call>()->id() == "redundant_constraint") {
env.inRedundantConstraint++;
}
if (e->isa<Call>() && e->cast<Call>()->id() == "symmetry_breaking_constraint") {
env.inSymmetryBreakingConstraint++;
}
if (e->ann().contains(constants().ann.maybe_partial)) {
env.inMaybePartial++;
}
@ -1136,9 +1124,6 @@ CallStackItem::~CallStackItem() {
if (e->isa<Call>() && e->cast<Call>()->id() == "redundant_constraint") {
env.inRedundantConstraint--;
}
if (e->isa<Call>() && e->cast<Call>()->id() == "symmetry_breaking_constraint") {
env.inSymmetryBreakingConstraint--;
}
if (e->ann().contains(constants().ann.maybe_partial)) {
env.inMaybePartial--;
}
@ -2689,6 +2674,10 @@ KeepAlive flat_cv_exp(EnvI& env, Ctx ctx, Expression* e) {
typedef Expression* ArrayVal;
Expression* e(EnvI& env, Expression* e) const { return flat_cv_exp(env, ctx, e)(); }
static Expression* exp(Expression* e) { return e; }
static Expression* flatten(EnvI& env, Expression* e0) {
return flat_exp(env, Ctx(), e0, nullptr, constants().varTrue).r();
}
} eval(ctx);
std::vector<Expression*> a = eval_comp<EvalFlatCvExp>(env, eval, c);
@ -3157,14 +3146,8 @@ void flatten(Env& e, FlatteningOptions opt) {
GCLock lock;
IntSetVal* dom = eval_intset(env, vdi->e()->ti()->domain());
if (0 == dom->size()) {
std::ostringstream oss;
oss << "Variable has empty domain: " << (*vdi->e());
env.fail(oss.str());
}
bool needRangeDomain = onlyRangeDomains && !vdi->e()->type().isOpt();
if (!needRangeDomain && !vdi->e()->type().isOpt()) {
bool needRangeDomain = onlyRangeDomains;
if (!needRangeDomain && dom->size() > 0) {
if (dom->min(0).isMinusInfinity() || dom->max(dom->size() - 1).isPlusInfinity()) {
needRangeDomain = true;
}
@ -3203,7 +3186,7 @@ void flatten(Env& e, FlatteningOptions opt) {
std::vector<Expression*> args(2);
args[0] = vdi->e()->id();
args[1] = new SetLit(vdi->e()->loc(), dom);
Call* call = new Call(vdi->e()->loc(), constants().ids.mzn_set_in_internal, args);
Call* call = new Call(vdi->e()->loc(), constants().ids.set_in, args);
call->type(Type::varbool());
call->decl(env.model->matchFn(env, call, false));
// Give distinct call stack
@ -3224,11 +3207,6 @@ void flatten(Env& e, FlatteningOptions opt) {
vdi->e()->ti()->domain() != nullptr) {
GCLock lock;
FloatSetVal* vdi_dom = eval_floatset(env, vdi->e()->ti()->domain());
if (0 == vdi_dom->size()) {
std::ostringstream oss;
oss << "Variable has empty domain: " << (*vdi->e());
env.fail(oss.str());
}
FloatVal vmin = vdi_dom->min();
FloatVal vmax = vdi_dom->max();
if (vmin == -FloatVal::infinity() && vmax == FloatVal::infinity()) {

View File

@ -193,6 +193,9 @@ EE flatten_comp(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b
: nullptr;
return flat_exp(env, ctx, e0, r, b);
}
static Expression* flatten(EnvI& env, Expression* e0) {
return flat_exp(env, Ctx(), e0, nullptr, constants().varTrue).r();
}
} _evalf(ctx);
std::vector<EE> elems_ee;
bool wasUndefined = false;

View File

@ -36,35 +36,26 @@ EE flatten_par(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b)
}
if (e->type().dim() > 0) {
EnvI::CSEMap::iterator it;
auto* ident = e->dynamicCast<Id>();
if (ident != nullptr) {
Expression* e_val = follow_id_to_decl(ident);
if (e_val->isa<Id>()) {
ident = e_val->cast<Id>();
} else if (e_val->isa<VarDecl>()) {
ident = e_val->cast<VarDecl>()->id();
}
if (ident->decl()->flat() == nullptr || ident->decl()->toplevel()) {
VarDecl* vd = ident->decl()->flat();
if (vd == nullptr) {
EE flat_ident = flat_exp(env, Ctx(), ident->decl(), nullptr, constants().varTrue);
vd = flat_ident.r()->cast<Id>()->decl();
ident->decl()->flat(vd);
auto* al = follow_id(vd->id())->cast<ArrayLit>();
if (al->size() == 0) {
if (r == nullptr) {
ret.r = al;
} else {
ret.r = bind(env, ctx, r, al);
}
ret.b = bind(env, Ctx(), b, constants().literalTrue);
return ret;
Id* id = e->dynamicCast<Id>();
if ((id != nullptr) && (id->decl()->flat() == nullptr || id->decl()->toplevel())) {
VarDecl* vd = id->decl()->flat();
if (vd == nullptr) {
vd = flat_exp(env, Ctx(), id->decl(), nullptr, constants().varTrue).r()->cast<Id>()->decl();
id->decl()->flat(vd);
auto* al = follow_id(vd->id())->cast<ArrayLit>();
if (al->size() == 0) {
if (r == nullptr) {
ret.r = al;
} else {
ret.r = bind(env, ctx, r, al);
}
ret.b = bind(env, Ctx(), b, constants().literalTrue);
return ret;
}
ret.r = bind(env, ctx, r, e->cast<Id>()->decl()->flat()->id());
ret.b = bind(env, Ctx(), b, constants().literalTrue);
return ret;
}
ret.r = bind(env, ctx, r, e->cast<Id>()->decl()->flat()->id());
ret.b = bind(env, Ctx(), b, constants().literalTrue);
return ret;
}
if ((it = env.cseMapFind(e)) != env.cseMapEnd()) {
ret.r = bind(env, ctx, r, it->second.r()->cast<VarDecl>()->id());

View File

@ -34,11 +34,7 @@ EE flatten_setlit(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl*
ret.b = conj(env, b, Ctx(), elems_ee);
if (allPar) {
GCLock lock;
auto* nsl = new SetLit(Location().introduce(), elems);
Type nsl_t(e->type());
nsl_t.ti(Type::TI_PAR);
nsl->type(nsl_t);
Expression* ee = eval_set_lit(env, nsl);
Expression* ee = eval_set_lit(env, e);
ret.r = bind(env, Ctx(), r, ee);
} else {
GCLock lock;

View File

@ -63,13 +63,6 @@ EE flatten_vardecl(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl
}
}
}
if (vd->e() != nullptr && vd->e()->type().isPar() && !vd->ti()->type().isPar()) {
// Flattening the RHS resulted in a par expression. Make the variable par.
Type t(vd->ti()->type());
t.ti(Type::TI_PAR);
vd->ti()->type(t);
vd->type(t);
}
}
ret.r = bind(env, Ctx(), r, vd->id());

View File

@ -474,10 +474,9 @@ void Flattener::flatten(const std::string& modelString, const std::string& model
}
if (!_globalsDir.empty()) {
_includePaths.insert(_includePaths.begin(),
FileUtils::file_path(_stdLibDir + "/" + _globalsDir + "/"));
_includePaths.insert(_includePaths.begin(), _stdLibDir + "/" + _globalsDir + "/");
}
_includePaths.push_back(FileUtils::file_path(_stdLibDir + "/std/"));
_includePaths.push_back(_stdLibDir + "/std/");
for (auto& includePath : _includePaths) {
if (!FileUtils::directory_exists(includePath)) {

View File

@ -629,8 +629,7 @@ void JSONParser::parseModel(Model* m, std::istream& is, bool isData) {
string ident = expectString(is);
expectToken(is, T_COLON);
auto it = knownIds.find(ident);
bool possibleString = it == knownIds.end() ||
(!it->second->isEnum() && it->second->type().bt() != Type::BT_UNKNOWN);
bool possibleString = it == knownIds.end() || it->second->type().bt() != Type::BT_UNKNOWN;
Expression* e = parseExp(is, isData, possibleString);
if (ident[0] != '_' && (!isData || it != knownIds.end())) {
if (e == nullptr) {
@ -648,7 +647,7 @@ void JSONParser::parseModel(Model* m, std::istream& is, bool isData) {
e = coerceArray(it->second, al);
} else if (it->second->type().isSet()) {
// Convert array to a set
e = new SetLit(Location().introduce(), al->getVec());
e = new Call(Location().introduce(), "array2set", {al});
}
}
auto* ai = new AssignI(e->loc().introduce(), ident, e);

View File

@ -217,7 +217,7 @@ void make_par(EnvI& env, Expression* e) {
bool outputObjective = (c.argCount() == 1 && eval_bool(env, c.arg(0)));
c.id(ASTString("array1d"));
Expression* json =
copy(env, env.cmap, create_json_output(env, outputObjective, false, false));
copy(env, env.cmap, create__json_output(env, outputObjective, false, false));
std::vector<Expression*> new_args({json});
new_args[0]->type(Type::parstring(1));
c.args(new_args);
@ -655,14 +655,12 @@ void create_dzn_output_item(EnvI& e, bool outputObjective, bool includeOutputIte
bool needArrayXd = false;
if (vd->type().dim() > 0) {
ArrayLit* al = nullptr;
if (!vd->ann().contains(constants().ann.output_only)) {
if ((vd->flat() != nullptr) && (vd->flat()->e() != nullptr)) {
al = eval_array_lit(_e, vd->flat()->e());
} else if (vd->e() != nullptr) {
al = eval_array_lit(_e, vd->e());
}
if ((vd->flat() != nullptr) && (vd->flat()->e() != nullptr)) {
al = eval_array_lit(_e, vd->flat()->e());
} else if (vd->e() != nullptr) {
al = eval_array_lit(_e, vd->e());
}
if (al == nullptr || al->size() > 0) {
if (al->size() > 0) {
needArrayXd = true;
s << "array" << vd->type().dim() << "d(";
for (int i = 0; i < vd->type().dim(); i++) {
@ -672,33 +670,9 @@ void create_dzn_output_item(EnvI& e, bool outputObjective, bool includeOutputIte
s << _e.getEnum(enumId)->e()->id()->str() << ", ";
} else if (al != nullptr) {
s << al->min(i) << ".." << al->max(i) << ", ";
} else if (vd->ti()->ranges()[i]->domain() != nullptr) {
} else {
IntSetVal* idxset = eval_intset(_e, vd->ti()->ranges()[i]->domain());
s << *idxset << ", ";
} else {
// Don't know index set range - have to compute in solns2out
auto* sl = new StringLit(Location().introduce(), s.str());
_outputVars.push_back(sl);
std::string index_set_fn = "index_set";
if (vd->type().dim() > 1) {
index_set_fn +=
"_" + std::to_string(i + 1) + "of" + std::to_string(vd->type().dim());
}
auto* index_set_xx = new Call(Location().introduce(), index_set_fn, {vd->id()});
index_set_xx->type(Type::parsetint());
auto* i_fi = _e.model->matchFn(_e, index_set_xx, false);
assert(i_fi);
index_set_xx->decl(i_fi);
auto* show = new Call(Location().introduce(), constants().ids.show, {index_set_xx});
show->type(Type::parstring());
FunctionI* s_fi = _e.model->matchFn(_e, show, false);
assert(s_fi);
show->decl(s_fi);
_outputVars.push_back(show);
s.str(", ");
}
}
}
@ -764,8 +738,8 @@ void create_dzn_output_item(EnvI& e, bool outputObjective, bool includeOutputIte
e.model->addItem(newOutputItem);
}
ArrayLit* create_json_output(EnvI& e, bool outputObjective, bool includeOutputItem,
bool hasChecker) {
ArrayLit* create__json_output(EnvI& e, bool outputObjective, bool includeOutputItem,
bool hasChecker) {
std::vector<Expression*> outputVars;
outputVars.push_back(new StringLit(Location().introduce(), "{\n"));
@ -893,7 +867,7 @@ void create_json_output_item(EnvI& e, bool outputObjective, bool includeOutputIt
bool hasChecker) {
auto* newOutputItem =
new OutputI(Location().introduce(),
create_json_output(e, outputObjective, includeOutputItem, hasChecker));
create__json_output(e, outputObjective, includeOutputItem, hasChecker));
e.model->addItem(newOutputItem);
}

View File

@ -53,27 +53,6 @@ std::string get_file_contents(std::ifstream& in) {
namespace MiniZinc {
std::string ParserState::canonicalFilename(const std::string& f) const {
if (FileUtils::is_absolute(f) || std::string(filename).empty()) {
return f;
}
for (const auto& ip : includePaths) {
std::string fullname = FileUtils::file_path(ip + "/" + f);
if (FileUtils::file_exists(fullname)) {
return fullname;
}
}
std::string parentPath = FileUtils::dir_name(filename);
if (parentPath.empty()) {
parentPath = ".";
}
std::string fullname = FileUtils::file_path(parentPath + "/" + f);
if (FileUtils::file_exists(fullname)) {
return fullname;
}
return f;
}
void parse(Env& env, Model*& model, const vector<string>& filenames,
const vector<string>& datafiles, const std::string& modelString,
const std::string& modelStringName, const vector<string>& ip, bool isFlatZinc,
@ -103,7 +82,7 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
string fullName = filenames[i];
string baseName = FileUtils::base_name(filenames[i]);
if (!FileUtils::is_absolute(fullName)) {
fullName = FileUtils::file_path(workingDir + "/" + fullName);
fullName = workingDir + "/" + fullName;
}
bool isFzn = (baseName.compare(baseName.length() - 4, 4, ".fzn") == 0);
if (isFzn) {
@ -112,7 +91,7 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
auto* includedModel = new Model;
includedModel->setFilename(baseName);
files.emplace_back(includedModel, nullptr, "", fullName);
seenModels.insert(pair<string, Model*>(fullName, includedModel));
seenModels.insert(pair<string, Model*>(baseName, includedModel));
Location loc(ASTString(filenames[i]), 0, 0, 0, 0);
auto* inc = new IncludeI(loc, includedModel->filename());
inc->m(includedModel, true);
@ -138,19 +117,11 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
auto include_file = [&](const std::string& libname, bool builtin) {
GCLock lock;
auto* lib = new Model;
std::string fullname;
for (const auto& ip : includePaths) {
std::string n = FileUtils::file_path(ip + "/" + libname);
if (FileUtils::file_exists(n)) {
fullname = n;
break;
}
}
lib->setFilename(fullname);
files.emplace_back(lib, nullptr, "./", fullname, builtin);
seenModels.insert(pair<string, Model*>(fullname, lib));
lib->setFilename(libname);
files.emplace_back(lib, nullptr, "./", libname, builtin);
seenModels.insert(pair<string, Model*>(libname, lib));
Location libloc(ASTString(model->filename()), 0, 0, 0, 0);
auto* libinc = new IncludeI(libloc, libname);
auto* libinc = new IncludeI(libloc, lib->filename());
libinc->m(lib, true);
model->addItem(libinc);
};
@ -178,7 +149,6 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
std::string s;
std::string fullname;
std::string basename;
bool isFzn;
if (!isModelString) {
for (Model* p = m->parent(); p != nullptr; p = p->parent()) {
@ -191,36 +161,46 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
}
}
ifstream file;
if (FileUtils::is_absolute(f)) {
if (FileUtils::is_absolute(f) || parentPath.empty()) {
fullname = f;
basename = FileUtils::base_name(fullname);
if (FileUtils::file_exists(fullname)) {
file.open(FILE_PATH(fullname), std::ios::binary);
}
}
if (file.is_open() &&
FileUtils::file_path(FileUtils::dir_name(fullname)) != FileUtils::file_path(workingDir) &&
FileUtils::file_exists(workingDir + "/" + basename)) {
err << "Warning: file " << basename
<< " included from library, but also exists in current working directory" << endl;
}
for (const auto& includePath : includePaths) {
std::string deprecatedName = includePath + "/" + basename + ".deprecated.mzn";
if (FileUtils::file_exists(deprecatedName)) {
string deprecatedFullPath = FileUtils::file_path(deprecatedName);
string deprecatedBaseName = FileUtils::base_name(deprecatedFullPath);
string deprecatedDirName = FileUtils::dir_name(deprecatedFullPath);
auto* includedModel = new Model;
includedModel->setFilename(deprecatedName);
files.emplace_back(includedModel, nullptr, "", deprecatedName, isSTDLib, false);
seenModels.insert(pair<string, Model*>(deprecatedName, includedModel));
Location loc(ASTString(deprecatedName), 0, 0, 0, 0);
auto* inc = new IncludeI(loc, includedModel->filename());
inc->m(includedModel, true);
m->addItem(inc);
files.emplace_back(includedModel, inc, deprecatedDirName, deprecatedFullPath, isSTDLib,
false);
} else {
includePaths.push_back(parentPath);
unsigned int i = 0;
for (; i < includePaths.size(); i++) {
fullname = includePaths[i] + "/" + f;
if (FileUtils::file_exists(fullname)) {
file.open(FILE_PATH(fullname), std::ios::binary);
if (file.is_open()) {
break;
}
}
}
if (file.is_open() && i < includePaths.size() - 1 && parentPath == workingDir &&
FileUtils::file_path(includePaths[i], workingDir) != FileUtils::file_path(workingDir) &&
FileUtils::file_exists(workingDir + "/" + f)) {
err << "Warning: file " << f
<< " included from library, but also exists in current working directory" << endl;
}
for (; i < includePaths.size(); i++) {
std::string deprecatedName = includePaths[i] + "/" + f + ".deprecated.mzn";
if (FileUtils::file_exists(deprecatedName)) {
string deprecatedBaseName = FileUtils::base_name(deprecatedName);
auto* includedModel = new Model;
includedModel->setFilename(deprecatedBaseName);
files.emplace_back(includedModel, nullptr, "", deprecatedName, isSTDLib, false);
seenModels.insert(pair<string, Model*>(deprecatedBaseName, includedModel));
Location loc(ASTString(deprecatedName), 0, 0, 0, 0);
auto* inc = new IncludeI(loc, includedModel->filename());
inc->m(includedModel, true);
m->addItem(inc);
files.emplace_back(includedModel, inc, deprecatedName, deprecatedBaseName, isSTDLib,
false);
}
}
includePaths.pop_back();
}
if (!file.is_open()) {
if (np_ii != nullptr) {
@ -248,7 +228,7 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
fullname = f;
s = parentPath;
}
ParserState pp(fullname, s, err, includePaths, files, seenModels, m, false, isFzn, isSTDLib,
ParserState pp(fullname, s, err, files, seenModels, m, false, isFzn, isSTDLib,
parseDocComments);
mzn_yylex_init(&pp.yyscanner);
mzn_yyset_extra(&pp, pp.yyscanner);
@ -285,8 +265,7 @@ void parse(Env& env, Model*& model, const vector<string>& filenames,
s = get_file_contents(file);
}
ParserState pp(f, s, err, includePaths, files, seenModels, model, true, false, false,
parseDocComments);
ParserState pp(f, s, err, files, seenModels, model, true, false, false, parseDocComments);
mzn_yylex_init(&pp.yyscanner);
mzn_yyset_extra(&pp, pp.yyscanner);
mzn_yyparse(&pp);

View File

@ -395,20 +395,20 @@ error_item_start : MZN_INCLUDE | MZN_ENUM | MZN_OUTPUT
include_item :
MZN_INCLUDE MZN_STRING_LITERAL
{ ParserState* pp = static_cast<ParserState*>(parm);
string canonicalName=pp->canonicalFilename($2);
map<string,Model*>::iterator ret = pp->seenModels.find(canonicalName);
map<string,Model*>::iterator ret = pp->seenModels.find($2);
IncludeI* ii = new IncludeI(@$,ASTString($2));
$$ = ii;
if (ret == pp->seenModels.end()) {
Model* im = new Model;
im->setParent(pp->model);
im->setFilename(canonicalName);
im->setFilename($2);
string fpath = FileUtils::dir_name(pp->filename);
string fbase = FileUtils::base_name(pp->filename);
if (fpath=="")
fpath="./";
pp->files.emplace_back(im, ii, fpath, canonicalName, pp->isSTDLib);
pp->files.emplace_back(im, ii, fpath, $2, pp->isSTDLib);
ii->m(im);
pp->seenModels.insert(pair<string,Model*>(canonicalName,im));
pp->seenModels.insert(pair<string,Model*>($2,im));
} else {
ii->m(ret->second, false);
}

View File

@ -33,20 +33,6 @@ namespace MiniZinc {
using std::string;
using std::vector;
ASTString strip_stdlib_path(const vector<string>& includePaths, const ASTString& fs) {
std::string f(fs.c_str());
for (const auto& p : includePaths) {
if (f.size() > p.size() && f.substr(0, p.size()) == p) {
f = f.substr(p.size());
while (!f.empty() && f[0] == '/') {
f = f.substr(1);
}
return ASTString(f);
}
}
return fs;
}
Env* change_library(Env& e, vector<string>& includePaths, const string& globals_dir,
CompilePassFlags& compflags, bool verbose = false) {
GCLock lock;
@ -67,11 +53,7 @@ Env* change_library(Env& e, vector<string>& includePaths, const string& globals_
vector<ASTString> include_names;
for (Item* item : *m) {
if (auto* inc = item->dynamicCast<IncludeI>()) {
if (FileUtils::is_absolute(inc->f().c_str())) {
include_names.push_back(inc->f());
} else {
include_names.push_back(strip_stdlib_path(new_includePaths, inc->m()->filepath()));
}
include_names.push_back(inc->m()->filepath());
} else {
new_mod->addItem(copy(e.envi(), cm, item));
}

View File

@ -657,7 +657,7 @@ public:
}
switch (i->iid()) {
case Item::II_INC:
_os << "include \"" << Printer::escapeStringLit(i->cast<IncludeI>()->f()) << "\"";
_os << "include \"" << i->cast<IncludeI>()->f() << "\"";
break;
case Item::II_VD:
p(i->cast<VarDeclI>()->e());
@ -1648,7 +1648,7 @@ public:
typedef Document* ret;
static ret mapIncludeI(const IncludeI& ii) {
std::ostringstream oss;
oss << "include \"" << Printer::escapeStringLit(ii.f()) << "\";";
oss << "include \"" << ii.f() << "\";";
return new StringDocument(oss.str());
}
static ret mapVarDeclI(const VarDeclI& vi) {

View File

@ -18,7 +18,7 @@
namespace MiniZinc {
SolverInstanceBase::Status SolverInstanceBase::solve() { return SolverInstanceError; }
SolverInstanceBase::Status SolverInstanceBase::solve() { return SolverInstance__ERROR; }
void SolverInstanceBase::reset() { assert(false); }

View File

@ -154,45 +154,10 @@ public:
}
};
// Create all required mapping functions for a new enum
// (mapping enum identifiers to strings, and mapping between different enums)
void create_enum_mapper(EnvI& env, Model* m, unsigned int enumId, VarDecl* vd, Model* enumItems) {
GCLock lock;
Id* ident = vd->id();
if (vd->e() == nullptr) {
// Enum without right hand side (may be supplied later in an assignment
// item, or we may be runnint in --model-interface-only mode).
// Need to create stub function declarations, so that the type checker
// is happy.
Type tx = Type::parint();
tx.ot(Type::OT_OPTIONAL);
auto* ti_aa = new TypeInst(Location().introduce(), tx);
auto* vd_aa = new VarDecl(Location().introduce(), ti_aa, "x");
vd_aa->toplevel(false);
auto* ti_ab = new TypeInst(Location().introduce(), Type::parbool());
auto* vd_ab = new VarDecl(Location().introduce(), ti_ab, "b");
vd_ab->toplevel(false);
auto* ti_aj = new TypeInst(Location().introduce(), Type::parbool());
auto* vd_aj = new VarDecl(Location().introduce(), ti_aj, "json");
vd_aj->toplevel(false);
auto* ti_fi = new TypeInst(Location().introduce(), Type::parstring());
std::vector<VarDecl*> fi_params(3);
fi_params[0] = vd_aa;
fi_params[1] = vd_ab;
fi_params[2] = vd_aj;
auto* fi =
new FunctionI(Location().introduce(), create_enum_to_string_name(ident, "_toString_"),
ti_fi, fi_params, nullptr);
enumItems->addItem(fi);
return;
}
Call* c = vd->e()->dynamicCast<Call>();
auto* al = vd->e()->dynamicCast<ArrayLit>();
@ -796,14 +761,7 @@ void create_enum_mapper(EnvI& env, Model* m, unsigned int enumId, VarDecl* vd, M
}
// Create set literal for overall enum
Expression* upperBound;
if (!partCardinality.empty()) {
upperBound = partCardinality.back();
} else {
// For empty enums, just create 1..0.
upperBound = IntLit::a(0);
}
auto* rhs = new BinOp(vd->loc(), IntLit::a(1), BOT_DOTDOT, upperBound);
auto* rhs = new BinOp(vd->loc(), IntLit::a(1), BOT_DOTDOT, partCardinality.back());
vd->e(rhs);
if (parts.size() > 1) {
@ -1162,7 +1120,9 @@ void TopoSorter::add(EnvI& env, VarDeclI* vdi, bool handleEnums, Model* enumItem
vd->ti()->type(vdt);
vd->type(vdt);
create_enum_mapper(env, model, enumId, vd, enumItems);
if (vd->e() != nullptr) {
create_enum_mapper(env, model, enumId, vd, enumItems);
}
}
scopes.add(env, vd);
}
@ -1488,7 +1448,7 @@ KeepAlive add_coercion(EnvI& env, Model* m, Expression* e, const Type& funarg_t)
FunctionI* fi = m->matchFn(env, c, false);
assert(fi);
Type ct = fi->rtype(env, args, false);
ct.cv(e->type().cv() || ct.cv());
ct.cv(e->type().cv());
c->type(ct);
c->decl(fi);
KeepAlive ka(c);
@ -2143,7 +2103,7 @@ public:
args[0] = bop.lhs();
args[1] = bop.rhs();
Type ty = fi->rtype(_env, args, true);
ty.cv(bop.lhs()->type().cv() || bop.rhs()->type().cv() || ty.cv());
ty.cv(bop.lhs()->type().cv() || bop.rhs()->type().cv());
bop.type(ty);
if (fi->e() != nullptr) {
@ -2292,7 +2252,7 @@ public:
uop.e(add_coercion(_env, _model, uop.e(), fi->argtype(_env, args, 0))());
args[0] = uop.e();
Type ty = fi->rtype(_env, args, true);
ty.cv(uop.e()->type().cv() || ty.cv());
ty.cv(uop.e()->type().cv());
uop.type(ty);
if (fi->e() != nullptr) {
uop.decl(fi);
@ -2420,7 +2380,7 @@ public:
// Set type and decl
Type ty = fi->rtype(_env, args, true);
ty.cv(cv || ty.cv());
ty.cv(cv);
call.type(ty);
if (Call* deprecated = fi->ann().getCall(constants().ann.mzn_deprecated)) {
@ -2476,7 +2436,7 @@ public:
isVar |= li->type().isvar();
}
Type ty = let.in()->type();
ty.cv(cv || ty.cv());
ty.cv(cv);
if (isVar && ty.bt() == Type::BT_BOOL && ty.dim() == 0) {
ty.ti(Type::TI_VAR);
}
@ -2952,13 +2912,6 @@ void typecheck(Env& env, Model* origModel, std::vector<TypeError>& typeErrors,
_bottomUpTyper.run(i->e());
if (i->e() != nullptr) {
Type et = i->e()->type();
if (et.isbool()) {
Type target_t = Type::varint();
if (et.isOpt()) {
target_t.ot(Type::OT_OPTIONAL);
}
i->e(add_coercion(_env, _env.model, i->e(), target_t)());
}
bool needOptCoercion = et.isOpt() && et.isint();
if (needOptCoercion) {
@ -3180,34 +3133,10 @@ void typecheck(Env& env, Model* origModel, std::vector<TypeError>& typeErrors,
} while (didRemove);
// Create par versions of remaining functions
if (!fnsToMakePar.empty()) {
{
// First step: copy and register functions
std::vector<FunctionI*> parFunctions;
CopyMap parCopyMap;
// Step 1a: enter all global declarations into copy map
class EnterGlobalDecls : public EVisitor {
public:
CopyMap& cm;
EnterGlobalDecls(CopyMap& cm0) : cm(cm0) {}
void vId(Id& ident) {
if (ident.decl() != nullptr && ident.decl()->toplevel()) {
cm.insert(ident.decl(), ident.decl());
}
}
} _egd(parCopyMap);
for (auto& p : fnsToMakePar) {
if (!p.second.first) {
for (auto* param : p.first->params()) {
top_down(_egd, param);
}
for (ExpressionSetIter i = p.first->ann().begin(); i != p.first->ann().end(); ++i) {
top_down(_egd, *i);
}
top_down(_egd, p.first->e());
}
}
// Step 1b: copy functions
for (auto& p : fnsToMakePar) {
if (!p.second.first) {
GCLock lock;
@ -3574,7 +3503,7 @@ void output_model_interface(Env& env, Model* m, std::ostream& os,
os << ",\n \"method\": \"";
os << _ifc.method;
os << "\"";
os << ",\n \"has_output_item\": " << (_ifc.outputItem ? "true" : "false");
os << ",\n \"has_outputItem\": " << (_ifc.outputItem ? "true" : "false");
os << ",\n \"included_files\": [\n" << _ifc.ossIncludedFiles.str() << "\n ]";
os << "\n}\n";
}

View File

@ -5,10 +5,8 @@
"solverDefaults" : [
["org.minizinc.mip.gurobi", "-DQuadrIntSolverConfig=true", ""],
["org.minizinc.mip.gurobi", "-DQuadrFloatSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DQuadrIntSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DQuadrFloatSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DCumulativeSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DOrbisackSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DOrbitopeSolverConfig=true", ""]
["org.minizinc.mip.scip", "-DQuadrIntSolverConfig=true", ""],
["org.minizinc.mip.scip", "-DQuadrFloatSolverConfig=true", ""]
]
}

View File

@ -1,4 +0,0 @@
include "fzn_lex_chain_lesseq_int.mzn";
predicate fzn_lex_chain_lesseq_bool(array[int, int] of var bool: a) =
fzn_lex_chain_lesseq_int(a);

View File

@ -1,23 +0,0 @@
include "lex_lesseq.mzn";
include "fzn_lex_chain_lesseq_orbitope.mzn";
predicate fzn_lex_chain_lesseq_int(array[int, int] of var int: a) =
if MZN__Orbitope /\ dom_array(a) subset 0..1 then
fzn_lex_chain_lesseq__orbitope( a,
card(index_set_1of2(a)), 0, true,
not mzn_in_symmetry_breaking_constraint()
)
else
fzn_lex_chain_lesseq_int__CP(a)
endif;
predicate fzn_lex_chain_lesseq_int__CP(array[int, int] of var int: a) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
);

View File

@ -1,40 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_orbitope(
array[int, int] of var int: a, int: kind) =
if MZN__Orbitope then
fzn_lex_chain_lesseq__orbitope( a,
card(index_set_1of2(a)), kind, true,
not mzn_in_symmetry_breaking_constraint()
)
else
fzn_lex_chain_lesseq_orbitope__CP(a, kind)
endif;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SCIP 7.0.2, binary matrix, columns sorted
predicate fzn_lex_chain_lesseq__orbitope(array[int, int] of var int: matr,
int: m, int: orbType, bool: resolveprop, bool: isModelCons);
predicate fzn_lex_chain_lesseq_orbitope__CP(
array[int, int] of var int: a, int: kind) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
/\
if 1==kind then
forall(i in index_set_1of2(a))(
1 == sum(row(a, i))
)
elseif 2==kind then
forall(i in index_set_1of2(a))(
1 >= sum(row(a, i))
)
else true
endif
);

View File

@ -1,12 +0,0 @@
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is strictly lexicographically less than
% array 'y'. Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
include "fzn_lex_less_int.mzn";
predicate fzn_lex_less_bool(array[int] of var bool: x,
array[int] of var bool: y) =
fzn_lex_less_int(x, y);
%-----------------------------------------------------------------------------%

View File

@ -0,0 +1,21 @@
include "../std/fzn_lex_less_bool_reif.mzn";
predicate fzn_lex_less_bool_imp(array[int] of var bool: x,
array[int] of var bool: y,
var bool: c) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = max(ux - lx, uy - ly),
array[0..size+1] of var bool: b }
in
(c -> b[0])
/\
forall(i in 0..size) (
b[i] = ( x[lx + i] <= y[ly + i]
/\
(x[lx + i] < y[ly + i] \/ b[i+1]) )
)
/\
b[size + 1] = (ux - lx < uy - ly);

View File

@ -1,38 +0,0 @@
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is strictly lexicographically less than
% array 'y'. Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
predicate fzn_lex_less_float(array[int] of var float: x,
array[int] of var float: y) =
assert(length(x) == length(y),
"lex_less_float(\(x), \(y)): arrays of different lengths")
/\
fzn_lex_less_float__MIP(x, y);
predicate fzn_lex_less_float__MIP(array[int] of var float: x,
array[int] of var float: y) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size] of var 0..1: fEQ;
array[0..size] of var 0..1: fLT;
} in
sum(fLT) == 1
/\
fEQ[0] + fLT[0] == 1
/\
forall(i in 1..size) (
fEQ[i-1] == fEQ[i] + fLT[i]
)
/\
forall(i in 0..size) (
aux_float_eq_if_1(x[lx+i], y[ly+i], fEQ[i])
/\
aux_float_lt_if_1(x[lx+i], y[ly+i], fLT[i])
)
;
%-----------------------------------------------------------------------------%

View File

@ -1,39 +0,0 @@
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is strictly lexicographically less than array 'y'.
% Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
predicate fzn_lex_less_int(array[int] of var int: x,
array[int] of var int: y) =
assert(length(x) == length(y),
"lex_less_int(\(x), \(y)): arrays of different lengths")
/\
fzn_lex_less_int__MIP(x, y)
;
predicate fzn_lex_less_int__MIP(array[int] of var int: x,
array[int] of var int: y) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size] of var 0..1: fEQ;
array[0..size] of var 0..1: fLT;
} in
sum(fLT) == 1
/\
fEQ[0] + fLT[0] == 1
/\
forall(i in 1..size) (
fEQ[i-1] == fEQ[i] + fLT[i]
)
/\
forall(i in 0..size) (
aux_int_eq_if_1(x[lx+i], y[ly+i], fEQ[i])
/\
aux_int_lt_if_1(x[lx+i], y[ly+i], fLT[i])
)
;
%-----------------------------------------------------------------------------%

View File

@ -3,10 +3,47 @@
% array 'y'. Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
include "fzn_lex_lesseq_int.mzn";
predicate fzn_lex_lesseq_bool(array[int] of var bool: x,
array[int] of var bool: y) =
fzn_lex_lesseq_int(x, y);
% if (min(card(index_set(x)), card(index_set(y))) <= 25) then
% let { int: size = min(card(index_set(x)), card(index_set(y)));
% } in
% sum(i in 0..size-1)(pow(2, (size-1-i)) * bool2int(x[i+min(index_set(x))]))
% <= sum(i in 0..size-1)(pow(2, (size-1-i)) * bool2int(y[i+min(index_set(y))]))
% else
% my_trace ("lex_lesseq_bool(\(x), \(y))") /\
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size+1] of var bool: b }
% b[i] is true if the lexicographical order holds from position i on.
in
b[0]
/\
forall(i in 0..size) (
b[i] -> ( ( ( x[lx + i] <= y[ly + i] ) ) /\
% bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) <= 2 /\
% ( b[i] ->
( x[lx + i] < y[ly + i] \/ b[i+1] ) )
% /\ ( bool2int(b[i]) <= bool2int(x[lx + i] < y[ly + i]) + bool2int(b[i+1]) ) /\
% bool2int(b[i]) + (1-bool2int(x[lx + i])) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
% /\ bool2int(b[i]) + bool2int(x[lx + i]) + bool2int(y[ly + i]) + (1-bool2int(b[i+1])) <= 3
%% This guy is dominated by the 1st one above but helps:
% /\ bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
)
/\ b[size+1] = (ux-lx <= uy-ly)
% endif
;
% forall(i in 0..size) (
% ( b[i] == ( x[lx + i] <= y[ly + i] ) )
% /\
% if i < size then
% ( b[i] == ( x[lx + i] < y[ly + i] \/ b[i+1]
% ) ) else true endif
% );
%-----------------------------------------------------------------------------%

View File

@ -0,0 +1,50 @@
predicate fzn_lex_lesseq_bool_reif(array[int] of var bool: x,
array[int] of var bool: y,
var bool: c) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = max(ux - lx, uy - ly),
array[0..size+1] of var bool: b }
% b[i] is true if the lexicographical order holds from position i on.
in
(c <-> b[0])
/\
forall(i in 0..size) (
( b[i] -> ( x[lx + i] <= y[ly + i] ) ) /\
bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) <= 2
/\
( b[i] -> ( x[lx + i] < y[ly + i] \/ b[i+1] ) ) /\
bool2int(b[i]) + (1-bool2int(x[lx + i])) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
/\ bool2int(b[i]) + bool2int(x[lx + i]) + bool2int(y[ly + i]) + (1-bool2int(b[i+1])) <= 3
/\ bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
)
/\ b[size+1] = (ux-lx <= uy-ly)
% endif
;
predicate fzn_lex_lesseq_bool_imp(array[int] of var bool: x,
array[int] of var bool: y,
var bool: c) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = max(ux - lx, uy - ly),
array[0..size+1] of var bool: b }
% b[i] is true if the lexicographical order holds from position i on.
in
(c -> b[0])
/\
forall(i in 0..size) (
( b[i] -> ( x[lx + i] <= y[ly + i] ) ) /\
bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) <= 2
/\
( b[i] -> ( x[lx + i] < y[ly + i] \/ b[i+1] ) ) /\
bool2int(b[i]) + (1-bool2int(x[lx + i])) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
/\ bool2int(b[i]) + bool2int(x[lx + i]) + bool2int(y[ly + i]) + (1-bool2int(b[i+1])) <= 3
/\ bool2int(b[i]) + bool2int(x[lx + i]) + (1-bool2int(y[ly + i])) + (1-bool2int(b[i+1])) <= 3
)
/\ b[size+1] = (ux-lx <= uy-ly)
;

View File

@ -1,38 +0,0 @@
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is lexicographically less than or equal to
% array 'y'. Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
predicate fzn_lex_lesseq_float(array[int] of var float: x,
array[int] of var float: y) =
assert(length(x) == length(y), %% SCIP cannot
"lex_lesseq_float(\(x), \(y)): arrays of different lengths")
/\
fzn_lex_lesseq_float__MIP(x, y);
predicate fzn_lex_lesseq_float__MIP(array[int] of var float: x,
array[int] of var float: y) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size] of var 0..1: fEQ;
array[0..size] of var 0..1: fLT;
} in
sum(fLT) <= 1
/\
fEQ[0] + fLT[0] == 1
/\
forall(i in 1..size) (
fEQ[i-1] == fEQ[i] + fLT[i]
)
/\
forall(i in 0..size) (
aux_float_eq_if_1(x[lx+i], y[ly+i], fEQ[i])
/\
aux_float_lt_if_1(x[lx+i], y[ly+i], fLT[i])
)
;
%-----------------------------------------------------------------------------%

View File

@ -1,77 +0,0 @@
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is lexicographically less than or equal to
% array 'y'. Compares them from first to last element, regardless of indices
%-----------------------------------------------------------------------------%
opt bool: UseCPLexLesseq; %% When not UseOrbisack, use CP decomposition
opt bool: OrbisackAlwaysModelConstraint; %% Use with SCIP 7.0.2
predicate fzn_lex_lesseq_int(array[int] of var int: x,
array[int] of var int: y) =
assert(length(x) == length(y), %% SCIP cannot
"lex_lesseq_int(\(x), \(y)): arrays of different lengths")
/\
if MZN__Orbisack /\
dom_array(x) subset 0..1 /\ dom_array(y) subset 0..1 then
fzn_lex_lesseq__orbisack(x, y,
( occurs(OrbisackAlwaysModelConstraint) /\
deopt(OrbisackAlwaysModelConstraint) ) \/
not mzn_in_symmetry_breaking_constraint())
elseif occurs(UseCPLexLesseq) /\ deopt(UseCPLexLesseq) then
fzn_lex_lesseq_int__CP(x, y)
else
fzn_lex_lesseq_int__MIP(x, y)
endif;
predicate fzn_lex_lesseq_int__CP(array[int] of var int: x,
array[int] of var int: y) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size+1] of var bool: b }
% b[i] is true if the lexicographical order holds from position i on.
in
b[0]
/\
forall(i in 0..size) (
b[i] = ( x[lx + i] <= y[ly + i]
/\
(x[lx + i] < y[ly + i] \/ b[i+1])
)
)
/\
b[size + 1] = (ux - lx <= uy - ly)
;
predicate fzn_lex_lesseq_int__MIP(array[int] of var int: x,
array[int] of var int: y) =
let { int: lx = min(index_set(x)),
int: ux = max(index_set(x)),
int: ly = min(index_set(y)),
int: uy = max(index_set(y)),
int: size = min(ux - lx, uy - ly),
array[0..size] of var 0..1: fEQ;
array[0..size] of var 0..1: fLT;
} in
sum(fLT) <= 1
/\
fEQ[0] + fLT[0] == 1
/\
forall(i in 1..size) (
fEQ[i-1] == fEQ[i] + fLT[i]
)
/\
forall(i in 0..size) (
aux_int_eq_if_1(x[lx+i], y[ly+i], fEQ[i])
/\
aux_int_lt_if_1(x[lx+i], y[ly+i], fLT[i])
)
;
%% SCIP constraint handler orbisack
predicate fzn_lex_lesseq__orbisack(
array[int] of var int: vec1, array[int] of var int: vec2, bool: isModelCons);
%-----------------------------------------------------------------------------%

View File

@ -40,25 +40,11 @@ bool: MZN__MinMaxGeneral = if absent(MinMaxGeneral) then false else deopt(MinMax
%% CUMULATIVE
opt bool: CumulativeSolverConfig; %% As set in share/minizinc/Preferences.json
opt bool: UseCumulative; %% User option, e.g., with -D
bool: MZN__Cumulative_Fixed_d_r = if occurs(UseCumulative) then deopt(UseCumulative)
opt bool: Cumulative; %% User option, e.g., with -D
bool: MZN__Cumulative_Fixed_d_r = if occurs(Cumulative) then deopt(Cumulative)
elseif occurs(CumulativeSolverConfig) then deopt(CumulativeSolverConfig)
else false endif;
%% ORBISACK
opt bool: OrbisackSolverConfig; %% As set in share/minizinc/Preferences.json
opt bool: UseOrbisack; %% User option, e.g., with -D
bool: MZN__Orbisack = if occurs(UseOrbisack) then deopt(UseOrbisack)
elseif occurs(OrbisackSolverConfig) then deopt(OrbisackSolverConfig)
else false endif;
%% ORBITOPE
opt bool: OrbitopeSolverConfig; %% As set in share/minizinc/Preferences.json
opt bool: UseOrbitope; %% User option, e.g., with -D
bool: MZN__Orbitope = if occurs(UseOrbitope) then deopt(UseOrbitope)
elseif occurs(OrbitopeSolverConfig) then deopt(OrbitopeSolverConfig)
else false endif;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Quadratic expressions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% --------------------------------------------------------------------------------------- %

View File

@ -1,10 +1,21 @@
include "lex_chain_lesseq.mzn";
include "lex_lesseq.mzn";
predicate fzn_lex2(array[int, int] of var int: x) =
lex_chain_lesseq(x)
/\
lex_chain_lesseq( %% transpose
array2d(index_set_2of2(x), index_set_1of2(x),
[x[i, j] | j in index_set_2of2(x), i in index_set_1of2(x)]
let {
int: lbx1 = min(index_set_1of2(x)),
int: ubx1 = max(index_set_1of2(x)),
int: lbx2 = min(index_set_2of2(x)),
int: ubx2 = max(index_set_2of2(x))
} in (
forall(i in lbx1 + 1 .. ubx1) (
lex_lesseq([x[i - 1, j] | j in index_set_2of2(x)],
[x[i, j] | j in index_set_2of2(x)]
)
)
/\
forall(j in lbx2 + 1 .. ubx2) (
lex_lesseq([x[i, j - 1] | i in index_set_1of2(x)],
[x[i, j ] | i in index_set_1of2(x)]
)
)
);

View File

@ -1,12 +1,21 @@
include "lex_lesseq.mzn";
predicate fzn_lex2_reif(array[int, int] of var int: x, var bool: b) =
b <-> (
lex_chain_lesseq(x)
let {
int: lbx1 = min(index_set_1of2(x)),
int: ubx1 = max(index_set_1of2(x)),
int: lbx2 = min(index_set_2of2(x)),
int: ubx2 = max(index_set_2of2(x))
} in b <-> (
forall(i in lbx1 + 1 .. ubx1) (
lex_lesseq([x[i - 1, j] | j in index_set_2of2(x)],
[x[i, j] | j in index_set_2of2(x)]
)
)
/\
lex_chain_lesseq( %% transpose
array2d(index_set_2of2(x), index_set_1of2(x),
[x[i, j] | j in index_set_2of2(x), i in index_set_1of2(x)]
forall(j in lbx2 + 1 .. ubx2) (
lex_lesseq([x[i, j - 1] | i in index_set_1of2(x)],
[x[i, j ] | i in index_set_1of2(x)]
)
)
);

View File

@ -1,11 +0,0 @@
include "lex_less.mzn";
predicate fzn_lex_chain_less_bool(array[int, int] of var bool: a) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_less(col(a, j-1), col(a, j))
)
);

View File

@ -1,12 +0,0 @@
include "lex_less.mzn";
predicate fzn_lex_chain_less_bool_reif(
array[int, int] of var bool: a, var bool: b) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in b <-> (
forall(j in lb2 + 1 .. ub2) (
lex_less(col(a, j-1), col(a, j))
)
);

View File

@ -1,11 +0,0 @@
include "lex_less.mzn";
predicate fzn_lex_chain_less_int(array[int, int] of var int: a) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_less(col(a, j-1), col(a, j))
)
);

View File

@ -1,12 +0,0 @@
include "lex_less.mzn";
predicate fzn_lex_chain_less_int_reif(
array[int, int] of var int: a, var bool: b) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in b <-> (
forall(j in lb2 + 1 .. ub2) (
lex_less(col(a, j-1), col(a, j))
)
);

View File

@ -1,11 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_bool(array[int, int] of var bool: a) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
);

View File

@ -1,12 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_bool_reif(
array[int, int] of var bool: a, var bool: b) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in b <-> (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
);

View File

@ -1,11 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_int(array[int, int] of var int: a) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
);

View File

@ -1,12 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_int_reif(
array[int, int] of var int: a, var bool: b) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in b <-> (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
);

View File

@ -1,23 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_orbitope(
array[int, int] of var int: a, int: kind) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
/\
if 1==kind then
forall(i in index_set_1of2(a))(
1 == sum(row(a, i))
)
elseif 2==kind then
forall(i in index_set_1of2(a))(
1 >= sum(row(a, i))
)
else true
endif
);

View File

@ -1,23 +0,0 @@
include "lex_lesseq.mzn";
predicate fzn_lex_chain_lesseq_orbitope_reif(
array[int, int] of var int: a, int: kind, var bool: b) =
let {
int: lb2 = min(index_set_2of2(a)),
int: ub2 = max(index_set_2of2(a))
} in b <-> (
forall(j in lb2 + 1 .. ub2) (
lex_lesseq(col(a, j-1), col(a, j))
)
/\
if 1==kind then
forall(i in index_set_1of2(a))(
1 == sum(row(a, i))
)
elseif 2==kind then
forall(i in index_set_1of2(a))(
1 >= sum(row(a, i))
)
else true
endif
);

View File

@ -1,9 +1,8 @@
/*
* Function fzn_piecewise_linear_base creates
* auxiliary variables for the interval representation of xi
* and constrains them to correspond to the value of x.
* The auxiliaries are reusable if we have several pwls
* on the same set of breakpoints and x.
* interval representation of x,
* which is reusable if we have several pwls
* on the same set of breakpoints
*/
function array[int, int] of var 0.0..1.0: fzn_piecewise_linear_base(
var float: x, array[int] of float: xi) ::promise_total =

View File

@ -1,37 +0,0 @@
/*
* Function fzn_piecewise_linear_base creates
* auxiliary variables for the intervals {x_start[i]..x_end[i]},
* and constrains them to correspond to the value of x.
* The auxiliaries are reusable if we have several pwls
* on the same set of intervals and x.
*/
function array[int, int] of var 0.0..1.0: fzn_piecewise_linear_base(var float: x,
array[int] of float: x_start, array[int] of float: x_end) ::promise_total =
let {
set of int: is = index_set(x_start),
array[is] of var 0.0..1.0: s, %% Segment variables
array[is] of var 0..1: f,
constraint 1 == sum(f),
constraint forall(i in is)(
if x_start[i] < x_end[i] then f[i] >= s[i]
elseif x_start[i] == x_end[i] then s[i] == 0.0
else abort("piecewise linear discontinuous: interval \(i): x_end < x_start") endif),
constraint x == sum(i in is)(x_start[i] * f[i] + (x_end[i]-x_start[i]) * s[i]),
} in
array2d(1..2, is, f++s);
predicate fzn_piecewise_linear(var float: x, var float: y,
array[int] of float: x_start, array[int] of float: x_end,
array[int] of float: v_start, array[int] of float: v_end) =
let {
set of int: is = index_set(x_start),
constraint assert(is == index_set(v_start)
/\ is == index_set(v_end) /\ is == index_set(x_end) /\ 0<card(is) ,
"fzn_pwl: index sets unequal or empty"),
array[int, int] of var float: fs = fzn_piecewise_linear_base(x, x_start,x_end),
} in
y == sum(i in is)(v_start[i] * fs[1, i] + (v_end[i]-v_start[i]) * fs[2, i]);
%-----------------------------------------------------------------------------%

View File

@ -1,7 +0,0 @@
predicate fzn_piecewise_linear_reif(var float: x, var float: y,
array[int] of float: xi1, array[int] of float: xi2,
array[int] of float: vi1, array[int] of float: vi2,
var bool: b) =
abort("Reified piecewise_linear (non_continuous) constraint is not supported");
%-----------------------------------------------------------------------------%

View File

@ -1,10 +1,22 @@
include "lex_chain_less.mzn";
include "lex_less.mzn";
predicate fzn_strict_lex2(array[int, int] of var int: x) =
lex_chain_less(x)
/\
lex_chain_less( %% transpose
array2d(index_set_2of2(x), index_set_1of2(x),
[x[i, j] | j in index_set_2of2(x), i in index_set_1of2(x)]
let {
int: lbx1 = min(index_set_1of2(x)),
int: ubx1 = max(index_set_1of2(x)),
int: lbx2 = min(index_set_2of2(x)),
int: ubx2 = max(index_set_2of2(x))
} in (
forall(i in lbx1 + 1 .. ubx1) (
lex_less([x[i - 1, j] | j in index_set_2of2(x)],
[x[i, j] | j in index_set_2of2(x)]
)
)
/\
forall(j in lbx2 + 1 .. ubx2) (
lex_less([x[i, j - 1] | i in index_set_1of2(x)],
[x[i, j ] | i in index_set_1of2(x)]
)
)
);

View File

@ -1,12 +1,22 @@
include "lex_chain_less.mzn";
include "lex_less.mzn";
predicate fzn_strict_lex2_reif(array[int, int] of var int: x, var bool: b) =
b <-> (
lex_chain_less(x)
let {
int: lbx1 = min(index_set_1of2(x)),
int: ubx1 = max(index_set_1of2(x)),
int: lbx2 = min(index_set_2of2(x)),
int: ubx2 = max(index_set_2of2(x))
} in b <-> (
forall(i in lbx1 + 1 .. ubx1) (
lex_less([x[i - 1, j] | j in index_set_2of2(x)],
[x[i, j] | j in index_set_2of2(x)]
)
)
/\
lex_chain_less( %% transpose
array2d(index_set_2of2(x), index_set_1of2(x),
[x[i, j] | j in index_set_2of2(x), i in index_set_1of2(x)]
forall(j in lbx2 + 1 .. ubx2) (
lex_less([x[i, j - 1] | i in index_set_1of2(x)],
[x[i, j ] | i in index_set_1of2(x)]
)
)
);

View File

@ -1,8 +0,0 @@
include "fzn_strictly_increasing_int_opt.mzn";
%-----------------------------------------------------------------------------%
% Requires that the array 'x' is in strict decreasing order
%-----------------------------------------------------------------------------%
predicate fzn_strictly_decreasing_int_opt(array[int] of var opt int: x) =
fzn_strictly_increasing_int_opt(reverse(x));

View File

@ -93,18 +93,11 @@ include "inverse_fn.mzn";
include "inverse_in_range.mzn";
include "inverse_set.mzn";
include "knapsack.mzn";
include "lex_greatereq.mzn";
include "lex_greater.mzn";
include "lex_greatereq.mzn";
include "lex_lesseq.mzn";
include "lex_less.mzn";
include "lex_chain_lesseq.mzn";
include "lex_chain_greatereq.mzn";
include "lex_chain_lesseq_orbitope.mzn";
include "lex_chain_greatereq_orbitope.mzn";
include "lex_chain_less.mzn";
include "lex_chain_greater.mzn";
include "lex2.mzn";
include "lex2_strict.mzn";
include "link_set_to_booleans.mzn";
include "maximum.mzn";
include "mdd.mzn";

View File

@ -1,8 +0,0 @@
include "strict_lex2.mzn";
/** @group globals.lexicographic
Require adjacent rows and adjacent columns in the array \a x to be
lexicographically ordered. Adjacent rows and adjacent columns cannot be equal.
*/
predicate lex2_strict(array[int, int] of var int: x) =
strict_lex2(x);

View File

@ -1,28 +0,0 @@
include "lex_chain_less.mzn";
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
strictly decreasing.
*/
predicate lex_chain_greater(array[int, int] of var bool: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_less(
array2d( index_set_1of2(a), index_set_2of2(a),
[a[i, max(index_set_2of2(a)) - j + min(index_set_2of2(a))] |
i in index_set_1of2(a), j in index_set_2of2(a)]
)
) endif;
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
strictly decreasing.
*/
predicate lex_chain_greater(array[int, int] of var int: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_less(
array2d( index_set_1of2(a), index_set_2of2(a),
[a[i, max(index_set_2of2(a)) - j + min(index_set_2of2(a))] |
i in index_set_1of2(a), j in index_set_2of2(a)]
)
) endif;

View File

@ -1,28 +0,0 @@
include "lex_chain_lesseq.mzn";
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-increasing.
*/
predicate lex_chain_greatereq(array[int, int] of var bool: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_lesseq(
array2d( index_set_1of2(a), index_set_2of2(a),
[a[i, max(index_set_2of2(a)) - j + min(index_set_2of2(a))] |
i in index_set_1of2(a), j in index_set_2of2(a)]
)
) endif;
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-increasing.
*/
predicate lex_chain_greatereq(array[int, int] of var int: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_lesseq(
array2d( index_set_1of2(a), index_set_2of2(a),
[a[i, max(index_set_2of2(a)) - j + min(index_set_2of2(a))] |
i in index_set_1of2(a), j in index_set_2of2(a)]
)
) endif;

View File

@ -1,19 +0,0 @@
include "lex_chain_lesseq_orbitope.mzn";
/** @group globals.lexicographic
Requires that the columns of binary matrix \a a are
lexicographically sorted, non-increasing.
Moreover, the second parameter has the following meaning:
0: no further constraints, 1: set-partitioning orbitope,
2: set-packing orbitope
*/
predicate lex_chain_greatereq_orbitope(
array[int, int] of var int: a, int: kind) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_lesseq_orbitope(
array2d( index_set_1of2(a), index_set_2of2(a),
[a[i, max(index_set_2of2(a)) - j + min(index_set_2of2(a))] |
i in index_set_1of2(a), j in index_set_2of2(a)]
),
kind) endif;

View File

@ -1,19 +0,0 @@
include "lex_chain_less_bool.mzn";
include "lex_chain_less_int.mzn";
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
strictly increasing.
*/
predicate lex_chain_less(array[int, int] of var bool: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_less_bool(a) endif;
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-decreasing.
*/
predicate lex_chain_less(array[int, int] of var int: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_less_int(a) endif;

View File

@ -1,12 +0,0 @@
include "fzn_lex_chain_less_bool.mzn";
include "fzn_lex_chain_less_bool_reif.mzn";
%-----------------------------------------------------------------------------%
% Requires that the columns of matrix \a a are lexicographically sorted,
% strictly increasing.
%-----------------------------------------------------------------------------%
predicate lex_chain_less_bool(array[int, int] of var bool: a) =
fzn_lex_chain_less_bool(a);
%-----------------------------------------------------------------------------%

View File

@ -1,12 +0,0 @@
include "fzn_lex_chain_less_int.mzn";
include "fzn_lex_chain_less_int_reif.mzn";
%-----------------------------------------------------------------------------%
% Requires that the columns of matrix \a a are lexicographically sorted,
% strictly increasing.
%-----------------------------------------------------------------------------%
predicate lex_chain_less_int(array[int, int] of var int: a) =
fzn_lex_chain_less_int(a);
%-----------------------------------------------------------------------------%

View File

@ -1,33 +0,0 @@
include "lex_chain_lesseq_bool.mzn";
include "lex_chain_lesseq_int.mzn";
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-decreasing.
*/
predicate lex_chain_lesseq(array[int, int] of var bool: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_lesseq_bool(a) endif;
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-decreasing.
*/
predicate lex_chain_lesseq(array[int, int] of var int: a) =
if 1>=card(index_set_2of2(a)) then true
else lex_chain_lesseq_int(a) endif;
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-decreasing.
*/
predicate lex_chain(array[int, int] of var bool: a) =
lex_chain_lesseq(a);
/** @group globals.lexicographic
Requires that the columns of matrix \a a are lexicographically sorted,
non-decreasing.
*/
predicate lex_chain(array[int, int] of var int: a) =
lex_chain_lesseq(a);

View File

@ -1,12 +0,0 @@
include "fzn_lex_chain_lesseq_bool.mzn";
include "fzn_lex_chain_lesseq_bool_reif.mzn";
%-----------------------------------------------------------------------------%
% Requires that the columns of matrix \a a are lexicographically sorted,
% non-decreasing.
%-----------------------------------------------------------------------------%
predicate lex_chain_lesseq_bool(array[int, int] of var bool: a) =
fzn_lex_chain_lesseq_bool(a);
%-----------------------------------------------------------------------------%

View File

@ -1,12 +0,0 @@
include "fzn_lex_chain_lesseq_int.mzn";
include "fzn_lex_chain_lesseq_int_reif.mzn";
%-----------------------------------------------------------------------------%
% Requires that the columns of matrix \a a are lexicographically sorted,
% non-decreasing.
%-----------------------------------------------------------------------------%
predicate lex_chain_lesseq_int(array[int, int] of var int: a) =
fzn_lex_chain_lesseq_int(a);
%-----------------------------------------------------------------------------%

View File

@ -1,18 +0,0 @@
include "fzn_lex_chain_lesseq_orbitope.mzn";
include "fzn_lex_chain_lesseq_orbitope_reif.mzn";
/** @group globals.lexicographic
Requires that the columns of binary matrix \a a are
lexicographically sorted, non-decreasing.
Moreover, the second parameter has the following meaning:
0: no further constraints, 1: set-partitioning orbitope,
2: set-packing orbitope
*/
predicate lex_chain_lesseq_orbitope(
array[int, int] of var int: a, int: kind) =
assert(dom_array(a) subset 0..1,
"lex_chain_lesseq_orbitope: matrix \(a) is non-binary")
/\
if 1>=card(index_set_2of2(a)) then true
else fzn_lex_chain_lesseq_orbitope(a, kind) endif;

View File

@ -2,8 +2,8 @@ include "fzn_piecewise_linear.mzn";
include "fzn_piecewise_linear_reif.mzn";
/** @group globals
Return the piecewise-linear function of x
on the given point-value sequence
Return a piecewise-linear interpolation
of the given point sequence as a function of \a x
*/
function var float: piecewise_linear(var float: x, array[int] of float: xi, array[int] of float: vi) ::promise_total =
let {
@ -13,8 +13,8 @@ function var float: piecewise_linear(var float: x, array[int] of float: xi, arra
/** @group globals
Constrains \a y(\a x) to be the piecewise-linear function
on the provided point-value sequence.
Constrains \a y(\a x) to be a piecewise-linear interpolation of
the provided point sequence.
*/
predicate piecewise_linear(var float: x, var float: y,
array[int] of float: xi, array[int] of float: vi) =

View File

@ -1,29 +0,0 @@
include "fzn_piecewise_linear_non_continuous.mzn";
include "fzn_piecewise_linear_non_continuous_reif.mzn";
/** @group globals
Return the piecewise-linear function of x
on the given (possibly disconnected) intervals.
Each interval \a i connects
(\a x_start[\a i], \a v_start[\a i]) to (\a x_end[\a i], \a v_end[\a i]).
*/
function var float: piecewise_linear(var float: x,
array[int] of float: x_start, array[int] of float: x_end,
array[int] of float: v_start, array[int] of float: v_end) ::promise_total =
let {
var float: res,
constraint piecewise_linear(x, res, x_start,x_end, v_start,v_end),
} in res;
/** @group globals
Constrains \a y(\a x) to be the piecewise-linear function on
the provided point-value intervals.
*/
predicate piecewise_linear(var float: x, var float: y,
array[int] of float: x_start, array[int] of float: x_end,
array[int] of float: v_start, array[int] of float: v_end
) =
fzn_piecewise_linear(x, y, x_start,x_end, v_start,v_end);
%-----------------------------------------------------------------------------%

View File

@ -17,6 +17,12 @@ ann: on_restart(string: pred);
enum STATUS = {START, UNKNOWN, UNSAT, SAT, OPT};
function var STATUS: status();
/*
When complete is set to 'true', then it marks the search as complete.
*/
predicate complete();% = abort("'complete' should be used in reified context");
predicate complete_reif(var bool: marker);
/*
The 'uniform' function provides random values chosen by the solver. The arguments
to the function limit the values to a certain domain.
@ -134,4 +140,4 @@ predicate round_robin(array[int] of var bool: nbhs) =
select = -1
else
select = (sol(select) + 1) mod len
endif;
endif;

View File

@ -13,11 +13,6 @@ function int: round(float: x);
/** @group stdlib.coercion Return Boolean \a b coerced to an integer */
function int: bool2int(bool: b);
/** @group stdlib.coercion Return Boolean \a b coerced to an integer */
function opt int: bool2int(opt bool: b) =
if occurs(b) then bool2int(deopt(b)) else <> endif;
/** @group stdlib.coercion Return optional 0/1 integer that is absent iff \a x
is absent, and 1 iff \a x occurs and is true. */
function var opt int: bool2int(var opt bool: x) ::promise_total =
@ -30,10 +25,6 @@ function var opt int: bool2int(var opt bool: x) ::promise_total =
/** @group stdlib.coercion Return Boolean \a b coerced to a float */
function float: bool2float(bool: b) = if b then 1.0 else 0.0 endif;
/** @group stdlib.coercion Return Boolean \a b coerced to a float */
function opt float: bool2float(opt bool: b) =
if occurs(b) then bool2float(deopt(b)) else <> endif;
/** @group stdlib.coercion Return array of Booleans \a x coerced to an array of floats */
function array[$T] of float: bool2float(array[$T] of bool: x) ::promise_total =
let {
@ -53,9 +44,6 @@ function var float: bool2float(var bool: b) = int2float(bool2int(b));
/** @group stdlib.coercion Return integer \a x coerced to a float */
function float: int2float(int: x);
/** @group stdlib.coercion Return integer \a x coerced to a float */
function opt float: int2float(opt int: x) =
if occurs(x) then int2float(deopt(x)) else <> endif;
/** @group stdlib.coercion Return integer \a x coerced to a float */
function var float: int2float(var int: x) ::promise_total;
/** @group stdlib.arithmetic Return optional 0/1 float that is absent iff \a x
@ -99,24 +87,12 @@ function array[$T] of var int: bool2int(array[$T] of var bool: x) ::promise_tota
array[int] of var bool: xx = array1d(x)
} in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of Booleans \a x coerced to an array of integers */
function array[$T] of opt int: bool2int(array[$T] of opt bool: x) =
let {
array[int] of opt bool: xx = array1d(x)
} in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of Booleans \a x coerced to an array of integers */
function array[$T] of var opt int: bool2int(array[$T] of var opt bool: x) ::promise_total =
let {
array[int] of var opt bool: xx = array1d(x)
} in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of Booleans \a x coerced to an array of floats */
function array[$T] of opt float: bool2float(array[$T] of opt bool: x) =
let {
array[int] of opt bool: xx = array1d(x)
} in arrayXd(x, [bool2float(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of Booleans \a x coerced to an array of floats */
function array[$T] of var opt float: bool2float(array[$T] of var opt bool: x) ::promise_total =
let {
@ -129,12 +105,6 @@ function array[$T] of float: int2float(array[$T] of int: x) ::promise_total =
array[int] of int: xx = array1d(x)
} in arrayXd(x,[int2float(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of integers \a x coerced to an array of floats */
function array[$T] of opt float: int2float(array[$T] of opt int: x) ::promise_total =
let {
array[int] of opt int: xx = array1d(x)
} in arrayXd(x,[int2float(xx[i]) | i in index_set(xx)]);
/** @group stdlib.coercion Return array of integers \a x coerced to an array of floats */
function array[$T] of var float: int2float(array[$T] of var int: x) ::promise_total =
let {

View File

@ -159,8 +159,6 @@ test mzn_in_root_context(var $T);
test mzn_in_redundant_constraint();
test mzn_in_symmetry_breaking_constraint();
/* Internal function used to optimize over option type objective */
function var float: objective_deopt_(var opt float: x, bool: direction) =
let {
@ -1227,23 +1225,3 @@ function var float: min_t(array[int] of var float: x) :: promise_total =
predicate mzn_symmetry_breaking_constraint(var bool: b);
predicate mzn_redundant_constraint(var bool: b);
/* Annotations used for bookkeeping by the compiler */
annotation mzn_was_undefined;
/* Predicate used in the compiler for translating infinite domains into constraints */
predicate mzn_set_in_internal(var int: x, set of int: s) =
if min(s) != -infinity /\ max(s) != infinity then set_in(x,s)
else let {
array[int] of int: ranges_ = set_to_ranges(s);
array[int,1..2] of int: ranges = array2d(1..length(ranges_) div 2,1..2,ranges_);
int: max_range = card(index_set_1of2(ranges));
} in if max_range=2 /\ ranges[1,2]=ranges[2,1]-2 then
x != ranges[1,2]+1
else
x <= ranges[1,2] \/ x >= ranges[max_range,1] \/
exists (i in 2..max_range-1) (x in ranges[i,1]..ranges[i,2])
endif
endif;

View File

@ -218,20 +218,29 @@ function float: product(array[int] of opt float: x) =
function $T: min( $T: x, $T: y);
/** @group stdlib.arithmetic Return minimum of elements in array \a x */
function $T: min(array[$U] of par $T: x);
/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent. */
function var int: min(array[int] of var opt int: x) =
/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent, or
absent if all elements in \a x are absent. */
function var opt int: min(array[int] of var opt int: x) ::promise_total =
let {
var lb_array(x)..ub_array(x): xmax = max(xi in x)(deopt(xi));
% Array cannot be empty, otherwise min is undefined
constraint exists(xi in x)(occurs(xi));
} in min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent. */
function var float: min(array[int] of var opt float: x) =
var opt lb_array(x)..ub_array(x): m;
var lb_array(x)..ub_array(x): xmax;
constraint if ub(xmax) != infinity then xmax = ub(xmax) else forall (i in index_set(x)) (xmax >= deopt(x[i])) endif;
constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i]));
constraint occurs(m) ->
deopt(m) = min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
} in m;
/** @group stdlib.arithmetic Return minimum of elements in \a x that are not absent, or
absent if all elements in \a x are absent. */
% :NOTE: since -oo is always a lb for float variables, should we instead return -oo if all absent?
function var opt float: min(array[int] of var opt float: x) ::promise_total =
let {
var lb_array(x)..ub_array(x): xmax = max(xi in x)(deopt(xi));
% Array cannot be empty, otherwise min is undefined
constraint exists(xi in x)(occurs(xi));
} in min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
var opt lb_array(x)..ub_array(x): m;
var lb_array(x)..ub_array(x): xmax;
constraint if ub(xmax) != infinity then xmax = ub(xmax) else forall (i in index_set(x)) (xmax >= deopt(x[i])) endif;
constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i]));
constraint occurs(m) ->
deopt(m) = min([if occurs(xi) then deopt(xi) else xmax endif | xi in x]);
} in m;
/** @group stdlib.arithmetic Return maximum of \a x and \a y */
function $T: max( $T: x, $T: y);
@ -239,11 +248,15 @@ function $T: max( $T: x, $T: y);
function $T: max(array[$U] of $T: x);
/** @group stdlib.arithmetic Return maximum of elements in \a x that are not absent, or
absent if all elements in \a x are absent. */
function var int: max(array[int] of var opt int: x) =
function var opt int: max(array[int] of var opt int: x) ::promise_total =
let {
var lb_array(x)..ub_array(x): xmin = min(xi in x)(deopt(xi));
constraint exists (xi in x) (occurs(xi));
} in max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
var opt lb_array(x)..ub_array(x): m;
var lb_array(x)..ub_array(x): xmin;
constraint if lb(xmin) != -infinity then xmin = lb(xmin) else forall (i in index_set(x)) (xmin <= deopt(x[i])) endif;
constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i]));
constraint occurs(m) ->
deopt(m) = max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
} in m;
/** @group stdlib.arithmetic Return minimum of elements in set \a x */
function $$E: min(set of $$E: x);
/** @group stdlib.arithmetic Return maximum of elements in set \a x */
@ -261,12 +274,17 @@ function var int: max(array[$U] of var int: x) =
array[int] of var int: xx = array1d(x);
constraint length(x) >= 1;
} in max_t(xx);
/** @group stdlib.arithmetic Return maximum of elements in \a x that are not absent. */
function var float: max(array[int] of var opt float: x) =
/** @group stdlib.arithmetic Return maximum of elements in \a x that are not absent, or
absent if all elements in \a x are absent. */
function var opt float: max(array[int] of var opt float: x) ::promise_total =
let {
var lb_array(x)..ub_array(x): xmin = min(xi in x)(deopt(xi));
constraint exists (xi in x) (occurs(xi));
} in max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
var opt lb_array(x)..ub_array(x): m;
var lb_array(x)..ub_array(x): xmin;
constraint if lb(xmin) != -infinity then xmin = lb(xmin) else forall (i in index_set(x)) (xmin <= deopt(x[i])) endif;
constraint occurs(m) <-> exists (i in index_set(x)) (occurs(x[i]));
constraint occurs(m) ->
deopt(m) = max([if occurs(xi) then deopt(xi) else xmin endif | xi in x]);
} in m;
/** @group stdlib.arithmetic Return minimum of \a x and \a y */
function var int: min(var int: x, var int: y) :: promise_total =

View File

@ -1,5 +1,4 @@
include "fzn_strictly_decreasing_int.mzn";
include "fzn_strictly_decreasing_int_opt.mzn";
include "fzn_strictly_decreasing_int_reif.mzn";
include "fzn_strictly_decreasing_bool.mzn";
include "fzn_strictly_decreasing_bool_reif.mzn";
@ -9,7 +8,6 @@ include "analyse_all_different.mzn";
% Requires that the array 'x' is in strict decreasing order
%-----------------------------------------------------------------------------%
/** @group globals.sort Requires that the array \a x is in a stricly decreasing order (duplicates are *not* allowed). */
predicate strictly_decreasing(array[$X] of var bool: x) =
analyse_all_different(array1d(x)) /\
fzn_strictly_decreasing_bool(array1d(x));
@ -17,15 +15,9 @@ predicate strictly_decreasing(array[$X] of var bool: x) =
predicate strictly_decreasing_reif(array[$X] of var bool: x, var bool: b) =
fzn_strictly_decreasing_bool_reif(array1d(x),b);
/** @group globals.sort Requires that the array \a x is in a stricly decreasing order (duplicates are *not* allowed). */
predicate strictly_decreasing(array[$X] of var int: x) =
analyse_all_different(array1d(x)) /\
fzn_strictly_decreasing_int(array1d(x));
/** @group globals.sort Requires that the array \a x is in a stricly decreasing order (duplicates are *not* allowed). */
predicate strictly_decreasing(array[$X] of var opt int: x) =
analyse_all_different(array1d(x)) /\
fzn_strictly_decreasing_int_opt(array1d(x));
predicate strictly_decreasing_reif(array[$X] of var int: x, var bool: b) =
fzn_strictly_decreasing_int_reif(array1d(x),b);

View File

@ -1070,7 +1070,7 @@ MIPCplexWrapper::Status MIPCplexWrapper::convertStatus(int cplexStatus) {
break;
// case CPXMIP_ABORT_INFEAS:
case CPXMIP_FAIL_INFEAS:
s = Status::ERROR_STATUS;
s = Status::__ERROR;
break;
default:
// case CPXMIP_OPTIMAL_TOL:

Some files were not shown because too many files have changed in this diff Show More