chiark / gitweb /
WIP routesearch; before better SQL stmts
authorIan Jackson <ian@liberator.(none)>
Fri, 2 Oct 2009 21:10:19 +0000 (22:10 +0100)
committerIan Jackson <ian@liberator.(none)>
Fri, 2 Oct 2009 21:10:19 +0000 (22:10 +0100)
yarrg/rsvalue.c

index ad301b0..a1cdf0f 100644 (file)
@@ -1,6 +1,5 @@
 /**/
 
-#include <obstack.h>
 #include <glpk.h>
 
 #include "rscommon.h"
@@ -12,6 +11,7 @@ static int commodstablesz;
 static CommodInfo *commodstable;
 
 static sqlite3_stmt *ss_ipair_dist, *ss_ipair_trades;
+static sqlite3_stmt *ss_ite_buy, *ss_ite_sell;
 
 #define MAX_LEGS (MAX_ROUTELEN-1)
 
@@ -38,7 +38,9 @@ IslandPair ***ipairs; /* ipairs[sislandid][dislandid] */
 typedef struct IslandTradeEnd {
   struct IslandTradeEnd *next;
   int commodid, price;
-  int qty, rownum;
+  int qty;
+  unsigned long generation;
+  int rownum;
 } IslandTradeEnd, *IslandDirnTradeEnds;
 
 typedef struct {
@@ -46,8 +48,8 @@ typedef struct {
   IslandDirnTradeEnds collect, deliver;
 } IslandTradeEnds;
 
-static struct obstack ites_obstack;
 static LPX *lp;
+static unsigned long generation;
 
 static int nconstraint_rows;
 static int constraint_rows[1+2+3*MAX_LEGS];
@@ -60,34 +62,46 @@ static void add_constraint(int row, double coefficient) {
   constraint_coeffs[nconstraint_rows]= coefficient;
 }
 
-static void avail_constraint(const Trade *t, IslandDirnTradeEnds *trades,
-                            int price, int qty, const char *srcdst) {
+static void avail_c(const Trade *t, IslandDirnTradeEnds *trades,
+                   int price, const char *srcdst,
+                   int islandid, sqlite3_stmt *ss_ite) {
   /* find row number of trade availability constraint */
   IslandTradeEnd *search;
 
   for (search= *trades; search; search=search->next)
-    if (search->commodid==t->commodid && search->price==price) {
-      assert(search->qty == qty);
+    if (search->commodid==t->commodid && search->price==price)
       goto found;
-    }
   /* not found, add new row */
-  search= obstack_alloc(&ites_obstack, sizeof(*search));
+
+  search= mmalloc(sizeof(*search));
   search->commodid= t->commodid;
   search->price= price;
-  search->qty= qty;
-  search->rownum= lpx_add_rows(lp, 1);
   search->next= *trades;
-  if (DEBUGP(value)) {
-    char *name= masprintf("%s_commod%d_price%d",srcdst,t->commodid,price);
-    lpx_set_row_name(lp,search->rownum,name);
-    free(name);
-  }
+  search->generation= 0;
+
+  SQL_MUST( sqlite3_bind_int(ss_ite, 1, islandid) );
+  SQL_MUST( sqlite3_bind_int(ss_ite, 2, t->commodid) );
+  SQL_MUST( sqlite3_bind_int(ss_ite, 3, price) );
+  assert(SQL_STEP(ss_ite));
+  search->qty= sqlite3_column_int(ss_ite, 0);
+  SQL_MUST( sqlite3_reset(ss_ite) );
+  
   *trades= search;
+  
  found:;
-  int rownum= search->rownum;
+  if (search->generation != generation) {
+    search->rownum= lpx_add_rows(lp, 1);
+    lpx_set_row_bnds(lp, search->rownum, LPX_UP, 0, search->qty);
+
+    if (DEBUGP(value)) {
+      char *name= masprintf("%s_commod%d_price%d",srcdst,t->commodid,price);
+      lpx_set_row_name(lp,search->rownum,name);
+      free(name);
+    }
+    search->generation= generation;
+  }
 
-  lpx_set_row_bnds(lp, rownum, LPX_UP, 0, qty);
-  add_constraint(rownum, 1.0);
+  add_constraint(search->rownum, 1.0);
 }
 
 static int setup_leg_constraints(double max_thing, int legs, const char *wh) {
@@ -196,8 +210,7 @@ void value_route(int nislands, const int *islands) {
    */
 
   assert(nislands >= 1);
-
-  char *free_to_reset_obstack= obstack_alloc(&ites_obstack, 1);
+  assert(++generation);
 
   int nites=0;
   IslandTradeEnds ites[nislands], *iteps[nislands];
@@ -274,8 +287,8 @@ void value_route(int nislands, const int *islands) {
 
        nconstraint_rows=0;
 
-       avail_constraint(t, &iteps[s]->collect, t->src_price,t->src_qty,"src");
-       avail_constraint(t, &iteps[d]->deliver, t->dst_price,t->dst_qty,"dst");
+       avail_c(t, &iteps[s]->collect, t->src_price,"src", si, ss_ite_sell);
+       avail_c(t, &iteps[d]->deliver, t->dst_price,"dst", di, ss_ite_buy);
 
        int leg;
        for (leg=s; leg<d; leg++) {
@@ -306,18 +319,12 @@ void value_route(int nislands, const int *islands) {
 
   lpx_delete_prob(lp);
   lp= 0;
-
-  obstack_free(&ites_obstack, free_to_reset_obstack);
 }
 
 void setup_value(void) {
   sqlite3_stmt *sst;
   int i;
 
-#define obstack_chunk_alloc mmalloc
-#define obstack_chunk_free free
-  obstack_init(&ites_obstack);
-
   nislands= sql_single_int("SELECT max(islandid) FROM islands") + 1;
   debugf("VALUE nislands=%d\n",nislands);
 
@@ -337,23 +344,33 @@ void setup_value(void) {
   sqlite3_finalize(sst);
 
   SQL_MUST( sqlite3_prepare(db,
-     "SELECT\n"
+     " SELECT dist from dists where aiid=? and biid=?",
+                           -1, &ss_ipair_dist, 0) );
+
+  SQL_MUST( sqlite3_prepare(db,
+     "SELECT DISTINCT\n"
      " sell.commodid           commodid,\n"
      " sell.price              src_price,\n"
-     " sum(sell.qty)           src_qty,\n"
-     " buy.price               dst_price,\n"
-     " sum(buy.qty)            dst_qty\n"
+     " buy.price               dst_price\n"
      " FROM sell JOIN buy\n"
      "   ON sell.commodid = buy.commodid\n"
      "  AND buy.price > sell.price\n"
      " WHERE sell.islandid=?\n"
-     "   AND buy.islandid=?\n"
-     " GROUP BY sell.commodid, sell.price, buy.price",
+     "   AND buy.islandid=?",
                            -1, &ss_ipair_trades, 0) );
 
-  SQL_MUST( sqlite3_prepare(db,
-     " SELECT dist from dists where aiid=? and biid=?",
-                           -1, &ss_ipair_dist, 0) );
+#define BS(bs)                                         \
+  SQL_MUST( sqlite3_prepare(db,                                \
+     "SELECT\n"                                                \
+     " sum(qty)\n"                                     \
+     " FROM " #bs "\n"                                 \
+     " WHERE islandid=?\n"                             \
+     "   AND commodid=?\n"                             \
+     "   AND price=?",                                 \
+                           -1, &ss_ite_##bs, 0) );
+  BS(buy)
+  BS(sell)
+#undef BS
 
   ipairs= mcalloc(sizeof(*ipairs) * nislands);
 }