#include "rscommon.h"
-//DEBUG_DEFINE_SOME_DEBUGF(sql,sql_dprintf);
+DEBUG_DEFINE_DEBUGF(value);
typedef struct {
int commodid, src_price, src_qty, dst_price, dst_qty;
TradesBlock *trades;
} IslandPair;
-int nislands=100;
+int nislands;
IslandPair ***ipairs; /* ipairs[sislandid][dislandid] */
static IslandPair *ipair_get(int si, int di) {
int inblock= TRADES_PER_BLOCK;
TradesBlock *block= 0;
+ debugf("VALUE ipair_get(%d,%d) running...\n", si,di);
SQL_MUST( sqlite3_bind_int(ss_ipair, 1, si) );
SQL_MUST( sqlite3_bind_int(ss_ipair, 2, di) );
void value_route(int nislands, const int *islands) {
int s,d;
-
+
+ /* We need to construct the LP problem. GLPK talks
+ * about rows and columns, which are numbered from 1.
+ *
+ * Each column is a `structural variable' ie one of the entries in
+ * the objective function. In our case the set of structural
+ * variable is, for each visit, the set of Trades which collect at
+ * that island. (We use `visit' to mean `specific visit to an
+ * island' so if an island appears more than once so do its trades.)
+ * We don't need to worry about crossing with all the possible
+ * delivery locations as we always deliver on the first visit.
+ * We will call such a structural variable a Flow, for brevity.
+ *
+ * We iterate over the possible Flows adding them as columns as we
+ * go, and also adding their entries to the various constraints.
+ *
+ * Each row is an `auxiliary variable' ie one of the constraints.
+ * We have two kinds of constraint:
+ * - mass/volume/capital: one constraint for each sailed leg
+ * (unless relevant constraint is not satisfied)
+ * - quantity of commodity available for collection
+ * or delivery at particular price and island
+ * The former are numbered predictably: we have first all the mass
+ * limits, then all the volume limits, then all the capital limits
+ * (as applicable) - one for each leg, ie one for each entry
+ * in islands except the first.
+ *
+ * The latter are added as needed and the row numbers are stored in
+ * a data structure for later reuse.
+ */
+
for (s=0; s<nislands; s++) {
+ int si= islands[s];
for (d=s; d<nislands; d++) {
- ipair_get(islands[s], islands[d]);
+ int di= islands[d];
+ int already_d;
+ for (already_d=s+1; already_d<d; already_d++)
+ if (islands[already_d] == di)
+ /* visited this island already since we left s */
+ goto next_d;
+ if (d>s && di==si)
+ /* route has returned to s, no need to think more about this */
+ goto next_d;
+
+ IslandPair *ip= ipair_get(islands[s], islands[d]);
+ TradesBlock *block= ip->trades;
+ int ntrades= ip->ntrades;
+ int inblock= 0;
+ while (ntrades-- >0) {
+ if (inblock >= TRADES_PER_BLOCK) {
+ block= block->next;
+ inblock= 0;
+ }
+ Trade *t= &block->t[inblock++];
+
+ debugf(" TRADE %d#%d..%d#%d %d %d-%d\n",
+ si,s, di,d, t->commodid, t->src_price, t->dst_price);
+
+ }
}
+ next_d:;
}
-
- //char *tail;
- //struct sqlite_vm *sth;
- //r= sqlite_compile(db, stmt, &tail, &sth,
}
void setup_value(void) {
+ sqlite3_stmt *sst;
+
+ SQL_MUST( sqlite3_prepare(db, "SELECT max(islandid) FROM islands",
+ -1,&sst,0) );
+ assert( SQL_STEP(sst) );
+ nislands= sqlite3_column_int(sst,0);
+ nislands++;
+ sqlite3_finalize(sst);
+ debugf("VALUE nislands=%d\n",nislands);
+
SQL_MUST( sqlite3_prepare(db,
"SELECT\n"
" sell.commodid commodid,\n"