Skip to content

Commit

Permalink
Merge branch 'hotfix/2.1.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
guidotack committed May 17, 2017
2 parents 8fe4f8b + ddc0c5d commit 334d55b
Show file tree
Hide file tree
Showing 25 changed files with 405 additions and 270 deletions.
31 changes: 31 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,37 @@
All bug numbers refer to the issue tracker at
https://github.com/MiniZinc/libminizinc/issues

Version 2.1.5
=============

Changes:
- Some improvements to the linearisation library.
- Make parser read multiple .mzn files correctly.
- Enable better bounds computation for array access expressions on
fixed arrays.
- Perform better constant folding during optimisation phase. Fixes #155.
- Don't rewrite pow function into multiplication in the case of power of 2.
- Save some memory by making certain internal data structures more compact.
- Improve source code location of identifiers in generator calls (should give
more precise error messages).
- Produce an error message when a comprehension attempts to iterate over an
infinite set.
- Produce better error messages for operations on infinite values (previously
some errors did not contain a source code location).
- Speed up garbage collection by pre-allocating some memory.

Bug fixes:
- Fix range check for float literals in arrays.
- Fix a bug where a constraint could be removed incorrectly. Fixes #150.
- Include variables for dzn and json output from all included models, not
just the main model. Fixes #153.
- Produce multi-dimensional arrays in json output. Fixes #156 and #157.
- Remove incorrect closing bracket from json output. Fixes #154.
- Fix bounds computation of par int and float arrays.
- Don't allow var access to arrays of strings or annotations (since that would
require an element constraint and var string / var ann types).
- Introduce int2float constraints where necessary for some linearisations.

Version 2.1.4
=============

Expand Down
12 changes: 6 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ project (libminizinc CXX C)
# ---- For example, to produce mzn-gecode run "cd build; cmake -D GECODE_HOME=$GECODE_HOME ..; cmake --build ." ----
# -------------------------------------------------------------------------------------------------------------------
set(HAS_FZN TRUE) ### Always compile the mzn-fzn driver
if (DEFINED GECODE_HOME)
if (DEFINED GECODE_HOME AND NOT "${GECODE_HOME} " STREQUAL " ")
set(HAS_GECODE TRUE)
endif()
if (DEFINED CPLEX_STUDIO_DIR)
if (DEFINED CPLEX_STUDIO_DIR AND NOT "${CPLEX_STUDIO_DIR} " STREQUAL " ")
set(HAS_CPLEX TRUE)
endif()
if(DEFINED GUROBI_HOME)
if(DEFINED GUROBI_HOME AND NOT "${GUROBI_HOME} " STREQUAL " ")
set(HAS_GUROBI TRUE)
endif()
if (DEFINED SCIP_DIR AND DEFINED SOPLEX_DIR AND DEFINED ZIMPL_DIR)
if (DEFINED SCIP_DIR AND DEFINED SOPLEX_DIR AND DEFINED ZIMPL_DIR AND NOT "${SCIP_DIR} " STREQUAL " ")
set(HAS_SCIP TRUE) # Can use SCIP w/o ZIMPL too
endif()
if (DEFINED OSICBC_HOME)
if (DEFINED OSICBC_HOME AND NOT "${OSICBC_HOME} " STREQUAL " ")
set(HAS_OSICBC TRUE)
endif()

# -------------------------------------------------------------------------------------------------------------------
# The version number.
set (libminizinc_VERSION_MAJOR 2)
set (libminizinc_VERSION_MINOR 1)
set (libminizinc_VERSION_PATCH 4)
set (libminizinc_VERSION_PATCH 5)

if (ADDITIONAL_DATE_STRING)
set (libminizinc_VERSION_PATCH "${libminizinc_VERSION_PATCH}.${ADDITIONAL_DATE_STRING}")
Expand Down
3 changes: 3 additions & 0 deletions include/minizinc/ast.hh
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,9 @@ namespace MiniZinc {
Generator(const std::vector<ASTString>& v,
Expression* in);
/// Allocate
Generator(const std::vector<Id*>& v,
Expression* in);
/// Allocate
Generator(const std::vector<VarDecl*>& v,
Expression* in);

Expand Down
20 changes: 10 additions & 10 deletions include/minizinc/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ namespace MiniZinc {
d[i*2+1] = dims[i].second;
}
_v = ASTExprVec<Expression>(v);
_dims = ASTIntVec(d);
if (d.size()!=2 || d[0]!=1) {
// only allocate dims vector if it is not a 1d array indexed from 1
_dims = ASTIntVec(d);
}
rehash();
}

