5 DEBUG_DEFINE_DEBUGF(value);
8 int commodid, src_price, src_qty, dst_price, dst_qty;
11 #define TRADES_PER_BLOCK 10
13 typedef struct TradesBlock{
14 struct TradesBlock *next;
15 Trade t[TRADES_PER_BLOCK];
24 IslandPair ***ipairs; /* ipairs[sislandid][dislandid] */
26 static IslandPair *ipair_get(int si, int di) {
27 IslandPair *ip, **ipa;
29 assert(si < nislands);
30 assert(di < nislands);
32 if (!(ipa= ipairs[si])) {
33 ipa= ipairs[si]= mcalloc(sizeof(*ipa) * nislands);
38 ipa[di]= ip= mmalloc(sizeof(*ip));
41 int inblock= TRADES_PER_BLOCK;
42 TradesBlock *block= 0;
44 debugf("VALUE ipair_get(%d,%d) running...\n", si,di);
45 SQL_MUST( sqlite3_bind_int(ss_ipair, 1, si) );
46 SQL_MUST( sqlite3_bind_int(ss_ipair, 2, di) );
48 while (SQL_STEP(ss_ipair)) {
49 if (inblock == TRADES_PER_BLOCK) {
50 block= mmalloc(sizeof(*block));
51 block->next= ip->trades;
56 for (i=0, irp=&block->t[inblock].commodid; i<5; i++, irp++)
57 *irp= sqlite3_column_int(ss_ipair, i);
61 if (inblock < TRADES_PER_BLOCK)
62 block->t[inblock].commodid= -1;
64 sqlite3_reset(ss_ipair);
69 void value_route(int nislands, const int *islands) {
72 /* We need to construct the LP problem. GLPK talks
73 * about rows and columns, which are numbered from 1.
75 * Each column is a `structural variable' ie one of the entries in
76 * the objective function. In our case the set of structural
77 * variable is, for each visit, the set of Trades which collect at
78 * that island. (We use `visit' to mean `specific visit to an
79 * island' so if an island appears more than once so do its trades.)
80 * We don't need to worry about crossing with all the possible
81 * delivery locations as we always deliver on the first visit.
82 * We will call such a structural variable a Flow, for brevity.
84 * We iterate over the possible Flows adding them as columns as we
85 * go, and also adding their entries to the various constraints.
87 * Each row is an `auxiliary variable' ie one of the constraints.
88 * We have two kinds of constraint:
89 * - mass/volume/capital: one constraint for each sailed leg
90 * (unless relevant constraint is not satisfied)
91 * - quantity of commodity available for collection
92 * or delivery at particular price and island
93 * The former are numbered predictably: we have first all the mass
94 * limits, then all the volume limits, then all the capital limits
95 * (as applicable) - one for each leg, ie one for each entry
96 * in islands except the first.
98 * The latter are added as needed and the row numbers are stored in
99 * a data structure for later reuse.
102 for (s=0; s<nislands; s++) {
104 for (d=s; d<nislands; d++) {
107 for (already_d=s+1; already_d<d; already_d++)
108 if (islands[already_d] == di)
109 /* visited this island already since we left s */
112 /* route has returned to s, no need to think more about this */
115 IslandPair *ip= ipair_get(islands[s], islands[d]);
116 TradesBlock *block= ip->trades;
117 int ntrades= ip->ntrades;
119 while (ntrades-- >0) {
120 if (inblock >= TRADES_PER_BLOCK) {
124 Trade *t= &block->t[inblock++];
126 debugf(" TRADE %d#%d..%d#%d %d %d-%d\n",
127 si,s, di,d, t->commodid, t->src_price, t->dst_price);
135 void setup_value(void) {
138 SQL_MUST( sqlite3_prepare(db, "SELECT max(islandid) FROM islands",
140 assert( SQL_STEP(sst) );
141 nislands= sqlite3_column_int(sst,0);
143 sqlite3_finalize(sst);
144 debugf("VALUE nislands=%d\n",nislands);
146 SQL_MUST( sqlite3_prepare(db,
148 " sell.commodid commodid,\n"
149 " sell.price src_price,\n"
150 " sum(sell.qty) src_qty,\n"
151 " buy.price dst_price,\n"
152 " sum(buy.qty) dst_qty\n"
153 " FROM sell JOIN buy\n"
154 " ON sell.commodid = buy.commodid\n"
155 " AND buy.price > sell.price\n"
156 " WHERE sell.islandid=?\n"
157 " AND buy.islandid=?\n"
158 " GROUP BY sell.commodid, sell.price, buy.price",
161 ipairs= mcalloc(sizeof(*ipairs) * nislands);