Skip to content

Commit 372c660

Browse files
Mikael Zayenz Lagerkvistzayenz
authored andcommitted
Complete GCC solution-loss fix
1 parent b1aa4e4 commit 372c660

3 files changed

Lines changed: 33 additions & 10 deletions

File tree

changelog.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ Rank: major
8282
Issue: 166
8383
Thanks: Mats Carlsson
8484
[DESCRIPTION]
85-
Fix domain-level global cardinality propagation losing solutions when search
86-
recomputation applies several branch choices before propagation.
85+
Fix domain-level global cardinality propagation losing solutions by counting
86+
assigned variables twice and retaining stale conflict marks when cardinality
87+
bounds shrink.
8788

8889
[ENTRY]
8990
Module: flatzinc

gecode/int/gcc/dom-sup.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,8 @@ namespace Gecode { namespace Int { namespace GCC {
12681268
v->maxlow(k[i].max() - (inc_lbc));
12691269
if (v->kmin() == v->kmax())
12701270
v->cap(LBC,k[i].max() - (inc_lbc));
1271-
v->card_conflict(rm);
1271+
int matched = inc_ubc - v->kcount();
1272+
v->card_conflict(std::min(rm, matched));
12721273
}
12731274
}
12741275
}

test/flatzinc/issue166.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,42 @@
3535
namespace Test { namespace FlatZinc {
3636

3737
namespace {
38-
/// Check that recomputation does not lose a solution
39-
bool check(const std::string& output) {
38+
/// Check that recomputation does not lose solutions
39+
bool check(const std::string& output, int expected,
40+
const std::string& representative) {
4041
const std::string separator = "----------\n";
4142
int solutions = 0;
4243
for (std::string::size_type p = 0;
4344
(p = output.find(separator,p)) != std::string::npos;
4445
p += separator.size())
4546
solutions++;
46-
return (solutions == 11) &&
47-
(output.find("A = 3;\nB = 1;\nC = 3;\nD = 1;\nE = 2;\nG = 3;\n")
48-
!= std::string::npos);
47+
return (solutions == expected) &&
48+
(output.find(representative) != std::string::npos);
4949
}
5050

5151
/// Helper class to create and register test
5252
class Create {
5353
public:
5454
/// Perform creation and registration
5555
Create(void) {
56-
(void) new FlatZincTest("Issue166",
56+
(void) new FlatZincTest("Issue166::Original",
57+
"predicate gecode_global_cardinality(array [int] of var int: x, array [int] of int: cover, array [int] of var int: counts);\n\
58+
var {1,3}: A :: output_var;\n\
59+
var 2..3: B :: output_var;\n\
60+
var 2..3: C :: output_var;\n\
61+
var 2..3: D :: output_var;\n\
62+
var 2..5: E :: output_var;\n\
63+
var 1..4: F :: output_var;\n\
64+
var 2..3: G :: output_var;\n\
65+
var 2..3: H :: output_var;\n\
66+
constraint gecode_global_cardinality([A,D,1,3,3,C,1,H,B],[1,2,3],[G,F,E]) :: domain;\n\
67+
solve :: int_search([A,B,C,D,E,F,G,H],anti_first_fail,indomain_min,complete) satisfy;\n",
68+
"", true, {"-a"}, [] (const std::string& output) {
69+
return check(output, 26,
70+
"A = 1;\nB = 2;\nC = 3;\nD = 3;\nE = 5;\n"
71+
"F = 1;\nG = 3;\nH = 3;\n");
72+
});
73+
(void) new FlatZincTest("Issue166::Minimized",
5774
"predicate gecode_global_cardinality(array [int] of var int: x, array [int] of int: cover, array [int] of var int: counts);\n\
5875
var 1..3: A :: output_var;\n\
5976
var 1..3: B :: output_var;\n\
@@ -63,7 +80,11 @@ var 2..3: E :: output_var;\n\
6380
var 2..3: G :: output_var;\n\
6481
constraint gecode_global_cardinality([3,A,D,G,E],[1,2,3],[1,B,C]) :: domain;\n\
6582
solve :: int_search([D,A,E,B],input_order,indomain_random,complete) satisfy;\n",
66-
"", true, {"-a", "-r", "0", "-c-d", "8"}, check);
83+
"", true, {"-a", "-r", "0", "-c-d", "8"},
84+
[] (const std::string& output) {
85+
return check(output, 11,
86+
"A = 3;\nB = 1;\nC = 3;\nD = 1;\nE = 2;\nG = 3;\n");
87+
});
6788
}
6889
};
6990

0 commit comments

Comments
 (0)