1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
on-restart-benchmarks/test/int/cumulatives.cpp
Jip J. Dekker 1d9faf38de Squashed 'software/gecode/' content from commit 313e8764
git-subtree-dir: software/gecode
git-subtree-split: 313e87646da4fc2752a70e83df16d993121a8e40
2021-06-16 14:02:33 +10:00

273 lines
8.8 KiB
C++
Executable File

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Mikael Lagerkvist <lagerkvist@gecode.org>
*
* Copyright:
* Mikael Lagerkvist, 2005
*
* This file is part of Gecode, the generic constraint
* development environment:
* http://www.gecode.org
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "test/int.hh"
#include <gecode/minimodel.hh>
#include <gecode/search.hh>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
namespace Test { namespace Int {
/// %Tests for scheduling constraints
namespace Cumulatives {
/**
* \defgroup TaskTestIntCumulatives Cumnulatives scheduling constraint
* \ingroup TaskTestInt
*/
//@{
/**
* \brief Script for generating assignments.
*
* We are only interested in assignments that represent tasks (s_i,
* d_i, e_i, h_i) such that the following hold:
* - The task starts at a positive time and has some extension.
* - The equation s_i + d_i = e_i holds.
* - The tasks are ordered to remove some symmetries, i.e.,
* s_i <= s_{i+1}
*/
class Ass : public Gecode::Space {
public:
/// Store task information
Gecode::IntVarArray x;
/// Initialize model for assignments
Ass(int n, const Gecode::IntSet& d) : x(*this, n, d) {
using namespace Gecode;
for (int i = 0; i < n; i += 4) {
rel(*this, x[i+0] >= 0);
rel(*this, x[i+1] >= 0);
rel(*this, x[i+2] >= 0);
rel(*this, x[i] + x[i+1] == x[i+2]);
branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
}
}
/// Constructor for cloning \a s
Ass(Ass& s) : Gecode::Space(s) {
x.update(*this, s.x);
}
/// Create copy during cloning
virtual Gecode::Space* copy(void) {
return new Ass(*this);
}
};
/// Class for generating reasonable assignments
class CumulativeAssignment : public Assignment {
/// Current assignment
Ass* cur;
/// Next assignment
Ass* nxt;
/// Search engine to find assignments
Gecode::DFS<Ass>* e;
public:
/// Initialize assignments for \a n0 variables and values \a d0
CumulativeAssignment(int n, const Gecode::IntSet& d) : Assignment(n,d) {
Ass* a = new Ass(n, d);
e = new Gecode::DFS<Ass>(a);
delete a;
nxt = cur = e->next();
if (cur != nullptr)
nxt = e->next();
}
/// %Test whether all assignments have been iterated
virtual bool has_more(void) const {
return nxt != nullptr;
}
/// Move to next assignment
virtual void next(Gecode::Support::RandomGenerator&) {
delete cur;
cur = nxt;
if (cur != nullptr) nxt = e->next();
}
/// Return value for variable \a i
virtual int operator[](int i) const {
assert((i>=0) && (i<n) && (cur != nullptr));
return cur->x[i].val();
}
/// Destructor
virtual ~CumulativeAssignment(void) {
delete cur; delete nxt; delete e;
}
};
/// %Event to be scheduled
class Event {
public:
int p, h; ///< Position and height of event
bool start; ///< Whether event has just started
/// Initialize event
Event(int pos, int height, bool s) : p(pos), h(height), start(s) {}
/// %Test whether this event is before event \a e
bool operator<(const Event& e) const {
return p<e.p;
}
};
/// Describe that event is below a certain limit
class Below {
public:
int limit; ///< limit
/// Initialize
Below(int l) : limit(l) {}
/// %Test whether \a val is below limit
bool operator()(int val) {
return val <= limit;
}
};
/// Describe that event is above a certain limit
class Above {
public:
int limit; ///< limit
/// Initialize
Above(int l) : limit(l) {}
/// %Test whether \a val is above limit
bool operator()(int val) {
return val >= limit;
}
};
/// Check whether event \a e is valid
template<class C>
bool valid(std::vector<Event> e, C comp) {
std::sort(e.begin(), e.end());
unsigned int i = 0;
int p = 0;
int h = 0;
int n = 0;
while (i < e.size()) {
p = e[i].p;
while (i < e.size() && e[i].p == p) {
h += e[i].h;
n += (e[i].start ? +1 : -1);
++i;
}
if (n && !comp(h))
return false;
}
return true;
}
/// %Test for cumulatives constraint
class Cumulatives : public Test {
protected:
int ntasks; ///< Number of tasks
bool at_most; ///< Whether to use atmost reasoning
int limit; ///< Limit
public:
/// Create and register test
Cumulatives(const std::string& s, int nt, bool am, int l)
: Test("Cumulatives::"+s,nt*4,-1,2), ntasks(nt), at_most(am), limit(l) {
testsearch = false;
}
/// Create first assignment
virtual Assignment* assignment(void) const {
assert(arity == 4*ntasks);
return new CumulativeAssignment(arity, dom);
}
/// %Test whether \a x is solution
virtual bool solution(const Assignment& x) const {
std::vector<Event> e;
for (int i = 0; i < ntasks; ++i) {
int p = i*4;
// Positive start, duration and end
if (x[p+0] < 0 || x[p+1] < 1 || x[p+2] < 1) return false;
// Start + Duration == End
if (x[p+0] + x[p+1] != x[p+2]) {
return false;
}
}
for (int i = 0; i < ntasks; ++i) {
int p = i*4;
// Up at start, down at end.
e.push_back(Event(x[p+0], +x[p+3], true));
e.push_back(Event(x[p+2], -x[p+3], false));
}
if (at_most) {
return valid(e, Below(limit));
} else {
return valid(e, Above(limit));
}
}
/// Post constraint on \a x
virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
using namespace Gecode;
IntArgs m(ntasks), l({limit});
IntVarArgs s(ntasks), d(ntasks), e(ntasks), h(ntasks);
for (int i = 0; i < ntasks; ++i) {
int p = i*4;
m[i] = 0;
s[i] = x[p+0]; rel(home, x[p+0], Gecode::IRT_GQ, 0);
d[i] = x[p+1]; rel(home, x[p+1], Gecode::IRT_GQ, 1);
e[i] = x[p+2]; rel(home, x[p+2], Gecode::IRT_GQ, 1);
h[i] = x[p+3];
}
cumulatives(home, m, s, d, e, h, l, at_most);
}
};
Cumulatives c1t1("1t1", 1, true, 1);
Cumulatives c1f1("1f1", 1, false, 1);
Cumulatives c1t2("1t2", 1, true, 2);
Cumulatives c1f2("1f2", 1, false, 2);
Cumulatives c1t3("1t3", 1, true, 3);
Cumulatives c1f3("1f3", 1, false, 3);
Cumulatives c2t1("2t1", 2, true, 1);
Cumulatives c2f1("2f1", 2, false, 1);
Cumulatives c2t2("2t2", 2, true, 2);
Cumulatives c2f2("2f2", 2, false, 2);
Cumulatives c2t3("2t3", 2, true, 3);
Cumulatives c2f3("2f3", 2, false, 3);
Cumulatives c3t1("3t1", 3, true, 1);
Cumulatives c3f1("3f1", 3, false, 1);
Cumulatives c3t2("3t2", 3, true, 2);
Cumulatives c3f2("3f2", 3, false, 2);
Cumulatives c3t3("3t3", 3, true, 3);
Cumulatives c3f3("3f3", 3, false, 3);
Cumulatives c3t_1("3t-1", 3, true, -1);
Cumulatives c3f_1("3f-1", 3, false, -1);
Cumulatives c3t_2("3t-2", 3, true, -2);
Cumulatives c3f_2("3f-2", 3, false, -2);
Cumulatives c3t_3("3t-3", 3, true, -3);
Cumulatives c3f_3("3f-3", 3, false, -3);
//@}
}
}}
// STATISTICS: test-int