59 static const bool verbose =
false;
62 static const unsigned int probes = 50U;
64 static const unsigned int fail_probe = 10000U;
67 static const unsigned int time_probe = 30U * 1000U;
69 static const unsigned int time_adjust = 30U * 1000U;
71 static const unsigned int time_solve = 60U * 1000U;
74 static const double restart_scale = 5000.0;
76 static const double restart_base = 1.3;
83 extern const int* js[];
85 extern const char* name[];
98 bool valid(
void)
const {
99 return data !=
nullptr;
102 int jobs(
void)
const {
106 int machines(
void)
const {
110 int machine(
int i,
int j)
const {
111 return data[2 + i*machines()*2 + j*2];
114 int duration(
int i,
int j)
const {
115 return data[2 + i*machines()*2 + j*2 + 1];
119 static const int* find(
const char* s) {
120 for (
int i=0; ::name[i] !=
nullptr; i++)
121 if (!strcmp(s,::name[i]))
126 int clower(
void)
const {
129 int* mach = r.
alloc<
int>(machines());
130 for (
int j=0; j<machines(); j++)
132 for (
int i=0; i<jobs(); i++) {
134 for (
int j=0; j<machines(); j++) {
135 mach[machine(i,j)] += duration(i,j);
136 job += duration(i,j);
140 for (
int j=0; j<machines(); j++)
141 l = std::max(l,mach[j]);
145 int cupper(
void)
const {
147 for (
int i=0; i<jobs(); i++)
148 for (
int j=0; j<machines(); j++)
154 Spec(
const char* s) : data(find(s)), l(0), u(0), n(s) {
156 l = clower(); u = cupper();
160 int lower(
void)
const {
164 int upper(
void)
const {
168 const char* name(
void)
const {
199 _verbose(
"verbose",
"whether to print schedule",
201 _probes(
"probes",
"how many probes to perform",
203 _fail_probe(
"fail-probe",
"failure limit per probe",
205 _time_probe(
"time-probe",
"time-out for probing (in milliseconds)",
207 _time_adjust(
"time-adjust",
"time-out for adjusting (in milliseconds)",
209 _time_solve(
"time-solve",
"time-out for solving (in milliseconds)",
211 _tbf(
"tbf",
"tie-breaking factor", 0.0) {
222 return _verbose.value();
226 return _probes.value();
230 return _fail_probe.value();
234 return _time_probe.value();
238 return _time_adjust.value();
242 return _time_solve.value();
251 std::cerr <<
"\tAvailable instances:" << std::endl <<
"\t\t";
252 for (
int i=1;
::name[i] !=
nullptr; i++) {
253 std::cerr <<
::name[i] <<
", ";
255 std::cerr << std::endl <<
"\t\t";
257 std::cerr << std::endl;
285 int n =
spec.jobs(), m =
spec.machines();
290 for (
int i=0; i<n; i++) {
291 for (
int j=1; j<m; j++)
299 int n =
spec.jobs(), m =
spec.machines();
304 for (
int i=0; i<n; i++)
305 for (
int j=0; j<m; j++) {
306 jobs[
spec.machine(i,j)*n+i] =
start[i*m+j];
307 dur[
spec.machine(i,j)*n+i] =
spec.duration(i,j);
310 for (
int j=0; j<m; j++) {
313 for (
int i=0; i<n; i++) {
314 jpm[i] = jobs[j*n+i]; dpm[i] = dur[j*n+i];
316 unary(*
this, jpm, dpm);
332 os <<
"\t\t" <<
spec.name()
333 <<
" [makespan: " <<
makespan <<
"]" << std::endl;
338 int m =
spec.machines();
339 for (
int i=0; i<n; i++) {
340 os <<
"\t\t\t[" << i <<
"]: ";
341 for (
int j=0; j<m; j++)
342 os <<
start[i*m+j] <<
" ";
473 int n =
spec.jobs(), m =
spec.machines();
475 fst.init(m*n*(n-1)/2);
476 snd.init(m*n*(n-1)/2);
480 for (
int i=0; i<n; i++)
481 for (
int j=0; j<m; j++) {
482 jobs[
spec.machine(i,j)*n+i] = i*m+j;
483 dur[
spec.machine(i,j)*n+i] =
spec.duration(i,j);
487 for (
int j=0; j<m; j++) {
488 for (
int i1=0; i1<n; i1++)
489 for (
int i2=i1+1; i2<n; i2++) {
490 if (dur[j*n+i1] > dur[j*n+i2]) {
492 start[jobs[j*n+i1]], dur[j*n+i1],
493 start[jobs[j*n+i2]], dur[j*n+i2],
495 fst[l] = j*n+i1;
snd[l] = j*n+i2;
498 start[jobs[j*n+i2]], dur[j*n+i2],
499 start[jobs[j*n+i1]], dur[j*n+i1],
501 fst[l] = j*n+i2;
snd[l] = j*n+i1;
505 assert(l == (j+1)*n*(n-1)/2);
508 double tbf =
opt.tbf();
509 switch (
opt.branching()) {
511 iafc.init(*this,start,opt.decay());
514 [tbf] (const Space&, double w, double b) {
516 return b - (b - w) * tbf;
518 branch(*this, sorder, tiebreak(BOOL_VAR_MERIT_MAX(&afcmerit,tbl),
522 branch(*this, sorder, BOOL_VAR_MERIT_MAX(&afcmerit),
531 [tbf] (
const Space&,
double w,
double b) {
533 return b - (b - w) * tbf;
548 [tbf] (
const Space&,
double w,
double b) {
550 return b - (b - w) * tbf;
588 return fs->stop(s,o) ||
ts->stop(s,o);
592 return fs->stop(s,o);
596 return ts->stop(s,o);
600 delete fs;
delete ts;
608 cout <<
"\t\t\tnodes: " << stat.
node << endl
609 <<
"\t\t\tfailures: " << stat.
fail << endl;
611 cout <<
"\t\t\trestarts: " << stat.
restart << endl
612 <<
"\t\t\tno-goods: " << stat.
nogood << endl;
613 cout <<
"\t\t\tpeak depth: " << stat.
depth << endl;
636 std::cerr <<
"Error: has no solution..." << std::endl;
646 bool stopped =
false;
648 std::cout <<
"\tProbing..." << std::endl;
650 std::cout <<
"\t\tBounds: [" << l <<
"," << u <<
"]"
653 for (
unsigned int p=0; p<opt.probes(); p++) {
666 }
else if (fts.
time(statj,so)) {
675 std::cout <<
"\t\t\truntime: ";
677 std::cout << std::endl;
680 std::cout <<
"\t\t\t\tstopped due to time-out..." << std::endl;
684 std::cout << std::endl <<
"\tAdjusting..." << std::endl;
693 std::cerr <<
"Error: has no solution..." << std::endl;
701 if (opt.time_adjust() > 0U)
703 bool stopped =
false;
705 std::cout <<
"\t\tBounds: [" << l <<
"," << u <<
"]"
712 JobShopConfig::restart_base);
716 stat +=
rbs.statistics();
722 }
else if (
rbs.stopped()) {
731 std::cout <<
"\t\t\truntime: ";
733 std::cout << std::endl;
736 std::cout <<
"\t\t\t\tstopped due to time-out..." << std::endl;
743 std::cout << std::endl
744 <<
"\tFound best solution and proved optimality."
752 std::cout << std::endl <<
"\tSolving..." << std::endl;
754 rel(*master, master->
cost() >= l);
755 rel(*master, master->
cost() < u);
758 if (opt.time_solve() > 0U)
761 JobShopConfig::restart_base);
770 std::cout <<
"\t\t\truntime: ";
772 std::cout << std::endl;
775 std::cout <<
"\t\t\t\tstopped due to time-out..." << std::endl;
776 std::cout << std::endl
777 <<
"\tSolution at most ";
778 double a = (
static_cast<double>(u-l+1) / u) * 100.0;
779 std::cout << std::setprecision(2) << a
780 <<
"% away from optimum."
784 std::cout << std::endl
785 <<
"\tFound best solution and proved optimality."
801main(
int argc,
char* argv[]) {
813 opt.instance(
"ft06");
815 opt.restart_base(JobShopConfig::restart_base);
816 opt.restart_scale(JobShopConfig::restart_scale);
820 if (!Spec(
opt.instance()).valid()) {
821 std::cerr <<
"Error: unknown instance" << std::endl;
Common command line options.
CommonOptions(const JobShopOptions &opt)
Initialize.
Stop object combining time and failuresa.
bool fail(const Search::Statistics &s, const Search::Options &o) const
Whether the stop was due to failures.
virtual bool stop(const Search::Statistics &s, const Search::Options &o)
Test whether search must be stopped.
~FailTimeStop(void)
Destructor.
Search::FailStop * fs
Used fail stop object.
FailTimeStop(unsigned int fail, unsigned int time)
Initialize stop object.
Search::TimeStop * ts
Used time stop object.
bool time(const Search::Statistics &s, const Search::Options &o) const
Whether the stop was due to time.
void add(Driver::BaseOption &o)
Add new option o.
const char * name(void) const
Return name of script.
Recording actions for Boolean variables.
Recording CHB for Boolean variables.
Boolean integer variables.
Depth-first search engine.
virtual void help(void)
Print help text.
InstanceOptions(const char *s)
Initialize options for script with name s.
Recording AFC information for integer variables.
Recording actions for integer variables.
Passing integer arguments.
Recording CHB for integer variables.
Passing integer variables.
int min(void) const
Return minimum of domain.
int val(void) const
Return assigned value.
int max(void) const
Return maximum of domain.
Meta-engine performing restart-based search.
T * alloc(long unsigned int n)
Allocate block of n objects of type T from region.
static Cutoff * geometric(unsigned long long int scale=Config::slice, double base=Config::base)
Stop-object based on number of failures
unsigned int c_d
Create a clone after every c_d commits (commit distance).
bool clone
Whether engines create a clone when being initialized.
Cutoff * cutoff
Cutoff for restart-based search.
unsigned int a_d
Create a clone during recomputation if distance is greater than a_d (adaptive distance).
Stop * stop
Stop object for stopping search.
unsigned int nogoods_limit
Depth limit for extraction of no-goods.
double threads
Number of threads to use.
unsigned long int restart
Number of restarts.
unsigned long int depth
Maximum depth of search stack.
unsigned long long int fail
Number of failed nodes in search tree.
unsigned long long int node
Number of nodes expanded.
unsigned long int nogood
Number of no-goods posted.
Base-class for Stop-object.
static Stop * time(double l)
Stop if time limit l (in milliseconds) has been exceeded.
Stop-object based on time
void start(void)
Start timer.
double afc(void) const
Return accumulated failure count.
virtual void print(std::ostream &os) const
Print solution.
const JobShopOptions & opt
Options.
IntVarArray start
Start times for each step in a job.
JobShopBase(JobShopBase &s)
Constructor for cloning s.
virtual IntVar cost(void) const
Return cost.
const Spec spec
Specification.
void nooverload(void)
Do not overload machines.
JobShopBase(const JobShopOptions &o)
Actual model.
Options for JobShop problems
unsigned int fail_probe(void) const
Return number of failures per probe.
JobShopOptions(const char *s)
Initialize options for example with name s.
unsigned int time_probe(void) const
Return time-out for probe.
unsigned int time_adjust(void) const
Return time-out for adjust.
virtual void help(void)
Print help text for list of instances.
bool verbose(void) const
Return whether to print schedule.
unsigned int time_solve(void) const
Return time-out for solve.
unsigned int probes(void) const
Return number of probes.
double tbf(void) const
Return tie-breaking factor.
void branch(unsigned int p, Rnd r)
JobShopProbe(JobShopProbe &s)
Constructor for cloning s.
virtual Space * copy(void)
Copy during cloning.
JobShopProbe(const JobShopOptions &o)
Actual model.
IntCHB ichb
CHB information.
virtual Space * copy(void)
Copy during cloning.
IntSharedArray snd
Record which step is second in order.
JobShopSolve(const JobShopOptions &o)
Actual model.
static double chbmerit(const Space &home, BoolVar, int i)
Trampoline function for CHB-based cost.
@ PROP_UNARY
Also post unary constraints.
@ PROP_ORDER
Only propagate order constraints.
static double afcmerit(const Space &home, BoolVar x, int i)
Trampoline function for AFC-based cost.
IntAFC iafc
AFC information.
IntAction iaction
Action information.
BoolVarArray sorder
Step order variables.
double chb(int i) const
CHB-based cost.
double action(int i) const
Action-based cost.
Rnd rnd
Random number generator for probing and relaxation.
double afc(BoolVar x, int i) const
AFC-based cost.
IntSharedArray fst
Record which step is first in order.
@ BRANCH_AFC
Branch using AFC.
@ BRANCH_ACTION
Branch using action.
@ BRANCH_CHB
Branch using CHB.
static double actionmerit(const Space &home, BoolVar, int i)
Trampoline function for Action-based cost.
JobShopSolve(JobShopSolve &s)
Constructor for cloning s.
int main(int argc, char *argv[])
Main function.
void parse(int argc, char *argv[])
Parse commandline arguments.
unsigned int seed
The random seed to be used.
unsigned int threads
Number of threads to use.
Driver::ScriptBase< Driver::IgnoreStepOption< IntMinimizeSpace > > IntMinimizeScript
Base-class for scripts for finding solution of lowest integer cost.
void assign(Home home, const FloatVarArgs &x, FloatVarBranch vars, FloatAssign vals, FloatBranchFilter bf=nullptr, FloatVarValPrint vvp=nullptr)
Assign all x with variable selection vars and value selection vals.
void branch(Home home, const FloatVarArgs &x, FloatVarBranch vars, FloatValBranch vals, FloatBranchFilter bf=nullptr, FloatVarValPrint vvp=nullptr)
Branch over x with variable selection vars and value selection vals.
void rel(Home home, FloatVar x0, FloatRelType frt, FloatVar x1)
Post propagator for .
T * rbs(T *s, const Search::Options &o)
Perform restart-based search.
@ SS_SOLVED
Space is solved (no brancher left)
@ SS_FAILED
Space is failed
void print(const Search::Statistics &stat, bool restart)
Print statistics.
void solve(const JobShopOptions &opt)
Solver.
void stop(Support::Timer &t, std::ostream &os)
Get time since start of timer and print user friendly time information.
bool valid(const FloatVal &n)
Return whether float n is a valid number.
Gecode toplevel namespace
IntValBranch INT_VAL_SPLIT_MIN(void)
Select values not greater than mean of smallest and largest value.
void order(Home home, IntVar s0, int p0, IntVar s1, int p1, BoolVar b, IntPropLevel ipl=IPL_DEF)
Post propagators for ordering two tasks.
SharedArray< int > IntSharedArray
Arrays of integers that can be shared among several element constraints.
TieBreak< VarBranch > tiebreak(VarBranch a, VarBranch b)
Combine variable selection criteria a and b for tie-breaking.
BoolValBranch BOOL_VAL_MIN(void)
Select smallest value.
BoolVarBranch BOOL_VAR_RND(Rnd r)
Select random variable (uniform distribution, for tie breaking).
IntVarBranch INT_VAR_MAX_MIN(BranchTbl tbl=nullptr)
Select variable with smallest max.
IntValBranch INT_VAL_MIN(void)
Select smallest value.
T * dfs(T *s, const Search::Options &o=Search::Options::def)
Invoke depth-first search engine for subclass T of space s with options o.
IntAssign INT_ASSIGN_MIN(void)
Select smallest value.
IntVarBranch INT_VAR_RND(Rnd r)
Select random variable (uniform distribution, for tie breaking).
void unary(Home home, const IntVarArgs &s, const IntArgs &p, IntPropLevel ipl=IPL_DEF)
Post propagators for scheduling tasks on unary resources.
IntVarBranch INT_VAR_SIZE_MIN(BranchTbl tbl=nullptr)
Select variable with smallest domain size.
BoolVarBranch BOOL_VAR_MERIT_MAX(BoolBranchMerit bm, BranchTbl tbl=nullptr)
Select variable with highest merit according to branch merit function bm.
IntVarBranch INT_VAR_MIN_MIN(BranchTbl tbl=nullptr)
Select variable with smallest min.
Default configuration settings.