void srcfss(stack *st, value cur) { #ifdef TREEDOT st->id = count; printf("ID = %zu\n", st->id); if (st->id) fprintf(st->dot, "\t%zu -> %zu;\n", (st - 1)->id, st->id); printcs(st); #endif count++; if (cur < min) { min = cur; sol = *st; } #ifdef LIMIT if (!stop) { gettimeofday(&t2, NULL); if ((double)(t2.tv_usec - t1.tv_usec) / 1e6 + t2.tv_sec - t1.tv_sec > LIMIT) stop = true; } #ifndef COMPLETEFRONTIER else return; #endif #endif #ifdef BOUND const value b = bound(st); #ifdef LIMIT if (stop) { if (b < bou) bou = b; return; } else #endif if (b >= min - MINGAIN) return; #endif chunk tmp[C], rt[C]; memcpy(tmp, st->c, sizeof(chunk) * C); MASKAND(tmp, st->r, tmp, C); edge popc = MASKPOPCNT(tmp, C); for (edge i = 0, e = MASKFFS(tmp, C); !stop && i < popc; i++, e = MASKCLEARANDFFS(tmp, e, C)) { agent v1 = X(st->a, e); agent v2 = Y(st->a, e); // At least one of the two coalitions must be a car if (!(st->dr[v1] + st->dr[v2])) continue; memcpy(rt, st->r, sizeof(chunk) * C); CLEAR(st->r, st->g[v1 * N + v2]); CLEAR(tmp, st->g[v1 * N + v2]); // Must not exceed the number of seats and the maximum number of drivers if (X(st->s, v1) + X(st->s, v2) > K || st->dr[v1] + st->dr[v2] > MAXDRIVERS) continue; CLEAR(st->c, st->g[v1 * N + v2]); st[1] = st[0]; memcpy(st[1].r, rt, sizeof(chunk) * C); merge(st + 1, v1, v2); contract(st + 1, v1, v2); st[1].l[v1] = minpath(st[1].cs + Y(st[1].s, v1), X(st[1].s, v1), st[1].dr[v1], st->sp); srcfss(st + 1, cur + COST(v1, st[1].dr, st[1].l) - COST(v1, st->dr, st->l) - COST(v2, st->dr, st->l)); } }
enqueue(pqueue *q, node * x) { int parent, leaf; node value, temp; if (q->count >= PQUEUESIZE) { printf("Warning: pqueue overflow enpqueue x=%dn",x); return; } q->count++; leaf = q->count - 1; q->q[leaf] = *x; // percolate up parent = PARENT(leaf); value = q->q[leaf]; while(leaf > 0 && (COST(q->q[leaf]) < COST(q->q[parent]))) { temp = q->q[leaf]; q->q[leaf] = q->q[parent]; q->q[parent] = temp; leaf = parent; parent = PARENT(leaf); } q->q[leaf] = value; }
void cmcostinit (struct tty_display_info *tty) { char *p; #define COST(x,e) (x ? (cost = 0, tputs (x, 1, e), cost) : BIG) #define CMCOST(x,e) ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e))) tty->Wcm->cc_up = COST (tty->Wcm->cm_up, evalcost); tty->Wcm->cc_down = COST (tty->Wcm->cm_down, evalcost); tty->Wcm->cc_left = COST (tty->Wcm->cm_left, evalcost); tty->Wcm->cc_right = COST (tty->Wcm->cm_right, evalcost); tty->Wcm->cc_home = COST (tty->Wcm->cm_home, evalcost); tty->Wcm->cc_cr = COST (tty->Wcm->cm_cr, evalcost); tty->Wcm->cc_ll = COST (tty->Wcm->cm_ll, evalcost); tty->Wcm->cc_tab = tty->Wcm->cm_tabwidth ? COST (tty->Wcm->cm_tab, evalcost) : BIG; /* * These last three are actually minimum costs. When (if) they are * candidates for the least-cost motion, the real cost is computed. * (Note that "0" is the assumed to generate the minimum cost. * While this is not necessarily true, I have yet to see a terminal * for which is not; all the terminals that have variable-cost * cursor motion seem to take straight numeric values. --ACT) */ tty->Wcm->cc_abs = CMCOST (tty->Wcm->cm_abs, evalcost); tty->Wcm->cc_habs = CMCOST (tty->Wcm->cm_habs, evalcost); tty->Wcm->cc_vabs = CMCOST (tty->Wcm->cm_vabs, evalcost); #undef CMCOST #undef COST }
node dequeue(pqueue *q) { int heapsize, root, childpos; node minVal, temp; node value; minVal = q->q[0]; q->q[0] = q->q[q->count-1]; // take last element and put on root of tree q->count--; // adjust size root = 0; if(q->count > 1) { // percolate down heapsize = q->count; value = q->q[root]; // get root while(root < heapsize) { childpos = LEFT(root); if(childpos < heapsize) { if((RIGHT(root) < heapsize) && (COST(q->q[childpos+1]) < COST(q->q[childpos]))) { childpos++; } if(COST(q->q[childpos]) < COST(q->q[root])) { temp = q->q[root]; q->q[root] = q->q[childpos]; q->q[childpos] = temp; root = childpos; } else { q->q[root] = value; break; } } else { q->q[root] = value; break; } } } return minVal; }
void printcs(const stack *st) { const agent *p = st->n + N + 1; agent m = st->n[N]; do { agent i = *(p++); printf("{ "); for (agent j = 0; j < X(st->s, i); j++) printf("%s%u%s%s ", i == st->cs[Y(st->s, i) + j] ? "<" : "", st->cs[Y(st->s, i) + j], i == st->cs[Y(st->s, i) + j] ? ">" : "", j < st->dr[i] ? "*" : ""); printf("} (%um) = %.2f€\n", st->l[i], EURO(COST(i, st->dr, st->l))); } while (--m); }
int main(int argc, char *argv[]) { // Allocate stack stack st[N]; // Create shortest paths matrix const unsigned seed = atoi(argv[1]); st->sp = createsp(seed); // Generate random set of drivers for (agent i = 0; i < D; i++) st->dr[i] = 1; memset(st->dr + D, 0, sizeof(agent) * (N - D)); shuffle(st->dr, N, sizeof(agent)); memcpy(drg, st->dr, N * sizeof(agent)); // Initialise n, s, and cs data structures st->n[N] = N; for (agent i = 0; i < N; i++) { X(sg, i) = X(st->s, i) = 1; Y(sg, i) = Y(st->s, i) = csg[i] = st->cs[i] = i; st->l[i] = st->sp[4 * i * N + 2 * i + 1]; min += COST(i, st->dr, st->l); st->n[st->n[i] = N + i + 1] = i; } // Initialise c and r bitmasks ONES(st->c, E + 1, C); CLEAR(st->c, 0); ONES(st->r, E + 1, C); CLEAR(st->r, 0); // Create graph #ifdef M init(seed); memset(st->g, 0, sizeof(edge) * N * N); scalefree(st->g, st->a); #else FILE *f = fopen(argv[2], "r"); for (agent e = 1; e <= E; e++) { agent v1, v2; fscanf(f, "%u %u", &v1, &v2); createedge(st->g, st->a, v1, v2, e); } fclose(f); #endif // Reorder (eventually) #ifdef REORDER edge go[N * N] = {0}; agent ao[2 * (E + 1)]; #ifdef METIS idx_t options[METIS_NOPTIONS]; METIS_SetDefaultOptions(options); options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; options[METIS_OPTION_SEED] = seed; real_t tpwgts[2] = {0.5, 0.5}, ubvec = TOLERANCE; agent map[N]; edge e = 1; for (agent i = 0; i < N; i++) map[i] = i; reorderedges(st->g, map, N, E, go, ao, &e, tpwgts, &ubvec, options); #else driversbfs(st->a, st->dr, go, ao); #endif memcpy(st->g, go, sizeof(edge) * N * N); memcpy(st->a, ao, sizeof(agent) * 2 * (E + 1)); #endif #ifdef TREEDOT st->dot = fopen(TREEDOT, "w+"); fprintf(st->dot, "digraph TREE {\n"); fprintf(st->dot, "\tnode [color = none; shape = plaintext, width = 0.2, height = 0.2];\n"); #endif // Solve sol = *st; #ifdef LIMIT value bou = bound(st); #endif gettimeofday(&t1, NULL); srcfss(st, min); gettimeofday(&t2, NULL); // Print solution #ifdef TREEDOT printf("SOLUTION = %zu\n", sol.id); fprintf(st->dot, "\t%zu [shape = circle, style = filled, fillcolor = green];\n", sol.id); #endif #ifdef PK FILE *pk = fopen(PK, "w+"); fprintf(pk, "%u\n%u\n%u\n", N, K, seed); printg(st->g, pk); printpk(&sol, pk); fclose(pk); #endif #ifdef CSV printf("%u,%u,%s,%.2f,%f,%zu\n", N, E, argv[1], 0.01 * min, (double)(t2.tv_usec - t1.tv_usec) / 1e6 + t2.tv_sec - t1.tv_sec, count); #else printcs(&sol); printf("Visited nodes = %zu\n", count); printf("Elapsed time = %f\n", (double)(t2.tv_usec - t1.tv_usec) / 1e6 + t2.tv_sec - t1.tv_sec); printf("Solution = %.2f€\n", 0.01 * min); #ifdef LIMIT printf("Bound = %.2f€\n", 0.01 * bou); #endif #endif // Free data structures #ifdef TREEDOT fprintf(st->dot, "}"); fclose(st->dot); #endif free(st->sp); return 0; }
__attribute__((always_inline)) inline value bound(const stack *st) { stack tst = *st; agent i, m = st->n[N]; const agent *p = st->n + N + 1; value b = 0; agent cars[N] = {0}; agentpath mp[N]; meter et[2 * N]; memcpy(tst.dr, drg, sizeof(agent) * N); memcpy(tst.cs, csg, sizeof(agent) * N); memcpy(tst.s, sg, sizeof(agent) * 2 * N); do { i = *(p++); cars[i] = (st->dr[i] > 0); } while (--m); connect(&tst, cars); p = tst.n + N + 1; m = tst.n[N]; do if (X(tst.s, i = *(p++)) == 1) b += COST(i, st->dr, st->l); else { agent cy, ck, tr = 0, ccx = X(tst.s, i); value pc, b1 = 0, b2 = 0; for (agent j = 0; j < ccx; j++) for (agent k = 0; k < X(st->s, cy = tst.cs[Y(tst.s, i) + j]); k++) { ck = st->cs[Y(st->s, cy) + k]; if (st->dr[ck]) b1 += PATHCOST(st->l[ck]); mp[tr].a = ck; mp[tr].d = st->dr[cy]; mp[tr].p = 0; tr++; } agent as = cars[i] * K; b += cars[i] * CARCOST + ((tr > as) ? (tr - as) * TICKETCOST : 0); if (cars[i]) { for (agent j = 0; j < tr; j++) { for (agent k = 0; k < tr; k++) { X(et, k) = st->sp[2 * mp[j].a * 2 * N + 2 * mp[k].a]; Y(et, k) = st->sp[2 * mp[j].a * 2 * N + 2 * mp[k].a + 1]; } QSORT(meter, et, 2 * tr, LT); mp[j].p += et[0] + (st->dr[mp[j].a] ? 0 : et[1]); for (agent k = 0; k < tr; k++) { X(et, k) = st->sp[(2 * mp[j].a + 1) * 2 * N + 2 * mp[k].a]; Y(et, k) = st->sp[(2 * mp[j].a + 1) * 2 * N + 2 * mp[k].a + 1]; } QSORT(meter, et, 2 * tr, LT); mp[j].p += et[0] + (st->dr[mp[j].a] ? 0 : et[1]); mp[j].p /= 2; } #define LTMP(a, b) ( ((*(a)).d != (*(b)).d) ? ((*(a)).d > (*(b)).d) : ((*(a)).p < (*(b)).p) ) QSORT(agentpath, mp, tr, LTMP); for (agent j = 0; j < (tr < as ? tr : as); j++) { pc = PATHCOST(mp[j].p); b2 += (pc > TICKETCOST) ? TICKETCOST : pc; } b += b1 > b2 ? b1 : b2; } //else b += tr * TICKETCOST; } while (--m); return b; }