Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion parsers/src/test/resources/flatzinc/hard_instances.csv
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#year,name,solutions,best,nodes,fails
2020,skill_allocation+mzn_1m_1.fzn,1,2,6196,6195
2020,stable-goods-solution+s-d6.fzn,13,6264,146933,146908
2018,rotating-workforce+ex1479.fzn,1,_,125855,125753
2018,rotating-workforce+ex1479.fzn,1,_,125773,125671
2016,tpp+6_3_20_1.fzn,65,131,2813024,2812895
2012,still-life-wastage+still-life+09.fzn,5,43,109471,109462
2012,still-life-wastage+still-life+10.fzn,7,54,164574,164561
Expand Down
6 changes: 3 additions & 3 deletions parsers/src/test/resources/xcsp/instances.csv
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ basics;Ramsey-12.xml.lzma;54;2;57445;33115
basics;Rcpsp-j30-01-01_c18.xml.lzma;7;43;199;162
basics;Rlfap-graph-04-opt_c18.xml.lzma;10;394;2651;1656
basics;RoomMate-sr0050-int.xml.lzma;1;_;2;0
basics;SocialGolfers-4-3-4-cp.xml.lzma;1;_;249;177
basics;SocialGolfers-4-3-4-cp.xml.lzma;1;_;227;161
#basics;Sonet-s2ring02.xml.lzma;9;14;815744;621835
basics;SportsScheduling-08.xml.lzma;1;_;210;168
basics;SportsScheduling-08.xml.lzma;1;_;181;150
basics;SteelMillSlab-m1-simple_c18.xml.lzma;4;0;221;180
basics;SteelMillSlab-m2-simple_c18.xml.lzma;2;0;228;196
basics;SteelMillSlab-m2s-mini-simple_c18.xml.lzma;1;0;127;50
Expand All @@ -99,6 +99,6 @@ basics;testObjective1.xml.lzma;2;11;8;5
basics;testPrimitive.xml.lzma;1;_;3;1
#basics;TestSchedulingM18-t30m10r3-15.xml.lzma;93;4149;3450;2650
basics;Tpp-3-3-20-1.xml.lzma;9;126;273;217
basics;TravelingTournament-a3-galaxy04_c18.xml.lzma;6;416;3765;3425
basics;TravelingTournament-a3-galaxy04_c18.xml.lzma;6;416;3693;3378
basics;Warehouse-opl.xml.lzma;19;383;130;90
basics;Zebra.xml.lzma;1;_;9;2
Original file line number Diff line number Diff line change
Expand Up @@ -1779,14 +1779,51 @@ default Constraint element(IntVar value, IntVar[] table, IntVar index, int offse
* Creates a global cardinality constraint (GCC):
* Each value values[i] should be taken by exactly occurrences[i] variables of vars.
* <br/>
* This constraint does not ensure any well-defined level of consistency, yet.
* Uses {@link GlobalCardinality#defaultConsistency()} (see
* {@link #globalCardinality(IntVar[], int[], IntVar[], boolean, String)}) — {@code "BC"}
* unless overridden via the {@value GlobalCardinality#CONSISTENCY_PROPERTY} system property.
*
* @param vars collection of variables
* @param values collection of constrained values
* @param occurrences collection of cardinality variables
* @param closed restricts domains of vars to values if set to true
*/
default Constraint globalCardinality(IntVar[] vars, int[] values, IntVar[] occurrences, boolean closed) {
return globalCardinality(vars, values, occurrences, closed,
GlobalCardinality.defaultConsistency().name());
}

/**
* Creates a global cardinality constraint (GCC):
* Each value values[i] should be taken by exactly occurrences[i] variables of vars.
*
* @param vars collection of variables
* @param values collection of constrained values
* @param occurrences collection of cardinality variables
* @param closed restricts domains of vars to values if set to true
* @param consistency consistency level, among {"DEFAULT", "BC", "AC"}
* <p>
* <b>DEFAULT</b>:
* <br/>
* Fast filtering, without any well-defined level of consistency.
* <p>
* <b>BC</b>:
* <br/>
* Bound-consistency, based on:
* C.-G. Quimper, P. van Beek, A. Lopez-Ortiz, A. Golynski, and S.B. Sadjad.
* "An efficient bounds consistency algorithm for the global cardinality
* constraint." CP-2003.
* Posted in addition to the {@code "DEFAULT"} filtering.
* <p>
* <b>AC</b>:
* <br/>
* Arc-consistency, based on:
* J.-C. Regin. "Generalized Arc Consistency for Global Cardinality
* Constraint." AAAI-96.
* Posted in addition to the {@code "DEFAULT"} filtering.
*/
default Constraint globalCardinality(IntVar[] vars, int[] values, IntVar[] occurrences,
boolean closed, String consistency) {
if (ref().getSolver().isLCG()) {
if (ref().getSettings().warnUser()) {
ref().getSolver().log().white().println("Warning: globalCardinality constraint is decomposed (due to LCG).");
Expand Down Expand Up @@ -1827,10 +1864,10 @@ default Constraint globalCardinality(IntVar[] vars, int[] values, IntVar[] occur
v2[i] = toAdd.get(i - values.length);
cards[i] = vars[0].getModel().intVar(0);
}
return new GlobalCardinality(vars, v2, cards);
return new GlobalCardinality(vars, v2, cards, consistency);
}
}
return new GlobalCardinality(vars, values, occurrences);
return new GlobalCardinality(vars, values, occurrences, consistency);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,74 @@
*/
public class GlobalCardinality extends Constraint {

/**
* Consistency level enforced by the propagator(s) posted for a {@link GlobalCardinality}
* constraint.
*/
public enum Consistency {
/**
* Fast filtering (see {@link PropFastGCC}), without any well-defined consistency level
* guarantee.
*/
DEFAULT,
/**
* Bound-consistency (see {@link PropGcc}), following:
* C.-G. Quimper, P. van Beek, A. Lopez-Ortiz, A. Golynski, and S.B. Sadjad.
* "An efficient bounds consistency algorithm for the global cardinality constraint."
* CP-2003.
*/
BC,
/**
* Arc-consistency (see {@link PropGcc}), following:
* J.-C. Regin. "Generalized Arc Consistency for Global Cardinality Constraint." AAAI-96.
*/
AC
}

/**
* System property used to override the default {@link Consistency} level, e.g.
* {@code -Dchoco.gcc.consistency=AC}. See {@link #defaultConsistency()}.
*/
public static final String CONSISTENCY_PROPERTY = "choco.gcc.consistency";

/**
* Returns the {@link Consistency} level used when none is explicitly specified, e.g. by
* {@link #GlobalCardinality(IntVar[], int[], IntVar[])} or by
* {@link org.chocosolver.solver.constraints.IIntConstraintFactory#globalCardinality(IntVar[], int[], IntVar[], boolean)}.
* <p>
* Defaults to {@link Consistency#BC}, which matches or beats {@link Consistency#AC} on
* solution quality while being cheaper to propagate, and both markedly outperform
* {@link Consistency#DEFAULT} on tightly-constrained instances.
* <p>
* Can be overridden via the {@value #CONSISTENCY_PROPERTY} system property (e.g. to
* benchmark alternative filtering levels without changing calling code).
*
* @return the default consistency level
* @throws IllegalArgumentException if the {@value #CONSISTENCY_PROPERTY} property is set to
* a value that is not a valid {@link Consistency} name
*/
public static Consistency defaultConsistency() {
return Consistency.valueOf(System.getProperty(CONSISTENCY_PROPERTY, Consistency.BC.name()));
}

/**
* Creates a global cardinality constraint using the {@linkplain #defaultConsistency() default
* consistency level}.
*
* @param vars collection of variables
* @param values collection of constrained values
* @param cards collection of cardinality variables
*/
public GlobalCardinality(IntVar[] vars, int[] values, IntVar[] cards) {
super(ConstraintsName.GCC, createProp(vars, values, cards));
this(vars, values, cards, defaultConsistency().name());
}

public GlobalCardinality(IntVar[] vars, int[] values, IntVar[] cards, String consistency) {
super(ConstraintsName.GCC, createProp(vars, values, cards, Consistency.valueOf(consistency)));
}

private static Propagator<IntVar> createProp(IntVar[] vars, int[] values, IntVar[] cards) {
private static Propagator<IntVar>[] createProp(IntVar[] vars, int[] values, IntVar[] cards,
Consistency consistency) {
assert values.length == cards.length;
TIntIntHashMap map = new TIntIntHashMap();
int idx = 0;
Expand All @@ -41,7 +104,16 @@ private static Propagator<IntVar> createProp(IntVar[] vars, int[] values, IntVar
throw new UnsupportedOperationException("ERROR: multiple occurrences of value: " + v);
}
}
return new PropFastGCC(vars, values, map, cards);
PropFastGCC fast = new PropFastGCC(vars, values, map, cards);
switch (consistency) {
case BC:
case AC:
//noinspection unchecked
return new Propagator[]{fast, new PropGcc(vars, values, cards, consistency)};
default:
//noinspection unchecked
return new Propagator[]{fast};
}
}

public static Constraint reformulate(IntVar[] vars, IntVar[] card, Model model) {
Expand Down
Comment thread
cprudhom marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* This file is part of choco-solver, http://choco-solver.org/
* Copyright (c) 1999, IMT Atlantique.
* SPDX-License-Identifier: BSD-3-Clause.
* See LICENSE file in the project root for full license information.
*/
package org.chocosolver.solver.constraints.nary.globalcardinality;

import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.constraints.PropagatorPriority;
import org.chocosolver.solver.constraints.nary.globalcardinality.GlobalCardinality.Consistency;
import org.chocosolver.solver.constraints.nary.globalcardinality.algo.AlgoGccAC;
import org.chocosolver.solver.constraints.nary.globalcardinality.algo.AlgoGccBC;
import org.chocosolver.solver.constraints.nary.globalcardinality.algo.GccFilter;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.events.IntEventType;
import org.chocosolver.util.ESat;
import org.chocosolver.util.tools.ArrayUtils;

import java.util.Arrays;

/**
* Consistency propagator for the Global Cardinality Constraint (GCC), enforcing either:
* <ul>
* <li>{@link Consistency#BC}: C.-G. Quimper, P. van Beek, A. Lopez-Ortiz, A. Golynski, and
* S.B. Sadjad. "An efficient bounds consistency algorithm for the global cardinality
* constraint." CP-2003.</li>
* <li>{@link Consistency#AC}: J.-C. Regin. "Generalized Arc Consistency for Global
* Cardinality Constraint." AAAI-96.</li>
* </ul>
* The two levels only differ in which {@link GccFilter} drives {@link #propagate(int)}, at which
* {@link PropagatorPriority}, and in which domain events wake this propagator up
* ({@link #getPropagationConditions(int)}); everything else, including the construction of the
* dense per-value occurrence bounds consumed by the filter, is shared.
* <p>
* Meant to be posted alongside {@link PropFastGCC}, which is left in charge of tightening the
* bounds of the cardinality variables and of the soundness/completeness of the constraint; this
* propagator only brings its consistency level on the decision variables.
*
* @author Charles Prud'homme
*/
public class PropGcc extends Propagator<IntVar> {

//***********************************************************************************
// VARIABLES
//***********************************************************************************

private final int n;
private final int n2;
private final int[] values;
private final GccFilter filter;
private final Consistency consistency;

//***********************************************************************************
// CONSTRUCTORS
//***********************************************************************************

/**
* @param decvars array of decision variables
* @param restrictedValues array of restricted values
* @param valueCardinalities array of cardinality variables, one per restricted value
* @param consistency consistency level to enforce, {@link Consistency#BC} or
* {@link Consistency#AC}
*/
public PropGcc(IntVar[] decvars, int[] restrictedValues, IntVar[] valueCardinalities,
Consistency consistency) {
super(ArrayUtils.append(decvars, valueCardinalities), priorityOf(consistency), false);
this.values = restrictedValues;
this.n = decvars.length;
this.n2 = values.length;
this.consistency = consistency;
this.filter = switch (consistency) {
case BC -> new AlgoGccBC(this);
case AC -> new AlgoGccAC(this);
case DEFAULT -> throw new IllegalArgumentException(
"PropGcc only supports Consistency.BC or Consistency.AC, not DEFAULT " +
"(handled by PropFastGCC alone)");
};
filter.reset(decvars);
}

private static PropagatorPriority priorityOf(Consistency consistency) {
// BC (Quimper et al.) is near-linear; AC (Regin) rebuilds/repairs a flow, quadratic-ish.
return consistency == Consistency.BC ? PropagatorPriority.LINEAR : PropagatorPriority.QUADRATIC;
}

//***********************************************************************************
// PROPAGATION
//***********************************************************************************

@Override
public void propagate(int evtmask) throws ContradictionException {
int gMin = Integer.MAX_VALUE;
int gMax = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
gMin = Math.min(gMin, vars[i].getLB());
gMax = Math.max(gMax, vars[i].getUB());
}
for (int v : values) {
gMin = Math.min(gMin, v);
gMax = Math.max(gMax, v);
}
int range = gMax - gMin + 1;
int[] minOcc = new int[range];
int[] maxOcc = new int[range];
// values out of the restricted list are unconstrained: [0, n]
Arrays.fill(maxOcc, n);
for (int i = 0; i < n2; i++) {
IntVar card = vars[n + i];
int idx = values[i] - gMin;
minOcc[idx] = card.getLB();
maxOcc[idx] = card.getUB();
}
filter.filter(minOcc, maxOcc, gMin);
}

//***********************************************************************************
// INFO
//***********************************************************************************

@Override
public int getPropagationConditions(int vIdx) {
// BC (Quimper et al.) only reasons on bounds; AC needs fine domain events to be sound
// on enumerated domains, so it keeps the default (all events).
return consistency == Consistency.BC ? IntEventType.boundAndInst() : super.getPropagationConditions(vIdx);
}

@Override
public ESat isEntailed() {
return ESat.TRUE; // redundant propagator, PropFastGCC already checks correctness
}

@Override
public String toString() {
StringBuilder st = new StringBuilder();
st.append("PropGcc_").append(consistency).append("_(");
int i = 0;
for (; i < Math.min(4, vars.length); i++) {
st.append(vars[i].getName()).append(", ");
}
if (i < vars.length - 2) {
st.append("...,");
}
st.append(vars[vars.length - 1].getName()).append(")");
return st.toString();
}

}
Loading
Loading