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 * Guido Tack <tack@gecode.org>
6 *
7 * Copyright:
8 * Christian Schulte, 2009
9 * Guido Tack, 2010
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.org
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include <algorithm>
37#include <cmath>
38
39namespace Gecode { namespace Int { namespace Cumulative {
40
41 /*
42 * Omega tree
43 */
44
45 forceinline void
46 OmegaNode::init(const OmegaNode&, const OmegaNode&) {
47 e = 0; env = -Limits::llinfinity;
48 }
49
50 forceinline void
51 OmegaNode::update(const OmegaNode& l, const OmegaNode& r) {
52 e = l.e + r.e; env = std::max(plus(l.env,r.e), r.env);
53 }
54
55 template<class TaskView>
56 OmegaTree<TaskView>::OmegaTree(Region& r, int c0,
57 const TaskViewArray<TaskView>& t)
58 : TaskTree<TaskView,OmegaNode>(r,t), c(c0) {
59 for (int i=0; i<tasks.size(); i++) {
60 leaf(i).e = 0; leaf(i).env = -Limits::llinfinity;
61 }
62 init();
63 }
64
65 template<class TaskView>
66 forceinline void
67 OmegaTree<TaskView>::insert(int i) {
68 leaf(i).e = tasks[i].e();
69 leaf(i).env =
70 static_cast<long long int>(c)*tasks[i].est()+tasks[i].e();
71 update(i);
72 }
73
74 template<class TaskView>
75 forceinline void
76 OmegaTree<TaskView>::remove(int i) {
77 leaf(i).e = 0; leaf(i).env = -Limits::llinfinity;
78 update(i);
79 }
80
81 template<class TaskView>
82 forceinline long long int
83 OmegaTree<TaskView>::env(void) const {
84 return root().env;
85 }
86
87 /*
88 * Extended Omega tree
89 */
90
91 forceinline void
92 ExtOmegaNode::init(const ExtOmegaNode& l, const ExtOmegaNode& r) {
93 OmegaNode::init(l,r);
94 cenv = -Limits::llinfinity;
95 }
96
97 forceinline void
98 ExtOmegaNode::update(const ExtOmegaNode& l, const ExtOmegaNode& r) {
99 OmegaNode::update(l,r);
100 cenv = std::max(plus(l.cenv,r.e), r.cenv);
101 }
102
103 template<class TaskView> void
104 ExtOmegaTree<TaskView>::init(int ci0) {
105 ci = ci0;
106 for (int i=0; i<tasks.size(); i++) {
107 leaf(i).e = 0;
108 leaf(i).env = leaf(i).cenv = -Limits::llinfinity;
109 }
110 init();
111 }
112
113 template<class TaskView> template<class Node>
114 ExtOmegaTree<TaskView>::ExtOmegaTree(Region& r, int c0,
115 const TaskTree<TaskView,Node>& t)
116 : TaskTree<TaskView,ExtOmegaNode>(r,t), c(c0) {}
117
118 template<class TaskView>
119 forceinline long long int
120 ExtOmegaTree<TaskView>::env(int i) {
121 // Enter task i
122 leaf(i).e = tasks[i].e();
123 leaf(i).env =
124 static_cast<long long int>(c)*tasks[i].est()+tasks[i].e();
125 leaf(i).cenv =
126 static_cast<long long int>(c-ci)*tasks[i].est()+tasks[i].e();
127 TaskTree<TaskView,ExtOmegaNode>::update(i);
128
129 // Perform computation of node for task with minest
130 int met = 0;
131 {
132 long long int e = 0;
133 while (!n_leaf(met)) {
134 if (plus(node[n_right(met)].cenv,e) >
135 static_cast<long long int>(c-ci) * tasks[i].lct()) {
136 met = n_right(met);
137 } else {
138 e += node[n_right(met)].e; met = n_left(met);
139 }
140 }
141 }
142
143 /*
144 * The following idea to compute the cut in one go is taken from:
145 * Joseph Scott, Filtering Algorithms for Discrete Resources,
146 * Master Thesis, Uppsala University, 2010 (in preparation).
147 */
148
149 // Now perform split from leaf met upwards
150 long long int a_e = node[met].e;
151 long long int a_env = node[met].env;
152 long long int b_e = 0;
153
154 while (!n_root(met)) {
155 if (left(met)) {
156 b_e += node[n_right(n_parent(met))].e;
157 } else {
158 a_env = std::max(a_env, plus(node[n_left(n_parent(met))].env,a_e));
159 a_e += node[n_left(n_parent(met))].e;
160 }
161 met = n_parent(met);
162 }
163
164 return plus(a_env,b_e);
165 }
166
167
168
169 /*
170 * Omega lambda tree
171 */
172
173 forceinline void
174 OmegaLambdaNode::init(const OmegaLambdaNode& l, const OmegaLambdaNode& r) {
175 OmegaNode::init(l,r);
176 le = 0; lenv = -Limits::llinfinity;
177 resLe = undef; resLenv = undef;
178 }
179
180 forceinline void
181 OmegaLambdaNode::update(const OmegaLambdaNode& l, const OmegaLambdaNode& r) {
182 OmegaNode::update(l,r);
183 if (l.le + r.e > l.e + r.le) {
184 le = l.le + r.e;
185 resLe = l.resLe;
186 } else {
187 le = l.e + r.le;
188 resLe = r.resLe;
189 }
190 if ((r.lenv >= plus(l.env,r.le)) && (r.lenv >= plus(l.lenv,r.e))) {
191 lenv = r.lenv; resLenv = r.resLenv;
192 } else if (plus(l.env,r.le) >= plus(l.lenv,r.e)) {
193 assert(plus(l.env,r.le) > r.lenv);
194 lenv = plus(l.env,r.le); resLenv = r.resLe;
195 } else {
196 assert((plus(l.lenv,r.e) > r.lenv) &&
197 (plus(l.lenv,r.e) > plus(l.env,r.le)));
198 lenv = plus(l.lenv,r.e); resLenv = l.resLenv;
199 }
200 }
201
202
203 template<class TaskView>
204 OmegaLambdaTree<TaskView>::OmegaLambdaTree(Region& r, int c0,
205 const TaskViewArray<TaskView>& t)
206 : TaskTree<TaskView,OmegaLambdaNode>(r,t), c(c0) {
207 // Enter all tasks into tree (omega = all tasks, lambda = empty)
208 for (int i=0; i<tasks.size(); i++) {
209 leaf(i).e = tasks[i].e();
210 leaf(i).le = 0;
211 leaf(i).env = static_cast<long long int>(c)*tasks[i].est()+tasks[i].e();
212 leaf(i).lenv = -Limits::llinfinity;
213 leaf(i).resLe = OmegaLambdaNode::undef;
214 leaf(i).resLenv = OmegaLambdaNode::undef;
215 }
216 update();
217 }
218
219 template<class TaskView>
220 forceinline void
221 OmegaLambdaTree<TaskView>::shift(int i) {
222 // i is in omega
223 assert(leaf(i).env > -Limits::llinfinity);
224 leaf(i).le = leaf(i).e;
225 leaf(i).e = 0;
226 leaf(i).lenv = leaf(i).env;
227 leaf(i).env = -Limits::llinfinity;
228 leaf(i).resLe = i;
229 leaf(i).resLenv = i;
230 update(i);
231 }
232
233 template<class TaskView>
234 forceinline void
235 OmegaLambdaTree<TaskView>::lremove(int i) {
236 // i not in omega but in lambda
237 assert(leaf(i).env == -Limits::llinfinity);
238 assert(leaf(i).lenv > -Limits::llinfinity);
239 leaf(i).le = 0;
240 leaf(i).lenv = -Limits::llinfinity;
241 leaf(i).resLe = OmegaLambdaNode::undef;
242 leaf(i).resLenv = OmegaLambdaNode::undef;
243 update(i);
244 }
245
246 template<class TaskView>
247 forceinline bool
248 OmegaLambdaTree<TaskView>::lempty(void) const {
249 return root().resLenv < 0;
250 }
251
252 template<class TaskView>
253 forceinline int
254 OmegaLambdaTree<TaskView>::responsible(void) const {
255 return root().resLenv;
256 }
257
258 template<class TaskView>
259 forceinline long long int
260 OmegaLambdaTree<TaskView>::env(void) const {
261 return root().env;
262 }
263
264 template<class TaskView>
265 forceinline long long int
266 OmegaLambdaTree<TaskView>::lenv(void) const {
267 return root().lenv;
268 }
269
270}}}
271
272// STATISTICS: int-prop