Expand All @@ -234,7 +237,10 @@ namespace MiniZinc {
d[i*2+1] = dims[i].second;
}
_v = v;
_dims = ASTIntVec(d);
if (d.size()!=2 || d[0]!=1) {
// only allocate dims vector if it is not a 1d array indexed from 1
_dims = ASTIntVec(d);
}
rehash();
}

Expand All @@ -243,11 +249,8 @@ namespace MiniZinc {
ASTExprVec<Expression> v)
: Expression(loc,E_ARRAYLIT,Type()) {
_flag_1 = false;
std::vector<int> dims(2);
dims[0]=1;
dims[1]=v.size();
_v = v;
_dims = ASTIntVec(dims);
// don't allocate dims vector since this is a 1d array indexed from 1
rehash();
}

Expand All @@ -256,11 +259,8 @@ namespace MiniZinc {
const std::vector<Expression*>& v)
: Expression(loc,E_ARRAYLIT,Type()) {
_flag_1 = false;
std::vector<int> dims(2);
dims[0]=1;
dims[1]=v.size();
// don't allocate dims vector since this is a 1d array indexed from 1
_v = ASTExprVec<Expression>(v);
_dims = ASTIntVec(dims);
rehash();
}

Expand Down
4 changes: 4 additions & 0 deletions include/minizinc/eval_par.hh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <minizinc/model.hh>
#include <minizinc/iter.hh>
#include <minizinc/astexception.hh>

#include <minizinc/prettyprinter.hh>

