00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <gecode/driver.hh>
00039 #include <gecode/int.hh>
00040 #include <gecode/minimodel.hh>
00041
00042 using namespace Gecode;
00043
00049 class EFPAOptions : public Options {
00050 private:
00051 Driver::UnsignedIntOption _v;
00052 Driver::UnsignedIntOption _q;
00053 Driver::UnsignedIntOption _l;
00054 Driver::UnsignedIntOption _d;
00055 Driver::StringOption _permutation;
00056 Driver::StringOption _symmetry;
00057
00058 public:
00060 EFPAOptions(const char* s,
00061 int v0 = 5, int q0 = 3, int lambda0 = 2, int d0 = 4)
00062 : Options(s),
00063 _v("-v", "number of sequences", v0 ),
00064 _q("-q", "number of symbols", q0 ),
00065 _l("-l", "sets of symbols per sequence (lambda)", lambda0),
00066 _d("-d", "Hamming distance between sequences", d0 ),
00067 _permutation("-permutation", "use permutation constraints if d=4",
00068 false),
00069 _symmetry("-symmetry", "use symmetry breaking",
00070 true)
00071 {
00072
00073 add(_d);
00074 add(_l);
00075 add(_q);
00076 add(_v);
00077 add(_permutation);
00078 add(_symmetry);
00079
00080
00081 _permutation.add(true, "true" );
00082 _permutation.add(false, "false");
00083
00084 _symmetry.add(true, "true" );
00085 _symmetry.add(false, "false");
00086 }
00088 void parse(int& argc, char* argv[]) {
00089 Options::parse(argc,argv);
00090 }
00092 int v(void) const { return _v.value(); }
00094 int q(void) const { return _q.value(); }
00096 int l(void) const { return _l.value(); }
00098 int d(void) const { return _d.value(); }
00099
00101 bool permutation(void) const { return d() == 4 && _permutation.value(); }
00103 bool symmetry(void) const { return _symmetry.value(); }
00104 };
00105
00106
00121 class EFPA : public Script {
00122 protected:
00123 int v;
00124 int q;
00125 int l;
00126 int d;
00127 int n;
00128 int nseqpair;
00129 IntVarArray c;
00130 BoolVarArray diff;
00131
00132 public:
00134 EFPA(const EFPAOptions& opt)
00135 : v(opt.v()),
00136 q(opt.q()),
00137 l(opt.l()),
00138 d(opt.d()),
00139 n(q*l),
00140 nseqpair((v*(v-1))/2),
00141 c(*this, n*v, 1,q),
00142 diff(*this, n*nseqpair, 0, 1)
00143 {
00144
00145
00146 Matrix<IntVarArray> cm(c, n, v);
00147
00148 Matrix<BoolVarArray> diffm(diff, n, nseqpair);
00149
00150
00151 {
00152 IntArgs values(q);
00153 for (int i = q; i--; ) values[i] = i+1;
00154 IntSet cardinality(l, l);
00155 for (int i = v; i--; )
00156 count(*this, cm.row(i), cardinality, values, opt.icl());
00157 }
00158
00159
00160 {
00161 int nseqi = 0;
00162 for (int a = 0; a < v; ++a) {
00163 for (int b = a+1; b < v; ++b) {
00164 for (int i = n; i--; ) {
00165 rel(*this, cm(i, a), IRT_NQ, cm(i, b), diffm(i, nseqi));
00166 }
00167 ++nseqi;
00168 }
00169 }
00170 assert(nseqi == nseqpair);
00171 }
00172
00173
00174 {
00175 for (int i = nseqpair; i--; ) {
00176 linear(*this, diffm.row(i), IRT_EQ, d);
00177 }
00178 }
00179
00180
00181 if (opt.symmetry()) {
00182 IntRelType row_less = d==0 ? IRT_EQ : IRT_LE;
00183
00184 for (int r = 0; r<v-1; ++r) {
00185 rel(*this, cm.row(r), row_less, cm.row(r+1));
00186 }
00187
00188 for (int c = 0; c<n-1; ++c) {
00189 rel(*this, cm.col(c), IRT_LQ, cm.col(c+1));
00190 }
00191
00192 int color = 1;
00193 int ncolor = 0;
00194 for (int c = 0; c < n; ++c) {
00195 rel(*this, cm(c, 0), IRT_EQ, color);
00196 if (++ncolor == l) {
00197 ncolor = 0;
00198 ++color;
00199 }
00200 }
00201 }
00202
00203
00204 if (opt.permutation()) {
00205 const int k[][4] = {
00206 {0, 1, 3, 2},
00207 {1, 2, 3, 0},
00208 };
00209 assert(d == 4);
00210
00211 for (int r1 = 0; r1 < v; ++r1) {
00212 for (int r2 = r1+1; r2 < v; ++r2) {
00213 IntVarArgs row1 = cm.row(r1);
00214 IntVarArgs row2 = cm.row(r2);
00215
00216 IntVarArgs perm(d);
00217 for (int i = d; i--; ) perm[i] = IntVar(*this, 0, n-1);
00218
00219 IntVar cform(*this, 0, 1);
00220 BoolVar cformb = channel(*this, cform);
00221
00222
00223
00224 IntVarArgs _p(2*d);
00225 for (int i = 2*d; i--; ) _p[i] = IntVar(*this, 1, q);
00226 Matrix<IntVarArgs> p(_p, d, 2);
00227 for (int i = 0; i < 2; ++i) {
00228 for (int j = 0; j < d; ++j) {
00229 element(*this, row1, perm[k[i][j]], p(j, i));
00230 }
00231 }
00232
00233
00234 for (int i = 0; i < d; ++i) {
00235 IntVar index(*this, 0, 2*d);
00236 post(*this, cform*d + i == index);
00237 IntVar value(*this, 1, q);
00238 element(*this, _p, index, value);
00239 element(*this, row2, perm[i], value);
00240 }
00241
00242
00243
00244 BoolVarArray p1b(*this, n, 0, 1);
00245 channel(*this, p1b, perm[0]);
00246 BoolVarArray p2b(*this, n, 0, 1);
00247 channel(*this, p2b, perm[1]);
00248 BoolVarArray p3b(*this, n, 0, 1);
00249 channel(*this, p3b, perm[2]);
00250 BoolVarArray p4b(*this, n, 0, 1);
00251 channel(*this, p4b, perm[3]);
00252 for (int i = n; i--; ) {
00253
00254
00255 post(*this, tt(eqv(!p1b[i] && !p2b[i] && !p3b[i] && !p4b[i],
00256 ~(row1[i] == row2[i]))));
00257 }
00258
00259
00260
00261 rel(*this, perm[0], IRT_NQ, perm[1]);
00262 rel(*this, perm[2], IRT_NQ, perm[3]);
00263
00264
00265 rel(*this, perm[0], IRT_NQ, perm[2], cformb);
00266 rel(*this, perm[0], IRT_NQ, perm[3], cformb);
00267 rel(*this, perm[1], IRT_NQ, perm[2], cformb);
00268 rel(*this, perm[1], IRT_NQ, perm[3], cformb);
00269
00270 rel(*this, perm[0], IRT_LE, perm[1]);
00271 rel(*this, perm[0], IRT_LE, perm[2]);
00272 rel(*this, perm[0], IRT_LE, perm[3]);
00273
00274 post(*this, tt(imp(!cformb,
00275 ~(perm[2] < perm[3]))));
00276 }
00277 }
00278 }
00279
00280
00281 branch(*this, c, INT_VAR_NONE, INT_VAL_MIN);
00282 }
00283
00285 virtual void
00286 print(std::ostream& os) const {
00287 Matrix<IntVarArray> cm(c, n, v);
00288 for (int i = 0; i < v; ++i) {
00289 IntVarArgs r = cm.row(i);
00290 os << r << std::endl;
00291 }
00292 os << std::endl;
00293 }
00294
00296 EFPA(bool share, EFPA& s)
00297 : Script(share,s),
00298 v(s.v),
00299 q(s.q),
00300 l(s.l),
00301 d(s.d),
00302 n(s.n),
00303 nseqpair(s.nseqpair)
00304 {
00305 c.update(*this, share, s.c);
00306 diff.update(*this, share, s.diff);
00307 }
00309 virtual Space*
00310 copy(bool share) {
00311 return new EFPA(share,*this);
00312 }
00313 };
00314
00318 int
00319 main(int argc, char* argv[]) {
00320 EFPAOptions opt("Equidistant Frequency Permutation Arrays");
00321 opt.icl(ICL_DOM);
00322 opt.parse(argc,argv);
00323
00324 Script::run<EFPA,DFS,EFPAOptions>(opt);
00325 return 0;
00326 }
00327
00328