Skip to content

Commit 0bee47e

Browse files
author
Christian Schulte
committed
Cost-based variants for circuit
git-svn-id: file:///Users/tack/GecodeGitMigration/gecode-svn-mirror/gecode/trunk@9381 e85b7adc-8362-4630-8c63-7469d557c915
1 parent b331745 commit 0bee47e

File tree

5 files changed

+210
-26
lines changed

5 files changed

+210
-26
lines changed

changelog.in

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,20 @@ Date: ?
7272
[DESCRIPTION]
7373
The next release.
7474

75+
[ENTRY]
76+
Module: graph
77+
What: new
78+
Rank: minor
79+
[DESCRIPTION]
80+
Cost-based variants for circuit added.
81+
7582
[ENTRY]
7683
Module: set
7784
What: change
7885
Rank: minor
7986
[DESCRIPTION]
80-
The element constraint with an integer index variable now throws an exception
81-
if used with an empty array.
87+
The element constraint with an integer index variable now throws
88+
an exception if used with an empty array.
8289

8390
[ENTRY]
8491
Module: int

examples/tsp.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ namespace {
178178
int size(void) const;
179179
/// Return distance between node \a i and \a j
180180
int d(int i, int j) const;
181+
/// Return distances
182+
const int* d(void) const;
181183
/// Return estimate for maximal cost of a path
182184
int max(void) const;
183185
};
@@ -193,6 +195,10 @@ namespace {
193195
Problem::d(int i, int j) const {
194196
return _d[i*_n+j];
195197
}
198+
inline const int*
199+
Problem::d(void) const {
200+
return _d;
201+
}
196202
inline int
197203
Problem::max(void) const {
198204
int m=0;
@@ -234,31 +240,25 @@ class TSP : public MinimizeScript {
234240
: p(ps[opt.size()]),
235241
succ(*this, p.size(), 0, p.size()-1),
236242
total(*this, 0, p.max()) {
243+
int n = p.size();
237244

238-
// Cost of each edge
239-
IntVarArgs costs(p.size());
240-
// Distances
241-
IntArgs d(p.size());
245+
// Cost matrix
246+
IntArgs c(n*n, p.d());
242247

243-
// Setup costs for edges
244-
for (int i=p.size(); i--; ) {
245-
int m=0;
246-
for (int j=p.size(); j--; ) {
247-
d[j] = p.d(i,j);
248-
m = std::max(m, d[j]);
249-
if (d[j] == 0)
248+
for (int i=n; i--; )
249+
for (int j=n; j--; )
250+
if (p.d(i,j) == 0)
250251
rel(*this, succ[i], IRT_NQ, j);
251-
}
252-
costs[i].init(*this,0,m);
253-
// Propagate cost for chosen edge
254-
element(*this, d, succ[i], costs[i]);
255-
}
256252

257-
// Cost ist sume of all costs
258-
linear(*this, costs, IRT_EQ, total);
253+
// Cost of each edge
254+
IntVarArgs costs(n);
255+
256+
// Initialize cost variables for edges
257+
for (int i=n; i--; )
258+
costs[i].init(*this, Int::Limits::min, Int::Limits::max);
259259

260-
// Enforce that the succesors yield a tour
261-
circuit(*this, succ, opt.icl());
260+
// Enforce that the succesors yield a tour with appropriate costs
261+
circuit(*this, c, succ, costs, total, opt.icl());
262262

263263
// Just assume that the circle starts forwards
264264
rel(*this, succ[0], IRT_LE, succ[1]);

gecode/graph.hh

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,62 @@ namespace Gecode {
9191
* other values for \a icl), where this refers to whether value or
9292
* domain consistent distinct in enforced on \a x.
9393
*
94-
* Throws an exception of type Int::ArgumentSame, if \a x
95-
* contains the same unassigned variable multiply.
94+
* Throws the following exceptions:
95+
* - Int::ArgumentSame, if \a x contains the same unassigned variable
96+
* multiply.
97+
* - Int::TooFewArguments, if \a x has no elements.
9698
*/
9799
GECODE_GRAPH_EXPORT void
98100
circuit(Space& home, const IntVarArgs& x,
99101
IntConLevel icl=ICL_DEF);
102+
/** \brief Post propagator such that \a x forms a circuit with costs \a y and \a z
103+
*
104+
* \a x forms a circuit if the graph with edges \f$i\to j\f$ where
105+
* \f$x_i=j\f$ has a single cycle covering all nodes. The integer array
106+
* \a c gives the costs of all possible edges where \f$c_{i*|x|+j}\f$ is
107+
* the cost of the edge \f$i\to j\f$. The variable \a z is the cost of
108+
* the entire circuit. The variables \a y define the cost
109+
* of the edge in \a x: that is, if \f$x_i=j\f$ then \f$y_i=c_{i*n+j}\f$.
110+
*
111+
* Supports domain (\a icl = ICL_DOM) and value propagation (all
112+
* other values for \a icl), where this refers to whether value or
113+
* domain consistent distinct in enforced on \a x for circuit.
114+
*
115+
* Throws the following exceptions:
116+
* - Int::ArgumentSame, if \a x contains the same unassigned variable
117+
* multiply.
118+
* - Int::TooFewArguments, if \a x has no elements.
119+
* - Int::ArgumentSizeMismacth, if \a x and \a y do not have the same
120+
* size or if \f$|x|\times|x|\neq|c|\f$.
121+
*/
122+
GECODE_GRAPH_EXPORT void
123+
circuit(Space& home,
124+
const IntArgs& c,
125+
const IntVarArgs& x, const IntVarArgs& y, IntVar z,
126+
IntConLevel icl=ICL_DEF);
127+
/** \brief Post propagator such that \a x forms a circuit with cost \a z
128+
*
129+
* \a x forms a circuit if the graph with edges \f$i\to j\f$ where
130+
* \f$x_i=j\f$ has a single cycle covering all nodes. The integer array
131+
* \a c gives the costs of all possible edges where \f$c_{i*|x|+j}\f$ is
132+
* the cost of the edge \f$i\to j\f$. The variable \a z is the cost of
133+
* the entire circuit.
134+
*
135+
* Supports domain (\a icl = ICL_DOM) and value propagation (all
136+
* other values for \a icl), where this refers to whether value or
137+
* domain consistent distinct in enforced on \a x for circuit.
138+
*
139+
* Throws the following exceptions:
140+
* - Int::ArgumentSame, if \a x contains the same unassigned variable
141+
* multiply.
142+
* - Int::TooFewArguments, if \a x has no elements.
143+
* - Int::ArgumentSizeMismacth, if \f$|x|\times|x|\neq|c|\f$.
144+
*/
145+
GECODE_GRAPH_EXPORT void
146+
circuit(Space& home,
147+
const IntArgs& c,
148+
const IntVarArgs& x, IntVar z,
149+
IntConLevel icl=ICL_DEF);
100150
//@}
101151

102152
}

gecode/graph/circuit.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ namespace Gecode {
4343
circuit(Space& home, const IntVarArgs& x, IntConLevel icl) {
4444
if (x.same(home))
4545
throw Int::ArgumentSame("Graph::circuit");
46-
if (home.failed()) return;
4746
if (x.size() == 0)
48-
return;
47+
throw Int::TooFewArguments("Graph::circuit");
48+
if (home.failed()) return;
4949
ViewArray<Int::IntView> xv(home,x);
5050
if (icl == ICL_DOM) {
5151
GECODE_ES_FAIL(home,Graph::Circuit::Dom<Int::IntView>::post(home,xv));
@@ -54,6 +54,35 @@ namespace Gecode {
5454
}
5555
}
5656

57+
void
58+
circuit(Space& home, const IntArgs& c,
59+
const IntVarArgs& x, const IntVarArgs& y, IntVar z,
60+
IntConLevel icl) {
61+
int n = x.size();
62+
if ((y.size() != n) || (c.size() != n*n))
63+
throw Int::ArgumentSizeMismatch("Graph::circuit");
64+
circuit(home, x, icl);
65+
if (home.failed()) return;
66+
IntArgs cx(n);
67+
for (int i=n; i--; ) {
68+
for (int j=0; j<n; j++)
69+
cx[j] = c[i*n+j];
70+
element(home, cx, x[i], y[i]);
71+
}
72+
linear(home, y, IRT_EQ, z);
73+
}
74+
75+
void
76+
circuit(Space& home, const IntArgs& c,
77+
const IntVarArgs& x, IntVar z,
78+
IntConLevel icl) {
79+
if (home.failed()) return;
80+
IntVarArgs y(x.size());
81+
for (int i=x.size(); i--; )
82+
y[i].init(home, Int::Limits::min, Int::Limits::max);
83+
circuit(home, c, x, y, z);
84+
}
85+
5786
}
5887

5988
// STATISTICS: graph-post

test/int/circuit.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,100 @@ namespace Test { namespace Int {
8080
}
8181
};
8282

83+
/// Simple test for circuit constraint with total cost
84+
class CircuitCost : public Test {
85+
public:
86+
/// Create and register test
87+
CircuitCost(int n, int min, int max, Gecode::IntConLevel icl)
88+
: Test("Circuit::Cost::" + str(icl) + "::" + str(n),
89+
n+1,min,max,false,icl) {
90+
contest = CTL_NONE;
91+
}
92+
/// Check whether \a x is solution
93+
virtual bool solution(const Assignment& x) const {
94+
int n=x.size()-1;
95+
for (int i=n; i--; )
96+
if ((x[i] < 0) || (x[i] > n-1))
97+
return false;
98+
int reachable = 0;
99+
{
100+
int j=0;
101+
for (int i=n; i--; ) {
102+
j=x[j]; reachable |= (1 << j);
103+
}
104+
}
105+
for (int i=n; i--; )
106+
if (!(reachable & (1 << i)))
107+
return false;
108+
int c=0;
109+
for (int i=n; i--; )
110+
c += x[i];
111+
return c == x[n];
112+
}
113+
/// Post circuit constraint on \a x
114+
virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
115+
using namespace Gecode;
116+
int n=x.size()-1;
117+
IntArgs c(n*n);
118+
for (int i=0; i<n; i++)
119+
for (int j=0; j<n; j++)
120+
c[i*n+j]=j;
121+
IntVarArgs y(n);
122+
for (int i=0; i<n; i++)
123+
y[i]=x[i];
124+
circuit(home, c, y, x[n], icl);
125+
}
126+
};
127+
128+
/// Simple test for circuit constraint with full cost information
129+
class CircuitFullCost : public Test {
130+
public:
131+
/// Create and register test
132+
CircuitFullCost(int n, int min, int max, Gecode::IntConLevel icl)
133+
: Test("Circuit::FullCost::" + str(icl) + "::" + str(n),
134+
2*n+1,min,max,false,icl) {
135+
contest = CTL_NONE;
136+
}
137+
/// Check whether \a x is solution
138+
virtual bool solution(const Assignment& x) const {
139+
int n=(x.size()-1) / 2;
140+
for (int i=n; i--; )
141+
if ((x[i] < 0) || (x[i] > n-1))
142+
return false;
143+
int reachable = 0;
144+
{
145+
int j=0;
146+
for (int i=n; i--; ) {
147+
j=x[j]; reachable |= (1 << j);
148+
}
149+
}
150+
for (int i=n; i--; )
151+
if (!(reachable & (1 << i)))
152+
return false;
153+
for (int i=n; i--; )
154+
if ((x[i]/2) != x[n+i])
155+
return false;
156+
int c=0;
157+
for (int i=n; i--; )
158+
c += x[n+i];
159+
return c == x[2*n];
160+
}
161+
/// Post circuit constraint on \a x
162+
virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
163+
using namespace Gecode;
164+
int n=(x.size()-1)/2;
165+
IntArgs c(n*n);
166+
for (int i=0; i<n; i++)
167+
for (int j=0; j<n; j++)
168+
c[i*n+j]=(j/2);
169+
IntVarArgs y(n), z(n);
170+
for (int i=0; i<n; i++) {
171+
y[i]=x[i]; z[i]=x[n+i];
172+
}
173+
circuit(home, c, y, z, x[2*n], icl);
174+
}
175+
};
176+
83177
/// Help class to create and register tests
84178
class Create {
85179
public:
@@ -89,6 +183,10 @@ namespace Test { namespace Int {
89183
(void) new Circuit(i,0,i-1,Gecode::ICL_VAL);
90184
(void) new Circuit(i,0,i-1,Gecode::ICL_DOM);
91185
}
186+
(void) new CircuitCost(4,0,9,Gecode::ICL_VAL);
187+
(void) new CircuitCost(4,0,9,Gecode::ICL_DOM);
188+
(void) new CircuitFullCost(3,0,3,Gecode::ICL_VAL);
189+
(void) new CircuitFullCost(3,0,3,Gecode::ICL_DOM);
92190
}
93191
};
94192

0 commit comments

Comments
 (0)