2
* Copyright (c) 2000 Matteo Frigo
3
* Copyright (c) 2000 Massachusetts Institute of Technology
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
/* $Id: planner.c,v 1.189 2006-01-17 05:17:27 athena Exp $ */
25
/* GNU Coding Standards, Sec. 5.2: "Please write the comments in a GNU
26
program in English, because English is the one language that nearly
27
all programmers in all countries can read."
29
ingemisco tanquam reus
30
culpa rubet vultus meus
31
supplicanti parce [rms]
34
#define VALIDP(solution) ((solution)->flags.hash_info & H_VALID)
35
#define LIVEP(solution) ((solution)->flags.hash_info & H_LIVE)
36
#define SLVNDX(solution) ((solution)->flags.slvndx)
37
#define BLISS(flags) (((flags).hash_info) & BLESSING)
38
#define INFEASIBLE_SLVNDX ((1U<<BITS_FOR_SLVNDX)-1)
41
#define MAXNAM 64 /* maximum length of registrar's name.
42
Used for reading wisdom. There is no point
43
in doing this right */
47
static void check(hashtab *ht);
51
#define LEQ(x, y) (((x) & (y)) == (x))
54
static int subsumes(const flags_t *a, unsigned slvndx_a, const flags_t *b)
56
if (slvndx_a != INFEASIBLE_SLVNDX) {
57
A(a->timelimit_impatience == 0);
58
return (LEQ(a->u, b->u) && LEQ(b->l, a->l));
60
return (LEQ(a->l, b->l)
61
&& a->timelimit_impatience <= b->timelimit_impatience);
65
static unsigned addmod(unsigned a, unsigned b, unsigned p)
67
/* gcc-2.95/sparc produces incorrect code for the fast version below. */
68
#if defined(__sparc__) && defined(__GNUC__)
74
return c >= p ? c - p : c;
81
static void sgrow(planner *ego)
83
unsigned osiz = ego->slvdescsiz, nsiz = 1 + osiz + osiz / 4;
84
slvdesc *ntab = (slvdesc *)MALLOC(nsiz * sizeof(slvdesc), SLVDESCS);
85
slvdesc *otab = ego->slvdescs;
89
ego->slvdescsiz = nsiz;
90
for (i = 0; i < osiz; ++i)
95
static void register_solver(planner *ego, solver *s)
100
if (s) { /* add s to solver list */
103
A(ego->nslvdesc < INFEASIBLE_SLVNDX);
104
if (ego->nslvdesc >= ego->slvdescsiz)
107
n = ego->slvdescs + ego->nslvdesc;
110
n->reg_nam = ego->cur_reg_nam;
111
n->reg_id = ego->cur_reg_id++;
113
A(strlen(n->reg_nam) < MAXNAM);
114
n->nam_hash = X(hash)(n->reg_nam);
116
kind = s->adt->problem_kind;
117
n->next_for_same_problem_kind = ego->slvdescs_for_problem_kind[kind];
118
ego->slvdescs_for_problem_kind[kind] = ego->nslvdesc;
124
static unsigned slookup(planner *ego, char *nam, int id)
126
unsigned h = X(hash)(nam); /* used to avoid strcmp in the common case */
127
FORALL_SOLVERS(ego, s, sp, {
129
if (sp->reg_id == id && sp->nam_hash == h
130
&& !strcmp(sp->reg_nam, nam))
131
return sp - ego->slvdescs;
133
return INFEASIBLE_SLVNDX;
140
/* first hash function */
141
static unsigned h1(const hashtab *ht, const md5sig s)
143
unsigned h = s[0] % ht->hashsiz;
144
A(h == (s[0] % ht->hashsiz));
148
/* second hash function (for double hashing) */
149
static unsigned h2(const hashtab *ht, const md5sig s)
151
unsigned h = 1U + s[1] % (ht->hashsiz - 1);
152
A(h == (1U + s[1] % (ht->hashsiz - 1)));
156
static void md5hash(md5 *m, const problem *p, const planner *plnr)
159
X(md5unsigned)(m, sizeof(R)); /* so we don't mix different precisions */
160
X(md5int)(m, plnr->nthr);
165
static int md5eq(const md5sig a, const md5sig b)
167
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3];
170
static void sigcpy(const md5sig a, md5sig b)
172
b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; b[3] = a[3];
176
memoization routines :
180
liber scriptus proferetur
181
in quo totum continetur
182
unde mundus iudicetur
189
static solution *htab_lookup(hashtab *ht, const md5sig s,
190
const flags_t *flagsp)
192
unsigned g, h = h1(ht, s), d = h2(ht, s);
197
/* search all entries that match; select the one with
198
the lowest flags.u */
199
/* This loop may potentially traverse the whole table, since at
200
least one element is guaranteed to be !LIVEP, but all elements
201
may be VALIDP. Hence, we stop after at the first invalid
202
element or after traversing the whole table. */
205
solution *l = ht->solutions + g;
210
&& subsumes(&l->flags, SLVNDX(l), flagsp) ) {
211
if (!best || LEQ(l->flags.u, best->flags.u))
217
g = addmod(g, d, ht->hashsiz);
225
static solution *hlookup(planner *ego, const md5sig s,
226
const flags_t *flagsp)
228
solution *sol = htab_lookup(&ego->htab_blessed, s, flagsp);
229
if (!sol) sol = htab_lookup(&ego->htab_unblessed, s, flagsp);
233
static void fill_slot(hashtab *ht, const md5sig s, const flags_t *flagsp,
234
unsigned slvndx, solution *slot)
239
slot->flags.u = flagsp->u;
240
slot->flags.l = flagsp->l;
241
slot->flags.timelimit_impatience = flagsp->timelimit_impatience;
242
slot->flags.hash_info |= H_VALID | H_LIVE;
243
SLVNDX(slot) = slvndx;
245
/* keep this check enabled in case we add so many solvers
246
that the bitfield overflows */
247
CK(SLVNDX(slot) == slvndx);
251
static void kill_slot(hashtab *ht, solution *slot)
253
A(LIVEP(slot)); /* ==> */ A(VALIDP(slot));
256
slot->flags.hash_info = H_VALID;
259
static void hinsert0(hashtab *ht, const md5sig s, const flags_t *flagsp,
263
unsigned g, h = h1(ht, s), d = h2(ht, s);
265
++ht->insert_unknown;
267
/* search for nonfull slot */
268
for (g = h; ; g = addmod(g, d, ht->hashsiz)) {
270
l = ht->solutions + g;
271
if (!LIVEP(l)) break;
272
A((g + d) % ht->hashsiz != h);
275
fill_slot(ht, s, flagsp, slvndx, l);
278
static void rehash(hashtab *ht, unsigned nsiz)
280
unsigned osiz = ht->hashsiz, h;
281
solution *osol = ht->solutions, *nsol;
283
nsiz = (unsigned)X(next_prime)((INT)nsiz);
284
nsol = (solution *)MALLOC(nsiz * sizeof(solution), HASHT);
288
for (h = 0; h < nsiz; ++h)
289
nsol[h].flags.hash_info = 0;
291
/* install new table */
293
ht->solutions = nsol;
297
for (h = 0; h < osiz; ++h) {
298
solution *l = osol + h;
300
hinsert0(ht, l->s, &l->flags, SLVNDX(l));
306
static unsigned minsz(unsigned nelem)
308
return 1U + nelem + nelem / 8U;
311
static unsigned nextsz(unsigned nelem)
313
return minsz(minsz(nelem));
316
static void hgrow(hashtab *ht)
318
unsigned nelem = ht->nelem;
319
if (minsz(nelem) >= ht->hashsiz)
320
rehash(ht, nextsz(nelem));
324
/* shrink the hash table, never used */
325
static void hshrink(hashtab *ht)
327
unsigned nelem = ht->nelem;
328
/* always rehash after deletions */
329
rehash(ht, nextsz(nelem));
333
static void htab_insert(hashtab *ht, const md5sig s, const flags_t *flagsp,
336
unsigned g, h = h1(ht, s), d = h2(ht, s);
339
/* Remove all entries that are subsumed by the new one. */
340
/* This loop may potentially traverse the whole table, since at
341
least one element is guaranteed to be !LIVEP, but all elements
342
may be VALIDP. Hence, we stop after at the first invalid
343
element or after traversing the whole table. */
346
solution *l = ht->solutions + g;
349
if (LIVEP(l) && md5eq(s, l->s)) {
350
if (subsumes(flagsp, slvndx, &l->flags)) {
351
if (!first) first = l;
354
/* It is an error to insert an element that
355
is subsumed by an existing entry. */
356
A(!subsumes(&l->flags, SLVNDX(l), flagsp));
362
g = addmod(g, d, ht->hashsiz);
366
/* overwrite FIRST */
367
fill_slot(ht, s, flagsp, slvndx, first);
369
/* create a new entry */
371
hinsert0(ht, s, flagsp, slvndx);
375
static void hinsert(planner *ego, const md5sig s, const flags_t *flagsp,
378
htab_insert(BLISS(*flagsp) ? &ego->htab_blessed : &ego->htab_unblessed,
383
static void invoke_hook(planner *ego, plan *pln, const problem *p,
387
ego->hook(ego, pln, p, optimalp);
390
double X(iestimate_cost)(const plan *pln)
405
static void evaluate_plan(planner *ego, plan *pln, const problem *p)
407
if (ESTIMATEP(ego) || !BELIEVE_PCOSTP(ego) || pln->pcost == 0.0) {
410
if (ESTIMATEP(ego)) {
413
pln->pcost = X(iestimate_cost)(pln);
414
ego->epcost += pln->pcost;
416
double t = X(measure_execution_time)(pln, p);
418
if (t < 0) { /* unavailable cycle counter */
419
/* Real programmers can write FORTRAN in any language */
425
ego->need_timeout_check = 1;
429
invoke_hook(ego, pln, p, 0);
432
/* maintain dynamic scoping of flags, nthr: */
433
static plan *invoke_solver(planner *ego, problem *p, solver *s,
434
const flags_t *nflags)
436
flags_t flags = ego->flags;
437
int nthr = ego->nthr;
439
ego->flags = *nflags;
440
PLNR_TIMELIMIT_IMPATIENCE(ego) = 0;
441
A(p->adt->problem_kind == s->adt->problem_kind);
442
pln = s->adt->mkplan(s, p, ego);
448
/* maintain the invariant TIMED_OUT ==> NEED_TIMEOUT_CHECK */
449
static int timeout_p(planner *ego)
451
/* do not timeout when estimating. First, the estimator is the
452
planner of last resort. Second, calling X(elapsed_since)() is
453
slower than estimating */
454
if (!ESTIMATEP(ego)) {
455
/* do not assume that X(elapsed_since)() is monotonic */
456
if (ego->timed_out) {
457
A(ego->need_timeout_check);
461
if (ego->timelimit >= 0 &&
462
X(elapsed_since)(ego->start_time) >= ego->timelimit) {
464
ego->need_timeout_check = 1;
470
ego->need_timeout_check = 0;
474
static plan *search0(planner *ego, problem *p, unsigned *slvndx,
475
const flags_t *flagsp)
478
int best_not_yet_timed = 1;
480
/* Do not start a search if the planner timed out. This check is
481
necessary, lest the relaxation mechanism kick in */
485
FORALL_SOLVERS_OF_KIND(p->adt->problem_kind, ego, s, sp, {
488
pln = invoke_solver(ego, p, s, flagsp);
490
if (ego->need_timeout_check)
491
if (timeout_p(ego)) {
492
X(plan_destroy_internal)(pln);
493
X(plan_destroy_internal)(best);
498
/* read COULD_PRUNE_NOW_P because PLN may be destroyed
499
before we use COULD_PRUNE_NOW_P */
500
int could_prune_now_p = pln->could_prune_now_p;
503
if (best_not_yet_timed) {
504
evaluate_plan(ego, best, p);
505
best_not_yet_timed = 0;
507
evaluate_plan(ego, pln, p);
508
if (pln->pcost < best->pcost) {
509
X(plan_destroy_internal)(best);
511
*slvndx = sp - ego->slvdescs;
513
X(plan_destroy_internal)(pln);
517
*slvndx = sp - ego->slvdescs;
520
if (ALLOW_PRUNINGP(ego) && could_prune_now_p)
528
static plan *search(planner *ego, problem *p, unsigned *slvndx,
534
/* relax impatience in this order: */
535
static const unsigned relax_tab[] = {
536
0, /* relax nothing */
538
NO_FIXED_RADIX_LARGE_N,
543
unsigned l_orig = flagsp->l;
544
unsigned x = flagsp->u;
546
/* guaranteed to be different from X */
547
unsigned last_x = ~x;
549
for (i = 0; i < sizeof(relax_tab) / sizeof(relax_tab[0]); ++i) {
550
if (LEQ(l_orig, x & ~relax_tab[i]))
551
x = x & ~relax_tab[i];
556
pln = search0(ego, p, slvndx, flagsp);
562
/* search [L_ORIG, U] */
563
if (l_orig != last_x) {
566
pln = search0(ego, p, slvndx, flagsp);
573
#define CHECK_FOR_BOGOSITY \
574
if (ego->wisdom_state == WISDOM_IS_BOGUS) \
577
static plan *mkplan(planner *ego, problem *p)
582
flags_t flags_of_solution;
586
ASSERT_ALIGNED_DOUBLE;
587
A(LEQ(PLNR_L(ego), PLNR_U(ego)));
590
PLNR_TIMELIMIT_IMPATIENCE(ego) = 0; /* canonical form */
594
check(&ego->htab_blessed);
595
check(&ego->htab_unblessed);
607
flags_of_solution = ego->flags;
609
if ((ego->wisdom_state != WISDOM_IGNORE_ALL) &&
610
(sol = hlookup(ego, m.s, &flags_of_solution))) {
611
/* wisdom is acceptable */
612
wisdom_state_t owisdom_state = ego->wisdom_state;
613
slvndx = SLVNDX(sol);
615
if (slvndx == INFEASIBLE_SLVNDX) {
616
if (ego->wisdom_state == WISDOM_IGNORE_INFEASIBLE)
619
return 0; /* known to be infeasible */
622
flags_of_solution = sol->flags;
624
/* inherit blessing either from wisdom
625
or from the planner */
626
flags_of_solution.hash_info |= BLISS(ego->flags);
628
ego->wisdom_state = WISDOM_ONLY;
630
s = ego->slvdescs[slvndx].slv;
631
if (p->adt->problem_kind != s->adt->problem_kind)
632
goto wisdom_is_bogus;
634
pln = invoke_solver(ego, p, s, &flags_of_solution);
636
CHECK_FOR_BOGOSITY; /* catch error in child solvers */
638
sol = 0; /* Paranoia: SOL may be dangling after
639
invoke_solver(); make sure we don't accidentally
643
goto wisdom_is_bogus;
645
ego->wisdom_state = owisdom_state;
651
/* cannot search in WISDOM_ONLY mode */
652
if (ego->wisdom_state == WISDOM_ONLY)
653
goto wisdom_is_bogus;
655
flags_of_solution = ego->flags;
656
pln = search(ego, p, &slvndx, &flags_of_solution);
657
CHECK_FOR_BOGOSITY; /* catch error in child solvers */
659
if (ego->timed_out) {
661
if (PLNR_TIMELIMIT_IMPATIENCE(ego) != 0) {
662
/* record (below) that this plan has failed because of
664
flags_of_solution.hash_info |= BLESSING;
666
/* this is not the top-level problem or timeout is not
667
active: record no wisdom. */
671
/* canonicalize to infinite timeout */
672
flags_of_solution.timelimit_impatience = 0;
676
if (ego->wisdom_state == WISDOM_NORMAL ||
677
ego->wisdom_state == WISDOM_ONLY) {
679
hinsert(ego, m.s, &flags_of_solution, slvndx);
680
invoke_hook(ego, pln, p, 1);
682
hinsert(ego, m.s, &flags_of_solution, INFEASIBLE_SLVNDX);
689
X(plan_destroy_internal)(pln);
690
ego->wisdom_state = WISDOM_IS_BOGUS;
694
static void htab_destroy(hashtab *ht)
696
X(ifree)(ht->solutions);
701
static void mkhashtab(hashtab *ht)
704
ht->succ_lookup = ht->lookup = ht->lookup_iter = 0;
705
ht->insert = ht->insert_iter = ht->insert_unknown = 0;
708
ht->hashsiz = ht->nelem = 0U;
709
hgrow(ht); /* so that hashsiz > 0 */
712
/* destroy hash table entries. If FORGET_EVERYTHING, destroy the whole
713
table. If FORGET_ACCURSED, then destroy entries that are not blessed. */
714
static void forget(planner *ego, amnesia a)
717
case FORGET_EVERYTHING:
718
htab_destroy(&ego->htab_blessed);
719
mkhashtab(&ego->htab_blessed);
721
case FORGET_ACCURSED:
722
htab_destroy(&ego->htab_unblessed);
723
mkhashtab(&ego->htab_unblessed);
730
/* FIXME: what sort of version information should we write? */
731
#define WISDOM_PREAMBLE PACKAGE "-" VERSION " " STRINGIZE(X(wisdom))
732
static const char stimeout[] = "TIMEOUT";
734
/* tantus labor non sit cassus */
735
static void exprt(planner *ego, printer *p)
738
hashtab *ht = &ego->htab_blessed;
740
p->print(p, "(" WISDOM_PREAMBLE "\n");
741
for (h = 0; h < ht->hashsiz; ++h) {
742
solution *l = ht->solutions + h;
747
if (SLVNDX(l) == INFEASIBLE_SLVNDX) {
751
slvdesc *sp = ego->slvdescs + SLVNDX(l);
752
reg_nam = sp->reg_nam;
756
/* qui salvandos salvas gratis
757
salva me fons pietatis */
758
p->print(p, " (%s %d #x%x #x%x #x%x #x%M #x%M #x%M #x%M)\n",
760
l->flags.l, l->flags.u, l->flags.timelimit_impatience,
761
l->s[0], l->s[1], l->s[2], l->s[3]);
767
/* mors stupebit et natura
768
cum resurget creatura */
769
static int imprt(planner *ego, scanner *sc)
771
char buf[MAXNAM + 1];
773
unsigned l, u, timelimit_impatience;
777
hashtab *ht = &ego->htab_blessed;
780
if (!sc->scan(sc, "(" WISDOM_PREAMBLE))
781
return 0; /* don't need to restore hashtable */
783
/* make a backup copy of the hash table (cache the hash) */
785
unsigned h, hsiz = ht->hashsiz;
787
old.solutions = (solution *)MALLOC(hsiz * sizeof(solution), HASHT);
788
for (h = 0; h < hsiz; ++h)
789
old.solutions[h] = ht->solutions[h];
793
if (sc->scan(sc, ")"))
796
/* qua resurget ex favilla */
797
if (!sc->scan(sc, "(%*s %d #x%x #x%x #x%x #x%M #x%M #x%M #x%M)",
798
MAXNAM, buf, ®_id, &l, &u, &timelimit_impatience,
799
sig + 0, sig + 1, sig + 2, sig + 3))
802
if (!strcmp(buf, stimeout) && reg_id == 0) {
803
slvndx = INFEASIBLE_SLVNDX;
805
if (timelimit_impatience != 0)
808
slvndx = slookup(ego, buf, reg_id);
809
if (slvndx == INFEASIBLE_SLVNDX)
813
/* inter oves locum praesta */
816
flags.timelimit_impatience = timelimit_impatience;
817
flags.hash_info = BLESSING;
821
CK(flags.timelimit_impatience == timelimit_impatience);
823
hinsert(ego, sig, &flags, slvndx);
826
X(ifree0)(old.solutions);
830
/* ``The wisdom of FFTW must be above suspicion.'' */
831
X(ifree0)(ht->solutions);
839
planner *X(mkplanner)(void)
843
static const planner_adt padt = {
844
register_solver, mkplan, forget, exprt, imprt
847
planner *p = (planner *) MALLOC(sizeof(planner), PLANNERS);
850
p->nplan = p->nprob = 0;
851
p->pcost = p->epcost = 0.0;
854
p->wisdom_state = WISDOM_NORMAL;
857
p->nslvdesc = p->slvdescsiz = 0;
861
p->flags.timelimit_impatience = 0;
862
p->flags.hash_info = 0;
864
p->need_timeout_check = 1;
867
mkhashtab(&p->htab_blessed);
868
mkhashtab(&p->htab_unblessed);
870
for (i = 0; i < PROBLEM_LAST; ++i)
871
p->slvdescs_for_problem_kind[i] = -1;
876
void X(planner_destroy)(planner *ego)
878
/* destroy hash table */
879
htab_destroy(&ego->htab_blessed);
880
htab_destroy(&ego->htab_unblessed);
882
/* destroy solvdesc table */
883
FORALL_SOLVERS(ego, s, sp, {
885
X(solver_destroy)(s);
888
X(ifree0)(ego->slvdescs);
889
X(ifree)(ego); /* dona eis requiem */
892
plan *X(mkplan_d)(planner *ego, problem *p)
894
plan *pln = ego->adt->mkplan(ego, p);
895
X(problem_destroy)(p);
899
/* like X(mkplan_d), but sets/resets flags as well */
900
plan *X(mkplan_f_d)(planner *ego, problem *p,
901
unsigned l_set, unsigned u_set, unsigned u_reset)
903
flags_t oflags = ego->flags;
906
PLNR_U(ego) &= ~u_reset;
907
PLNR_L(ego) &= ~u_reset;
908
PLNR_L(ego) |= l_set;
909
PLNR_U(ego) |= u_set | l_set;
910
pln = X(mkplan_d)(ego, p);
919
static void check(hashtab *ht)
924
A(ht->nelem < ht->hashsiz);
926
for (i = 0; i < ht->hashsiz; ++i) {
927
solution *l = ht->solutions + i;
932
A(ht->nelem == live);
934
for (i = 0; i < ht->hashsiz; ++i) {
935
solution *l1 = ht->solutions + i;
938
unsigned g, h = h1(ht, l1->s), d = h2(ht, l1->s);
942
solution *l = ht->solutions + g;
946
else if (LIVEP(l) && md5eq(l1->s, l->s)) {
947
A(!subsumes(&l->flags, SLVNDX(l), &l1->flags));
948
A(!subsumes(&l1->flags, SLVNDX(l1), &l->flags));
952
g = addmod(g, d, ht->hashsiz);