this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2013
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34namespace Gecode { namespace Search {
35
36 forceinline
37 NoNGL::NoNGL(void) {}
38
39 forceinline
40 NoNGL::NoNGL(Space& home)
41 : NGL(home) {}
42
43 forceinline
44 NoNGL::NoNGL(Space& home, NoNGL& ngl)
45 : NGL(home,ngl) {}
46
47
48
49 forceinline
50 NoGoodsProp::NoGoodsProp(Space& home, NGL* root0)
51 : Propagator(Home(home)), root(root0), n(0U) {
52 // Create subscriptions
53 root->subscribe(home,*this); n++;
54 bool notice = root->notice();
55 NGL* l = root->next();
56 while ((l != nullptr) && l->leaf()) {
57 l->subscribe(home,*this); n++;
58 notice = notice || l->notice();
59 l = l->next();
60 }
61 if (l != nullptr) {
62 l->subscribe(home,*this); n++;
63 }
64 while (!notice && (l != nullptr)) {
65 notice = notice || l->notice();
66 l = l->next();
67 }
68 if (notice)
69 home.notice(*this,AP_DISPOSE);
70 }
71
72 forceinline
73 NoGoodsProp::NoGoodsProp(Space& home, NoGoodsProp& p)
74 : Propagator(home,p), n(p.n) {
75 assert(p.root != nullptr);
76 NoNGL s;
77 NGL* c = &s;
78 for (NGL* pc = p.root; pc != nullptr; pc = pc->next()) {
79 NGL* n = pc->copy(home);
80 n->leaf(pc->leaf());
81 c->next(n); c=n;
82 }
83 root = s.next();
84 }
85
86
87
88 template<class Path>
89 forceinline ExecStatus
90 NoGoodsProp::post(Space& home, const Path& p) {
91 int s = 0;
92 int n = std::min(p.ds.entries(),static_cast<int>(p.ngdl()));
93
94 unsigned long int n_nogood = 0;
95
96 // Eliminate the alternatives which are not no-goods at the end
97 while ((n > s) && (p.ds[n-1].truealt() == 0U))
98 n--;
99
100 // A sentinel element
101 NoNGL nn;
102 // Current no-good literal
103 NGL* c = &nn;
104
105 // Commit no-goods at the beginning
106 while ((s < n) && (p.ds[s].truealt() > 0U))
107 // Try whether this is a rightmost alternative
108 if (p.ds[s].rightmost()) {
109 // No literal needed, directly try to commit
110 home.trycommit(*p.ds[s].choice(),p.ds[s].truealt());
111 s++;
112 } else {
113 // Prune using no-good literals
114 for (unsigned int a=0U; a<p.ds[s].truealt(); a++) {
115 NGL* l = home.ngl(*p.ds[s].choice(),a);
116 // Does the brancher support no-good literals?
117 if (l == nullptr)
118 return ES_OK;
119 GECODE_ES_CHECK(l->prune(home));
120 }
121 // Add literal as root if needed and stop
122 if (NGL* l = home.ngl(*p.ds[s].choice(),p.ds[s].truealt())) {
123 c = c->add(l,false);
124 s++; break;
125 }
126 }
127
128 // There are no literals
129 if (home.failed())
130 return ES_FAILED;
131 if (s >= n)
132 return ES_OK;
133
134 // There must be at least two literals
135 assert((n-s > 1) ||
136 ((n-s == 1) && (c != &nn)));
137
138 // Remember the last leaf
139 NGL* ll = nullptr;
140
141 // Create literals
142 for (int i=s; i<n; i++) {
143 // Add leaves
144 for (unsigned int a=0U; a<p.ds[i].truealt(); a++) {
145 NGL* l = home.ngl(*p.ds[i].choice(),a);
146 if (l == nullptr) {
147 // The brancher does not support no-goods
148 if (ll == nullptr)
149 return ES_OK;
150 ll->next(nullptr);
151 break;
152 }
153 c = c->add(l,true); ll = c;
154 n_nogood++;
155 }
156 // Check whether to add an additional subtree
157 if (NGL* l = home.ngl(*p.ds[i].choice(),p.ds[i].truealt())) {
158 c = c->add(l,false);
159 } else if (!p.ds[i].rightmost()) {
160 // The brancher does not support no-goods
161 if (ll == nullptr)
162 return ES_OK;
163 ll->next(nullptr);
164 break;
165 }
166 }
167
168 const_cast<Path&>(p).ng(n_nogood);
169
170 (void) new (home) NoGoodsProp(home,nn.next());
171 return ES_OK;
172 }
173
174}}
175
176// STATISTICS: search-other