Expand Down Expand Up @@ -189,6 +190,9 @@ namespace MiniZinc {
eval_comp_set(EnvI& env, Eval& eval, Comprehension* e, int gen, int id,
KeepAlive in, std::vector<typename Eval::ArrayVal>& a) {
IntSetVal* isv = eval_intset(env, in());
if (isv->card().isPlusInfinity()) {
throw EvalError(env,in()->loc(),"comprehension iterates over an infinite set");
}
IntSetRanges rsi(isv);
Ranges::ToValues<IntSetRanges> rsv(rsi);
for (; rsv(); ++rsv) {
Expand Down
15 changes: 12 additions & 3 deletions include/minizinc/values.hh
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,21 @@ namespace MiniZinc {
}
inline
IntVal operator *(const IntVal& x, const IntVal& y) {
if (! (x.isFinite() && y.isFinite()))
throw ArithmeticError("arithmetic operation on infinite value");
return x.toSafeInt()*y.toSafeInt();
if (!x.isFinite()) {
if (y.isFinite() && std::abs(y._v)==1)
return IntVal(x._v*y._v,!x.isFinite());
} else if (!y.isFinite()) {
if (x.isFinite() && std::abs(x._v)==1)
return IntVal(x._v*y._v,true);
} else {
return x.toSafeInt()*y.toSafeInt();
}
throw ArithmeticError("arithmetic operation on infinite value");
}
inline
IntVal operator /(const IntVal& x, const IntVal& y) {
if (y.isFinite() && std::abs(y._v)==1)
return IntVal(x._v * y._v, !x.isFinite());
if (! (x.isFinite() && y.isFinite()))
throw ArithmeticError("arithmetic operation on infinite value");
return x.toInt()/y.toInt();
Expand Down
47 changes: 32 additions & 15 deletions lib/MIPdomains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
/// - so better turn that off TODO
/// CSE for lineq coefs TODO

/// TODO use integer division instead of INT_EPS
#define INT_EPS 1e-5 // the absolute epsilon for integrality of integer vars.


Expand Down Expand Up @@ -312,13 +313,19 @@ namespace MiniZinc {
if ( ic->removed() )
continue;
if ( Call* c = ic->e()->dyn_cast<Call>() ) {
if ( auto ipct = mCallTypes.find(c->decl())
!= mCallTypes.end() ) {
auto ipct = mCallTypes.find(c->decl());
if ( ipct != mCallTypes.end() ) {
// No ! here because might be deleted immediately in later versions.
// ic->remove(); // mark removed at once
MZN_MIPD__assert_hard( c->args().size() > 1 );
++MIPD__stats[ N_POSTs__all ];
VarDecl* vd0 = expr2VarDecl(c->args()[0]);
if ( 0==vd0 ) {
/// Only allow literals as main argument for equality_encoding
MZN_MIPD__assert_hard( equality_encoding__POST==ipct->first );
ic->remove();
continue; // ignore this call
}
DBGOUT_MIPD__ ( " Call " << c->id().str()
<< " uses variable " << vd0->id()->str() );
if ( vd0->payload() == -1 ) { // ! yet visited
Expand Down Expand Up @@ -1435,6 +1442,7 @@ namespace MiniZinc {
SetLit* newDom = new SetLit( Location().introduce(), IntSetVal::a( LB, UB ) );
TypeInst* ti = new TypeInst(Location().introduce(),Type::varint(),newDom);
VarDecl* newVar = new VarDecl(Location().introduce(),ti,mipd.getEnv()->envi().genId());
newVar->flat(newVar);
mipd.getEnv()->envi().flat_addItem(new VarDeclI(Location().introduce(),newVar));
return newVar;
}
Expand Down Expand Up @@ -1473,22 +1481,29 @@ namespace MiniZinc {
);
std::vector<Expression*> nc_c(coefs.size());
std::vector<Expression*> nx(coefs.size());
bool fFloat = !((*vars.begin())->type().isint());
bool fFloat = false;
for ( auto v: vars ) {
if ( fFloat == v->type().isint() ) { // mixed types not allowed...
std::ostringstream oss;
oss << "addLinConstr: mixed var types: ";
for ( auto v: vars )
oss << v->type().isint();
throw std::runtime_error(oss.str());
if ( !v->type().isint() ) {
fFloat = true;
break;
}
}
auto sName = constants().ids.float_.lin_eq; // "int_lin_eq";
FunctionI* fDecl = mipd.float_lin_eq;
if ( fFloat ) { // MZN_MIPD__assert_hard all vars of same type TODO
for ( int i=0; i<vars.size(); ++i ) {
nc_c[i] = FloatLit::a( coefs[i] );
nx[i] = vars[i]; // ->id(); once passing a general expression
if (vars[i]->type().isint()) {
std::vector<Expression*> i2f_args(1);
i2f_args[0] = vars[i];
Call* i2f = new Call(Location().introduce(),constants().ids.int2float,i2f_args);
i2f->type(Type::varfloat());
i2f->decl(mipd.getEnv()->model()->matchFn(mipd.getEnv()->envi(), i2f, false));
EE ret = flat_exp(mipd.getEnv()->envi(), Ctx(), i2f, NULL, constants().var_true);
nx[i] = ret.r();
} else {
nx[i] = vars[i]; // ->id(); once passing a general expression
}
}
args[2] = FloatLit::a(rhs);
args[2]->type(Type::parfloat(0));
Expand Down Expand Up @@ -1633,12 +1648,14 @@ namespace MiniZinc {
// The requirement to have actual variable objects
// might be a limitation if more optimizations are done before...
// Might need to flexibilize this TODO
MZN_MIPD__assert_hard_msg( ! arg->dyn_cast<IntLit>(),
"Expression " << *arg << " is an IntLit!" );
MZN_MIPD__assert_hard( ! arg->dyn_cast<FloatLit>() );
MZN_MIPD__assert_hard( ! arg->dyn_cast<BoolLit>() );
// MZN_MIPD__assert_hard_msg( ! arg->dyn_cast<IntLit>(),
// "Expression " << *arg << " is an IntLit!" );
// MZN_MIPD__assert_hard( ! arg->dyn_cast<FloatLit>() );
// MZN_MIPD__assert_hard( ! arg->dyn_cast<BoolLit>() );
Id* id = arg->dyn_cast<Id>();
MZN_MIPD__assert_hard(id);
// MZN_MIPD__assert_hard(id);
if ( 0==id )
return 0; // the call using this should be ignored?
VarDecl* vd = id->decl();
MZN_MIPD__assert_hard(vd);
return vd;
Expand Down
49 changes: 35 additions & 14 deletions lib/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace MiniZinc {
Expression::mark(Expression* e) {
if (e==NULL || e->isUnboxedInt()) return;
std::vector<const Expression*> stack;
stack.reserve(1000);
stack.push_back(e);
while (!stack.empty()) {
const Expression* cur = stack.back(); stack.pop_back();
Expand Down Expand Up @@ -242,29 +243,24 @@ namespace MiniZinc {
init_hash();
}

void
ArrayLit::rehash(void) {
init_hash();
HASH_NAMESPACE::hash<int> h;
for (unsigned int i=0; i<_dims.size(); i+=2) {
cmb_hash(h(_dims[i]));
cmb_hash(h(_dims[i+1]));
}
for (unsigned int i=_v.size(); i--;) {
cmb_hash(h(i));
cmb_hash(Expression::hash(_v[i]));
}
}
int
ArrayLit::dims(void) const {
return _dims.size()/2;
return _dims.size()==0 ? 1 : _dims.size()/2;
}
int
ArrayLit::min(int i) const {
if (_dims.size()==0) {
assert(i==0);
return 1;
}
return _dims[2*i];
}
int
ArrayLit::max(int i) const {
if (_dims.size()==0) {
assert(i==0);
return _v.size();
}
return _dims[2*i+1];
}
int
Expand All @@ -275,6 +271,19 @@ namespace MiniZinc {
l *= (max(i) - min(i) + 1);
return l;
}
void
ArrayLit::rehash(void) {
init_hash();
HASH_NAMESPACE::hash<int> h;
for (unsigned int i=0; i<dims(); i+=2) {
cmb_hash(h(min(i)));
cmb_hash(h(max(i)));
}
for (unsigned int i=_v.size(); i--;) {
cmb_hash(h(i));
cmb_hash(Expression::hash(_v[i]));
}
}

void
ArrayAccess::rehash(void) {
Expand All @@ -298,6 +307,18 @@ namespace MiniZinc {
_v = vd;
_in = in;
}
Generator::Generator(const std::vector<Id*>& v,
Expression* in) {
std::vector<VarDecl*> vd;
for (unsigned int i=0; i<v.size(); i++) {
VarDecl* nvd = new VarDecl(v[i]->loc(),
new TypeInst(v[i]->loc(),Type::parint()),v[i]->v());
nvd->toplevel(false);
vd.push_back(nvd);
}
_v = vd;
_in = in;
}
Generator::Generator(const std::vector<std::string>& v,
Expression* in) {
std::vector<VarDecl*> vd;
Expand Down
20 changes: 20 additions & 0 deletions lib/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1410,14 +1410,34 @@ namespace MiniZinc {
return oss.str();
} else {
if (ArrayLit* al = e->dyn_cast<ArrayLit>()) {

std::vector<unsigned int> dims(al->dims()-1);
dims[0] = al->max(al->dims()-1)-al->min(al->dims()-1)+1;

for (unsigned int i=1; i<al->dims()-1; i++) {
dims[i] = dims[i-1] * (al->max(al->dims()-1-i)-al->min(al->dims()-1-i)+1);
}

std::ostringstream oss;
oss << "[";
for (unsigned int i=0; i<al->v().size(); i++) {
for (unsigned int j=0; j<dims.size(); j++) {
if (i % dims[j] == 0) {
oss << "[";
}
}
oss << b_show_json_basic(env, al->v()[i]);
for (unsigned int j=0; j<dims.size(); j++) {
if (i % dims[j] == dims[j]-1) {
oss << "]";
}
}

if (i<al->v().size()-1)
oss << ", ";
}
oss << "]";

return oss.str();
} else {
return b_show_json_basic(env, e);
Expand Down
Loading

0 comments on commit 334d55b

Please sign in to comment.