From c619ad6a060ac4b6d3968429451fd83e3b9c1a54 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Sat, 19 Nov 2016 16:38:30 +1100 Subject: [PATCH 1/9] Add cmath to hopefully fix compilation problems for some compilers. Fixes #125. --- include/minizinc/iter.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/include/minizinc/iter.hh b/include/minizinc/iter.hh index 42b7ce77b..88fe2cc22 100644 --- a/include/minizinc/iter.hh +++ b/include/minizinc/iter.hh @@ -13,6 +13,7 @@ #define __MINIZINC_ITER_HH__ #include +#include #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS From 0328049dea8fa6983a307910bf9ab22c2fada184 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Fri, 25 Nov 2016 13:30:37 +0100 Subject: [PATCH 2/9] Fix enum type checking for comprehensions --- lib/typecheck.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/typecheck.cpp b/lib/typecheck.cpp index 58b6af53e..9109a645f 100644 --- a/lib/typecheck.cpp +++ b/lib/typecheck.cpp @@ -859,6 +859,12 @@ namespace MiniZinc { throw TypeError(_env,c.e()->loc(), "array comprehension expression cannot be an array"); tt.dim(1); + if (tt.enumId() != 0) { + std::vector enumIds(2); + enumIds[0] = 0; + enumIds[1] = tt.enumId(); + tt.enumId(_env.registerArrayEnum(enumIds)); + } } c.type(tt); } From 63f4b962598fdf294320e45570ff7d61e2f26ced Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Fri, 25 Nov 2016 15:03:04 +0100 Subject: [PATCH 3/9] Add min/max functions for var set, including redefinition --- share/minizinc/std/builtins.mzn | 7 +++ share/minizinc/std/redefinitions-2.1.1.mzn | 58 ++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 share/minizinc/std/redefinitions-2.1.1.mzn diff --git a/share/minizinc/std/builtins.mzn b/share/minizinc/std/builtins.mzn index 29aa3a861..b2f09d9f3 100644 --- a/share/minizinc/std/builtins.mzn +++ b/share/minizinc/std/builtins.mzn @@ -691,6 +691,12 @@ function var set of int: array_intersect(array[int] of var set of int: x) ::prom } in y[u-1] endif; +/** @group builtins.set Return the minimum of the set \a s */ +function var $$E: min(var set of $$E: s); + +/** @group builtins.set Return the maximum of the set \a s */ +function var $$E: max(var set of $$E: s); + /*** @groupdef builtins.array Array operations @@ -2073,6 +2079,7 @@ include "redefinitions.mzn"; include "redefinitions-2.0.mzn"; include "redefinitions-2.0.2.mzn"; include "redefinitions-2.1.mzn"; +include "redefinitions-2.1.1.mzn"; %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% diff --git a/share/minizinc/std/redefinitions-2.1.1.mzn b/share/minizinc/std/redefinitions-2.1.1.mzn new file mode 100644 index 000000000..e6eed74be --- /dev/null +++ b/share/minizinc/std/redefinitions-2.1.1.mzn @@ -0,0 +1,58 @@ +% This file contains redefinitions of standard builtins for version 2.1.1 +% that can be overridden by solvers. + +function var $$E: min(var set of $$E: s) = + let { var min(ub(s)) .. max(ub(s)): m = + min([ e + (max(ub(s))+1-e)*(1 - (e in s)) | e in ub(s) ]) } in m; + +%% The following can be used as an alternative if the solver supports +%% a FlatZinc builtin set_min: + +% predicate set_min(var set of int: s, var int: m); +% +% function var $$E: min(var set of $$E: s) = +% if mzn_in_root_context(s) then min_t(s) else +% let { constraint card(s) > 0 } in min_mt(s) endif; +% +% function var $$E: min_t(var set of $$E: s) ::promise_total = +% let { +% var min(ub(s))..max(ub(s)): ms ::is_defined_var; +% constraint card(s) > 0; +% constraint set_min(s,ms) ::defines_var(ms); +% } in ms; +% +% function var $$E: min_mt(var set of $$E: s) ::promise_total = +% let { +% var set of ub(s) union {1}: x; +% var bool: b = card(s) > 0; +% constraint b -> x=s; +% constraint b \/ 1 in x; +% } in min_t(x); + +function var $$E: max(var set of $$E: s) = + let { var min(ub(s)) .. max(ub(s)): m = + max([ e + (min(ub(s))-1-e)*(1 - (e in s)) | e in ub(s) ]) } in m; + +%% The following can be used as an alternative if the solver supports +%% a FlatZinc builtin set_max: + +% predicate set_max(var set of int: s, var int: m); +% +% function var $$E: max(var set of $$E: s) = +% if mzn_in_root_context(s) then max_t(s) else +% let { constraint card(s) > 0 } in max_mt(s) endif; +% +% function var $$E: max_t(var set of $$E: s) ::promise_total = +% let { +% var min(ub(s))..max(ub(s)): ms ::is_defined_var; +% constraint card(s) > 0; +% constraint set_max(s,ms) ::defines_var(ms); +% } in ms; +% +% function var $$E: max_mt(var set of $$E: s) ::promise_total = +% let { +% var set of ub(s) union {1}: x; +% var bool: b = card(s) > 0; +% constraint b -> x=s; +% constraint b \/ 1 in x; +% } in max_t(x); From c77a2098b07c8cde583a6b43d84847f3e987a127 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Fri, 25 Nov 2016 15:03:21 +0100 Subject: [PATCH 4/9] Fix bounds computation for var set of $$E --- lib/eval_par.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/eval_par.cpp b/lib/eval_par.cpp index 812b7d72d..f859280fc 100644 --- a/lib/eval_par.cpp +++ b/lib/eval_par.cpp @@ -2363,7 +2363,7 @@ namespace MiniZinc { } /// Visit identifier void vId(const Id& id) { - if (id.decl()->ti()->domain()) { + if (id.decl()->ti()->domain() && !id.decl()->ti()->domain()->isa()) { _bounds.push_back(eval_intset(env,id.decl()->ti()->domain())); } else { if (id.decl()->e()) { From 0d35b15b395581fbe680b5e753bf45ae8e825d3b Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Fri, 25 Nov 2016 16:54:48 +0100 Subject: [PATCH 5/9] Support anon_enum initialisations, and print correct output for anonymous enums in dzn output mode --- lib/output.cpp | 10 ++-- lib/typecheck.cpp | 93 ++++++++++++++++++++++++--------- share/minizinc/std/builtins.mzn | 6 +++ 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/lib/output.cpp b/lib/output.cpp index 243c1cb50..ac7419f35 100644 --- a/lib/output.cpp +++ b/lib/output.cpp @@ -173,7 +173,7 @@ namespace MiniZinc { EnvI& env; Decls(EnvI& env0) : env(env0) {} void vCall(Call& c) { - if (c.id()=="format" || c.id()=="show") { + if (c.id()=="format" || c.id()=="show" || c.id()=="showDzn") { int enumId = c.args()[c.args().size()-1]->type().enumId(); if (enumId != 0 && c.args()[c.args().size()-1]->type().dim() != 0) { const std::vector& enumIds = env.getArrayEnum(enumId); @@ -182,7 +182,7 @@ namespace MiniZinc { if (enumId > 0) { Id* ti_id = env.getEnum(enumId)->e()->id(); GCLock lock; - std::vector args(1); + std::vector args(2); args[0] = c.args()[c.args().size()-1]; if (args[0]->type().dim() > 1) { Call* array1d = new Call(Location().introduce(),ASTString("array1d"),args); @@ -191,10 +191,14 @@ namespace MiniZinc { array1d->type(array1dt); args[0] = array1d; } + args[1] = constants().boollit(c.id()=="showDzn"); std::string enumName = createEnumToStringName(ti_id, "_toString_"); c.id(ASTString(enumName)); c.args(args); } + if (c.id()=="showDzn") { + c.id(constants().ids.show); + } } c.decl(env.orig->matchFn(env,&c,false)); } @@ -401,7 +405,7 @@ namespace MiniZinc { std::vector showArgs(1); showArgs[0] = vd->id(); - Call* show = new Call(Location().introduce(),constants().ids.show,showArgs); + Call* show = new Call(Location().introduce(),ASTString("showDzn"),showArgs); show->type(Type::parstring()); FunctionI* fi = e.orig->matchFn(e, show, false); assert(fi); diff --git a/lib/typecheck.cpp b/lib/typecheck.cpp index 9109a645f..4a16ab9df 100644 --- a/lib/typecheck.cpp +++ b/lib/typecheck.cpp @@ -120,12 +120,16 @@ namespace MiniZinc { TypeInst* ti_aa = new TypeInst(Location().introduce(),Type::parint()); VarDecl* vd_aa = new VarDecl(Location().introduce(),ti_aa,"x"); vd_aa->toplevel(false); + TypeInst* ti_ab = new TypeInst(Location().introduce(),Type::parbool()); + VarDecl* vd_ab = new VarDecl(Location().introduce(),ti_ab,"b"); + vd_ab->toplevel(false); std::vector aa_args(1); aa_args[0] = vd_aa->id(); ArrayAccess* aa = new ArrayAccess(Location().introduce(),vd_enumToString->id(),aa_args); TypeInst* ti_fi = new TypeInst(Location().introduce(),Type::parstring()); - std::vector fi_params(1); + std::vector fi_params(2); fi_params[0] = vd_aa; + fi_params[1] = vd_ab; FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,aa); @@ -136,32 +140,53 @@ namespace MiniZinc { /// know it's a non-anonymous enum) vd_enumToString->e(new ArrayLit(Location().introduce(), std::vector())); } - TypeInst* ti_aa = new TypeInst(Location().introduce(),Type::parint()); - VarDecl* vd_aa = new VarDecl(Location().introduce(),ti_aa,"x"); - vd_aa->toplevel(false); - - StringLit* sl = new StringLit(Location().introduce(), ASTString(ident->str().str()+"_")); - std::vector showIntArgs(1); - showIntArgs[0] = vd_aa->id(); - Call* showInt = new Call(Location().introduce(), constants().ids.show, showIntArgs); - BinOp* construct_string = new BinOp(Location().introduce(), sl, BOT_PLUSPLUS, showInt); - - TypeInst* ti_fi = new TypeInst(Location().introduce(),Type::parstring()); - std::vector fi_params(1); - fi_params[0] = vd_aa; - FunctionI* fi = new FunctionI(Location().introduce(), - createEnumToStringName(ident, "_toString_"), - ti_fi,fi_params,construct_string); - enumItems.push_back(fi); + { + TypeInst* ti_aa = new TypeInst(Location().introduce(),Type::parint()); + VarDecl* vd_aa = new VarDecl(Location().introduce(),ti_aa,"x"); + vd_aa->toplevel(false); + + TypeInst* ti_ab = new TypeInst(Location().introduce(),Type::parbool()); + VarDecl* vd_ab = new VarDecl(Location().introduce(),ti_ab,"b"); + vd_ab->toplevel(false); + + StringLit* sl_dzn = new StringLit(Location().introduce(), + ASTString("to_enum("+ident->str().str()+",")); + std::vector showIntArgs(1); + showIntArgs[0] = vd_aa->id(); + Call* showInt_dzn = new Call(Location().introduce(), constants().ids.show, showIntArgs); + BinOp* construct_string_dzn = new BinOp(Location().introduce(), sl_dzn, BOT_PLUSPLUS, showInt_dzn); + StringLit* closing_bracket = new StringLit(Location().introduce(), ASTString(")")); + BinOp* construct_string_dzn_2 = new BinOp(Location().introduce(), construct_string_dzn, + BOT_PLUSPLUS, closing_bracket); + + StringLit* sl = new StringLit(Location().introduce(), ASTString(ident->str().str()+"_")); + Call* showInt = new Call(Location().introduce(), constants().ids.show, showIntArgs); + BinOp* construct_string = new BinOp(Location().introduce(), sl, BOT_PLUSPLUS, showInt); + + std::vector if_then(2); + if_then[0] = vd_ab->id(); + if_then[1] = construct_string_dzn_2; + ITE* ite = new ITE(Location().introduce(), if_then, construct_string); + + + TypeInst* ti_fi = new TypeInst(Location().introduce(),Type::parstring()); + std::vector fi_params(2); + fi_params[0] = vd_aa; + fi_params[1] = vd_ab; + FunctionI* fi = new FunctionI(Location().introduce(), + createEnumToStringName(ident, "_toString_"), + ti_fi,fi_params,ite); + enumItems.push_back(fi); + } } { /* - function _toString_ENUM(array[$U] of ENUM: x) = + function _toString_ENUM(array[$U] of ENUM: x, bool: b) = let { array[int] of ENUM: xx = array1d(x) - } in "[" ++ join(", ", [ _toString_ENUM(xx[i]) | i in index_set(xx) ]) ++ "]"; + } in "[" ++ join(", ", [ _toString_ENUM(xx[i],b) | i in index_set(xx) ]) ++ "]"; */ @@ -174,6 +199,10 @@ namespace MiniZinc { VarDecl* vd_x = new VarDecl(Location().introduce(),x_ti,"x"); vd_x->toplevel(false); + TypeInst* b_ti = new TypeInst(Location().introduce(),Type::parbool()); + VarDecl* vd_b = new VarDecl(Location().introduce(),b_ti,"b"); + vd_b->toplevel(false); + TypeInst* xx_range = new TypeInst(Location().introduce(),Type::parint(),NULL); std::vector xx_ranges(1); xx_ranges[0] = xx_range; @@ -194,8 +223,9 @@ namespace MiniZinc { aa_xxi_idx[0] = idx_i->id(); ArrayAccess* aa_xxi = new ArrayAccess(Location().introduce(),vd_xx->id(),aa_xxi_idx); - std::vector _toString_ENUMArgs(1); + std::vector _toString_ENUMArgs(2); _toString_ENUMArgs[0] = aa_xxi; + _toString_ENUMArgs[1] = vd_b->id(); Call* _toString_ENUM = new Call(Location().introduce(), createEnumToStringName(ident, "_toString_"), _toString_ENUMArgs); @@ -226,8 +256,9 @@ namespace MiniZinc { Let* let = new Let(Location().introduce(),let_args,bopp1); TypeInst* ti_fi = new TypeInst(Location().introduce(),Type::parstring()); - std::vector fi_params(1); + std::vector fi_params(2); fi_params[0] = vd_x; + fi_params[1] = vd_b; FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,let); @@ -237,8 +268,8 @@ namespace MiniZinc { { /* - function _toString_ENUM(set of ENUM: x) = - "{" ++ join(", ", [ _toString_ENUM(i) | i in x ]) ++ "}"; + function _toString_ENUM(set of ENUM: x, bool: b) = + "{" ++ join(", ", [ _toString_ENUM(i,b) | i in x ]) ++ "}"; */ @@ -247,12 +278,17 @@ namespace MiniZinc { VarDecl* vd_x = new VarDecl(Location().introduce(),x_ti,"x"); vd_x->toplevel(false); + TypeInst* b_ti = new TypeInst(Location().introduce(),Type::parbool()); + VarDecl* vd_b = new VarDecl(Location().introduce(),b_ti,"b"); + vd_b->toplevel(false); + TypeInst* idx_i_ti = new TypeInst(Location().introduce(),Type::parint()); VarDecl* idx_i = new VarDecl(Location().introduce(),idx_i_ti,"i"); idx_i->toplevel(false); - std::vector _toString_ENUMArgs(1); + std::vector _toString_ENUMArgs(2); _toString_ENUMArgs[0] = idx_i->id(); + _toString_ENUMArgs[1] = vd_b->id(); Call* _toString_ENUM = new Call(Location().introduce(), createEnumToStringName(ident, "_toString_"), _toString_ENUMArgs); @@ -276,8 +312,9 @@ namespace MiniZinc { BinOp* bopp1 = new BinOp(Location().introduce(),bopp0,BOT_PLUSPLUS,sl_close); TypeInst* ti_fi = new TypeInst(Location().introduce(),Type::parstring()); - std::vector fi_params(1); + std::vector fi_params(2); fi_params[0] = vd_x; + fi_params[1] = vd_b; FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,bopp1); @@ -1081,6 +1118,10 @@ namespace MiniZinc { nEnumIds[nEnumIds.size()-1] = enumIds[enumIds.size()-1]; vdt.enumId(_env.registerArrayEnum(nEnumIds)); } + } else if (vd.ti()->isEnum() && vd.e()->isa()) { + if (vd.e()->cast()->id()=="anon_enum") { + vet.enumId(vdt.enumId()); + } } if (! _env.isSubtype(vet,vdt,true)) { diff --git a/share/minizinc/std/builtins.mzn b/share/minizinc/std/builtins.mzn index b2f09d9f3..bc5e44a24 100644 --- a/share/minizinc/std/builtins.mzn +++ b/share/minizinc/std/builtins.mzn @@ -1127,6 +1127,12 @@ function string: show(var opt set of $T: x); function string: show(var opt $T: x); /** @group builtins.string Convert \a x into a string */ function string: show(array[$U] of var opt $T: x); + +function string: showDzn(var opt set of $T: x); +function string: showDzn(var opt $T: x); +function string: showDzn(array[$U] of var opt $T: x); + + /** @group builtins.string Formatted to-string conversion for integers Converts the integer \a x into a string right From 3ad9960210649f3031d08a72cb0fbde1f42b9369 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Thu, 1 Dec 2016 14:08:11 +0100 Subject: [PATCH 6/9] Enable optimisation over option type expressions (only var opt int at the moment). The absent value is defined as the worst possible solution (depending on the direction of the optimisation). --- lib/typecheck.cpp | 18 ++++++++++++++++++ share/minizinc/std/stdlib.mzn | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/lib/typecheck.cpp b/lib/typecheck.cpp index 4a16ab9df..3d3813d88 100644 --- a/lib/typecheck.cpp +++ b/lib/typecheck.cpp @@ -1423,10 +1423,28 @@ namespace MiniZinc { bu_ty.run(i->e()); if (i->e()) { Type et = i->e()->type(); + + bool needOptCoercion = et.isopt() && et.isint(); + if (needOptCoercion) { + et.ot(Type::OT_PRESENT); + } + if (! (env.isSubtype(et,Type::varint(),true) || env.isSubtype(et,Type::varfloat(),true))) throw TypeError(env, i->e()->loc(), "objective has invalid type, expected int or float, actual `"+et.toString(env)+"'"); + + if (needOptCoercion) { + GCLock lock; + std::vector args(2); + args[0] = i->e(); + args[1] = constants().boollit(i->st()==SolveI::ST_MAX); + Call* c = new Call(Location().introduce(), ASTString("objective_deopt_"), args); + c->decl(env.orig->matchFn(env, c, false)); + assert(c->decl()); + c->type(et); + i->e(c); + } } } void vOutputI(OutputI* i) { diff --git a/share/minizinc/std/stdlib.mzn b/share/minizinc/std/stdlib.mzn index 0bf398037..929093988 100644 --- a/share/minizinc/std/stdlib.mzn +++ b/share/minizinc/std/stdlib.mzn @@ -484,6 +484,13 @@ function var opt int: element(var opt int: idx, array[int] of var opt int: x) = function var opt int: element(var opt int: idx1, var opt int: idx2, array[int,int] of var opt int: x) = if absent(idx1) \/ absent(idx2) then <> else element(deopt(idx1),deopt(idx2),x) endif; +/* Internal function used to optimize over option type objective */ + +function var int: objective_deopt_(var opt int: x, bool: direction) = + let { + int: worst = if direction then lb(x)-1 else ub(x)+1 endif; + } in if occurs(x) then deopt(x) else worst endif; + /*** @groupdef options Compiler options */ From c99d71665edb5d80736fee77656aedeee9099bf3 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Wed, 14 Dec 2016 14:43:22 +0100 Subject: [PATCH 7/9] Keep temporary enum declarations in a temporary model, otherwise they won't be kept alive for GC. --- include/minizinc/typecheck.hh | 2 +- lib/typecheck.cpp | 46 +++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/minizinc/typecheck.hh b/include/minizinc/typecheck.hh index 08262c02b..7ceb5f007 100644 --- a/include/minizinc/typecheck.hh +++ b/include/minizinc/typecheck.hh @@ -39,7 +39,7 @@ namespace MiniZinc { /// Add a variable declaration void add(EnvI& env, VarDecl* vd, bool unique); /// Add a variable declaration item - void add(EnvI& env, VarDeclI* vd, bool unique, bool handleEnums, std::vector& enumItems); + void add(EnvI& env, VarDeclI* vd, bool unique, bool handleEnums, Model* enumItems); /// Remove a variable declaration void remove(EnvI& env, VarDecl* vd); /// Get variable declaration from identifier \a id diff --git a/lib/typecheck.cpp b/lib/typecheck.cpp index 3d3813d88..0a42ff376 100644 --- a/lib/typecheck.cpp +++ b/lib/typecheck.cpp @@ -64,7 +64,7 @@ namespace MiniZinc { return name; } - AssignI* createEnumMapper(EnvI& env, Model* m, unsigned int enumId, VarDecl* vd, VarDecl* vd_enumToString, std::vector& enumItems) { + AssignI* createEnumMapper(EnvI& env, Model* m, unsigned int enumId, VarDecl* vd, VarDecl* vd_enumToString, Model* enumItems) { Id* ident = vd->id(); SetLit* sl = NULL; @@ -87,7 +87,7 @@ namespace MiniZinc { Call* toEnum = new Call(sl->v()[i]->loc(), ASTString("to_enum"), toEnumArgs); toEnum->decl(env.orig->matchFn(env, toEnum, false)); VarDecl* vd_id = new VarDecl(ti_id->loc(),ti_id,sl->v()[i]->cast()->str(),toEnum); - enumItems.push_back(new VarDeclI(vd_id->loc(),vd_id)); + enumItems->addItem(new VarDeclI(vd_id->loc(),vd_id)); } SetLit* nsl = new SetLit(vd->loc(), IntSetVal::a(1,sl->v().size())); Type tt = nsl->type(); @@ -114,7 +114,7 @@ namespace MiniZinc { TypeInst* ti = new TypeInst(Location().introduce(),Type::parstring(1)); ti->setRanges(ranges); vd_enumToString = new VarDecl(Location().introduce(),ti,name,al); - enumItems.push_back(new VarDeclI(Location().introduce(),vd_enumToString)); + enumItems->addItem(new VarDeclI(Location().introduce(),vd_enumToString)); } TypeInst* ti_aa = new TypeInst(Location().introduce(),Type::parint()); @@ -133,7 +133,7 @@ namespace MiniZinc { FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,aa); - enumItems.push_back(fi); + enumItems->addItem(fi); } else { if (vd_enumToString) { /// TODO: find a better solution (don't introduce the vd_enumToString until we @@ -176,7 +176,7 @@ namespace MiniZinc { FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,ite); - enumItems.push_back(fi); + enumItems->addItem(fi); } } @@ -262,7 +262,7 @@ namespace MiniZinc { FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,let); - enumItems.push_back(fi); + enumItems->addItem(fi); } { @@ -318,14 +318,14 @@ namespace MiniZinc { FunctionI* fi = new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi,fi_params,bopp1); - enumItems.push_back(fi); + enumItems->addItem(fi); } return ret; } void - TopoSorter::add(EnvI& env, VarDeclI* vdi, bool unique, bool handleEnums, std::vector& enumItems) { + TopoSorter::add(EnvI& env, VarDeclI* vdi, bool unique, bool handleEnums, Model* enumItems) { VarDecl* vd = vdi->e(); if (handleEnums && vd->ti()->isEnum()) { unsigned int enumId = env.registerEnum(vdi); @@ -344,7 +344,7 @@ namespace MiniZinc { TypeInst* ti = new TypeInst(Location().introduce(),Type::parstring(1)); ti->setRanges(ranges); VarDecl* vd_enumToString = new VarDecl(Location().introduce(),ti,name,NULL); - enumItems.push_back(new VarDeclI(Location().introduce(),vd_enumToString)); + enumItems->addItem(new VarDeclI(Location().introduce(),vd_enumToString)); } } DeclMap::iterator vd_id = idmap.find(vd->id()); @@ -1228,7 +1228,7 @@ namespace MiniZinc { std::vector functionItems; std::vector assignItems; - std::vector enumItems; + Model* enumItems = new Model; class TSV0 : public ItemVisitor { public: @@ -1238,9 +1238,9 @@ namespace MiniZinc { bool hadSolveItem; std::vector& fis; std::vector& ais; - std::vector& enumis; + Model* enumis; TSV0(EnvI& env0, TopoSorter& ts0, Model* model0, std::vector& fis0, std::vector& ais0, - std::vector& enumis0) + Model* enumis0) : env(env0), ts(ts0), model(model0), hadSolveItem(false), fis(fis0), ais(ais0), enumis(enumis0) {} void vAssignI(AssignI* i) { ais.push_back(i); } void vVarDeclI(VarDeclI* i) { ts.add(env, i, true, true, enumis); } @@ -1256,20 +1256,21 @@ namespace MiniZinc { } _tsv0(env.envi(),ts,m,functionItems,assignItems,enumItems); iterItems(_tsv0,m); - for (unsigned int i=0; idyn_cast()) { + for (unsigned int i=0; isize(); i++) { + if (AssignI* ai = (*enumItems)[i]->dyn_cast()) { assignItems.push_back(ai); - } else if (VarDeclI* vdi = enumItems[i]->dyn_cast()) { + } else if (VarDeclI* vdi = (*enumItems)[i]->dyn_cast()) { m->addItem(vdi); ts.add(env.envi(), vdi, true, false, enumItems); } else { - FunctionI* fi = enumItems[i]->dyn_cast(); + FunctionI* fi = (*enumItems)[i]->dyn_cast(); m->addItem(fi); m->registerFn(env.envi(),fi); functionItems.push_back(fi); } } - enumItems.clear(); + + Model* enumItems2 = new Model; for (unsigned int i=0; iloc()); if (vd_enum->e()) throw TypeError(env.envi(),ai->loc(),"multiple assignment to the same variable"); - AssignI* ai_enum = createEnumMapper(env.envi(), m, vd->ti()->type().enumId(), vd, vd_enum, enumItems); + AssignI* ai_enum = createEnumMapper(env.envi(), m, vd->ti()->type().enumId(), vd, vd_enum, enumItems2); if (ai_enum) { vd_enum->e(ai_enum->e()); ai_enum->remove(); @@ -1293,18 +1294,21 @@ namespace MiniZinc { ai->remove(); } - for (unsigned int i=0; idyn_cast()) { + for (unsigned int i=0; isize(); i++) { + if (VarDeclI* vdi = (*enumItems2)[i]->dyn_cast()) { m->addItem(vdi); ts.add(env.envi(), vdi, true, false, enumItems); } else { - FunctionI* fi = enumItems[i]->cast(); + FunctionI* fi = (*enumItems2)[i]->cast(); m->addItem(fi); m->registerFn(env.envi(),fi); functionItems.push_back(fi); } } + delete enumItems; + delete enumItems2; + class TSV1 : public ItemVisitor { public: EnvI& env; From b274b59a81e8dbfe312d512422685b4ba89119dc Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Wed, 14 Dec 2016 14:44:33 +0100 Subject: [PATCH 8/9] Bump version and add change log --- CHANGES.txt | 17 ++++++++++++++++- CMakeLists.txt | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 815e93102..14f9eeb2f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,11 +5,26 @@ All bug numbers refer to the issue tracker at https://github.com/MiniZinc/libminizinc/issues -Version 2.1.0 +Version 2.1.1 ============= Changes: + - Add missing min/max functions for set variables. Can be redefined to solver + builtins using the new redefinitions-2.1.1.mzn library file. + - Add support for option type expressions as objective functions. + +Bug fixes: + - Include cmath header to fix compilation issues with some compilers. Fixes #125. + - Fix a garbage collection bug in the type checking for enumerated types that would + sometimes lead to crashes or incorrect error messages. + - Fix type checking of comprehensions that involve enumerated types. + - Fix bounds computation for var sets of enumerated types. + - Support anon_enum function as documented. +Version 2.1.0 +============= + +Changes: - MiniZinc now supports enumerated types. - Solvers can be interfaced directly to the MiniZinc library, and MiniZinc comes with direct support for the CBC, Gurobi and CPLEX MIP solvers. diff --git a/CMakeLists.txt b/CMakeLists.txt index a40dd13a0..52adbc896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ endif() # The version number. set (libminizinc_VERSION_MAJOR 2) set (libminizinc_VERSION_MINOR 1) -set (libminizinc_VERSION_PATCH 0) +set (libminizinc_VERSION_PATCH 1) if (ADDITIONAL_DATE_STRING) set (libminizinc_VERSION_PATCH "${libminizinc_VERSION_PATCH}.${ADDITIONAL_DATE_STRING}") From 50f3703284aaa77e617f3c9ab3226acc655b7319 Mon Sep 17 00:00:00 2001 From: Guido Tack Date: Wed, 14 Dec 2016 14:48:55 +0100 Subject: [PATCH 9/9] Automatically coerce arrays constructed using ++ to any enum index set (in addition to array literals and comprehensions) --- CHANGES.txt | 2 ++ lib/typecheck.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 14f9eeb2f..898996365 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,8 @@ Changes: - Add missing min/max functions for set variables. Can be redefined to solver builtins using the new redefinitions-2.1.1.mzn library file. - Add support for option type expressions as objective functions. + - Automatically coerce arrays constructed using ++ to any enum index set + (in addition to array literals and comprehensions). Bug fixes: - Include cmath header to fix compilation issues with some compilers. Fixes #125. diff --git a/lib/typecheck.cpp b/lib/typecheck.cpp index 0a42ff376..6b30d8cd7 100644 --- a/lib/typecheck.cpp +++ b/lib/typecheck.cpp @@ -1105,7 +1105,9 @@ namespace MiniZinc { if (vd.e()) { Type vdt = vd.ti()->type(); Type vet = vd.e()->type(); - if (vdt.enumId() != 0 && vdt.dim() > 0 && (vd.e()->isa() || vd.e()->isa())) { + if (vdt.enumId() != 0 && vdt.dim() > 0 && + (vd.e()->isa() || vd.e()->isa() || + (vd.e()->isa() && vd.e()->cast()->op()==BOT_PLUSPLUS))) { // Special case: index sets of array literals and comprehensions automatically // coerce to any enum index set const std::vector& enumIds = _env.getArrayEnum(vdt.enumId());