From: Ian Jackson Date: Fri, 2 Oct 2009 21:58:26 +0000 (+0100) Subject: WIP routesearch; before try not using interior point X-Git-Tag: 5.0^2~92 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.web-live.git;a=commitdiff_plain;h=23f08e0abdbd5212e4a867c80f7833e4ebcbb1cf WIP routesearch; before try not using interior point --- diff --git a/yarrg/Makefile b/yarrg/Makefile index ca05ff5..ed4f372 100644 --- a/yarrg/Makefile +++ b/yarrg/Makefile @@ -38,7 +38,7 @@ all: default routesearch CONVERT_OBJS= convert.o ocr.o pages.o structure.o rgbimage.o resolve.o COMMON_OBJS= common.o -ROUTESEARCH_OBJS= rsvalue.o rsmain.o rssetup.o +ROUTESEARCH_OBJS= rsvalue.o rsmain.o rssql.o yarrg: $(CONVERT_OBJS) $(COMMON_OBJS) -lnetpbm -lXtst -lX11 -lpcre -lm $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) diff --git a/yarrg/common.h b/yarrg/common.h index 0856274..22f61cb 100644 --- a/yarrg/common.h +++ b/yarrg/common.h @@ -86,7 +86,9 @@ enum { extern unsigned debug_flags; void debug_flush(void); -#define debug stderr +#ifndef debug +# define debug stderr +#endif #define FMT(f,a) __attribute__((format(printf,f,a))) #define SCANFMT(f,a) __attribute__((format(scanf,f,a))) diff --git a/yarrg/rscommon.h b/yarrg/rscommon.h index b1003bf..860409e 100644 --- a/yarrg/rscommon.h +++ b/yarrg/rscommon.h @@ -5,20 +5,26 @@ #define DEBUG_FLAG_LIST \ DF(sql) \ - DF(value) + DF(sql2) \ + DF(value) \ + DF(lp) +#define debug stdout + +#include "common.h" -#define SQL_MUST( call ) ({ \ +#define SQL_MUST( call ) ({ \ /* `call' is an expression returning result, using const char *sqe; \ * chk1 and chk2 are blocks using sqe and int sqr; */ \ const char *sql_must_call_string= #call; \ int sqr; \ - if (DEBUGP(sql)) fprintf(stderr,"SQL %s", sql_must_call_string); \ + if (DEBUGP(sql2)) fprintf(stderr,"SQL %s", sql_must_call_string); \ sqr= (call); \ - if (DEBUGP(sql)) fprintf(stderr," = %d\n", sqr); \ - if (sqr) fatal("SQL call failed code %d: %s: %s", \ - sqr, sqlite3_errmsg(db), sql_must_call_string); \ - }) + if (DEBUGP(sql2)) fprintf(stderr," = %d\n", sqr); \ + if (sqr) sql_fatal("(unknown)", sqr, sql_must_call_string); \ + }) \ + +void sql_fatal(const char *stmt_what, int sqr, const char *act_what) NORET; #define SQL_STEP(ssh) (sql_step_wrap((ssh), #ssh, __FILE__, __LINE__)) int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string, @@ -26,14 +32,19 @@ int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string, int sql_single_int(const char *stmt); -#define MAX_ROUTELEN 20 +#define SQL_PREPARE(ss,stmt) ((ss)= sql_prepare((stmt),#ss)) +sqlite3_stmt *sql_prepare(const char *stmt, const char *what); -#include "common.h" +#define SQL_BIND(ss,index,value) (sql_bind((ss),(index),(value),#ss,#value)) +void sql_bind(sqlite3_stmt *ss, int index, int value, + const char *ss_what, const char *val_what); + +#define MAX_ROUTELEN 20 extern sqlite3 *db; void setup(void); -void value_route(int nislands, const int *islands); +double value_route(int nislands, const int *islands); void setup_value(void); void setup_commods(void); diff --git a/yarrg/rsmain.c b/yarrg/rsmain.c index ed17635..49a59a4 100644 --- a/yarrg/rsmain.c +++ b/yarrg/rsmain.c @@ -9,7 +9,7 @@ double distance_loss_factor_per_league; int main(int argc, const char **argv) { int ia[argc], ni=0; - debug_flags= ~0UL; + debug_flags= ~( dbg_sql2 ); setup(); max_mass= atof(*++argv); @@ -24,6 +24,7 @@ int main(int argc, const char **argv) { while ((arg= *++argv)) { ia[ni++]= atoi(arg); } - value_route(ni, ia); + double val= value_route(ni, ia); + printf("route value is %g\n", val); return 0; } diff --git a/yarrg/rssetup.c b/yarrg/rssql.c similarity index 51% rename from yarrg/rssetup.c rename to yarrg/rssql.c index dadeca6..463ef8b 100644 --- a/yarrg/rssetup.c +++ b/yarrg/rssql.c @@ -4,8 +4,10 @@ sqlite3 *db; sqlite3_stmt *ss_ipair; +DEBUG_DEFINE_DEBUGF(sql); + static int busy_handler(void *u, int previous) { - if (DEBUGP(sql)) fprintf(stderr,"[[DB BUSY %d]]",previous); + debugf("[[DB BUSY %d]]",previous); sysassert(! usleep(5000) ); return 1; } @@ -16,7 +18,7 @@ void setup(void) { SQL_MUST( sqlite3_open("OCEAN-Midnight.db", &db) ); SQL_MUST( sqlite3_busy_handler(db, busy_handler, 0) ); - SQL_MUST( sqlite3_prepare(db, "BEGIN", -1, &sst, 0) ); + sst= sql_prepare("BEGIN","(begin)"); assert( !SQL_STEP(sst) ); sqlite3_finalize(sst); @@ -25,13 +27,33 @@ void setup(void) { int sql_single_int(const char *stmt) { sqlite3_stmt *sst; - SQL_MUST( sqlite3_prepare(db, stmt, -1,&sst,0) ); + sst= sql_prepare(stmt,"(single int)"); assert( SQL_STEP(sst) ); int rv= sqlite3_column_int(sst,0); sqlite3_finalize(sst); return rv; } +void sql_fatal(const char *stmt_what, int sqr, const char *act_what) { + fatal("SQL call failed, stmt %s code %d: %s: %s", + stmt_what, sqr, sqlite3_errmsg(db), act_what); +} + +void sql_bind(sqlite3_stmt *ss, int index, int value, + const char *ss_what, const char *val_what) { + debugf("SQL BIND %s #%d = %d = %s\n", ss_what, index, value, val_what); + int sqr= sqlite3_bind_int(ss, index, value); + if (sqr) sql_fatal(ss_what, sqr, + masprintf("bind #%d (%s)", index, val_what)); +} + +sqlite3_stmt *sql_prepare(const char *stmt, const char *what) { + sqlite3_stmt *ssr; + debugf("SQL PREPARE %s [[\n%s\n]]\n", what, stmt); + SQL_MUST( sqlite3_prepare(db, stmt, -1, &ssr, 0) ); + return ssr; +} + int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string, const char *file, int line) { for (;;) { @@ -39,19 +61,18 @@ int sql_step_wrap(sqlite3_stmt *ssh, const char *ssh_string, sqr= sqlite3_step((ssh)); switch (sqr) { case SQLITE_DONE: - if (DEBUGP(sql)) - fprintf(stderr,"SQL %s DONE\n",ssh_string); + debugf("SQL %s DONE\n",ssh_string); return 0; case SQLITE_ROW: if (DEBUGP(sql)) { int i; - fprintf(stderr,"SQL %s R",ssh_string); + fprintf(debug,"SQL %s R",ssh_string); for (i=0; i", stderr); + fputs(txt ? txt : "", debug); } - fputs("\n",stderr); + fputs("\n",debug); } return 1; default: fatal("SQL step failed at %s:%d: code %d: %s: %s", diff --git a/yarrg/rsvalue.c b/yarrg/rsvalue.c index a1cdf0f..135583e 100644 --- a/yarrg/rsvalue.c +++ b/yarrg/rsvalue.c @@ -16,7 +16,7 @@ static sqlite3_stmt *ss_ite_buy, *ss_ite_sell; #define MAX_LEGS (MAX_ROUTELEN-1) typedef struct { - int commodid, src_price, src_qty, dst_price, dst_qty; + int commodid, src_price, dst_price; } Trade; #define TRADES_PER_BLOCK 10 @@ -79,9 +79,9 @@ static void avail_c(const Trade *t, IslandDirnTradeEnds *trades, search->next= *trades; 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) ); + SQL_BIND(ss_ite, 1, islandid); + SQL_BIND(ss_ite, 2, t->commodid); + SQL_BIND(ss_ite, 3, price); assert(SQL_STEP(ss_ite)); search->qty= sqlite3_column_int(ss_ite, 0); SQL_MUST( sqlite3_reset(ss_ite) ); @@ -94,7 +94,7 @@ static void avail_c(const Trade *t, IslandDirnTradeEnds *trades, 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); + char *name= masprintf("%s_c%d_%d",srcdst,t->commodid,price); lpx_set_row_name(lp,search->rownum,name); free(name); } @@ -163,7 +163,7 @@ static IslandPair *ipair_get(int si, int di) { inblock= 0; } int *irp, i; - for (i=0, irp=&block->t[inblock].commodid; i<5; i++, irp++) + for (i=0, irp=&block->t[inblock].commodid; i<3; i++, irp++) *irp= sqlite3_column_int(ss_ipair_trades, i); ip->ntrades++; inblock++; @@ -176,7 +176,7 @@ static IslandPair *ipair_get(int si, int di) { return ip; } -void value_route(int nislands, const int *islands) { +double value_route(int nislands, const int *islands) { int s,d; /* We need to construct the LP problem. GLPK talks @@ -234,6 +234,8 @@ void value_route(int nislands, const int *islands) { assert(!lp); lp= lpx_create_prob(); lpx_set_obj_dir(lp, LPX_MAX); + lpx_set_int_parm(lp, LPX_K_MSGLEV, DEBUGP(lp) ? 3 : 1); + if (DEBUGP(value)) { lpx_set_prob_name(lp,(char*)"value_route"); lpx_set_obj_name(lp,(char*)"profit"); @@ -303,11 +305,13 @@ void value_route(int nislands, const int *islands) { lpx_set_mat_col(lp, col, nconstraint_rows, constraint_rows, constraint_coeffs); if (DEBUGP(value)) { - char *name= masprintf("trade_commod%d_port%d_at%d_port%d_at%d", + char *name= masprintf("c%d_p%d_%d_p%d_%d", t->commodid, s, t->src_price, d, t->dst_price); lpx_set_col_name(lp, col, name); free(name); } + + col++; } /* while (tradestodo-- >0) */ /*----- that's done adding these trades to the LP problem -----*/ @@ -317,8 +321,22 @@ void value_route(int nislands, const int *islands) { next_s:; } /* for (s) */ + if (DEBUGP(lp)) + lpx_write_cpxlp(lp, (char*)"/dev/stdout"); + + int ipr= lpx_interior(lp); + assert(ipr==LPX_E_OK); + + if (DEBUGP(lp)) + lpx_print_ips(lp, (char*)"/dev/stdout"); + + assert(lpx_ipt_status(lp) == LPX_T_OPT); + double profit= lpx_ipt_obj_val(lp); + lpx_delete_prob(lp); lp= 0; + + return profit; } void setup_value(void) { @@ -333,8 +351,8 @@ void setup_value(void) { for (i=0; i=0 && id sell.price\n" - " WHERE sell.islandid=?\n" - " AND buy.islandid=?", - -1, &ss_ipair_trades, 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) ); + SQL_PREPARE(ss_ipair_dist, + " SELECT dist FROM dists\n" + " WHERE aiid=? and biid=?"); + + SQL_PREPARE(ss_ipair_trades, + "SELECT DISTINCT\n" + " sell.commodid commodid,\n" + " sell.price src_price,\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=?"); + +#define BS(bs) \ + SQL_PREPARE(ss_ite_##bs, \ + "SELECT\n" \ + " sum(qty)\n" \ + " FROM " #bs "\n" \ + " WHERE islandid=?\n" \ + " AND commodid=?\n" \ + " AND price=?"); BS(buy) BS(sell) #undef BS