From db63517f57d6f6a639c96eae3af99a85f8459854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sat, 27 Jun 2009 02:21:49 +0200 Subject: [PATCH] Machine is working, working on task1 --- ovm/CMakeLists.txt | 2 +- ovm/ovm.c | 52 ++++++++++++++++++++++---- ovm/ovm.h | 2 +- ovm/physics.h | 13 +++++++ ovm/task.c | 64 ++++++++++++++++++++++++++++++-- ovm/task.h | 25 +++++-------- ovm/task1.c | 85 ++++++++++++++++++++++++++++++++++-------- ovm/task_main.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++ ovm/trace.c | 82 +++++++++++++++++++++++++++++++++++++++++ ovm/trace.h | 24 ++++++++++++ 10 files changed, 398 insertions(+), 43 deletions(-) create mode 100644 ovm/physics.h create mode 100644 ovm/task_main.h create mode 100644 ovm/trace.c create mode 100644 ovm/trace.h diff --git a/ovm/CMakeLists.txt b/ovm/CMakeLists.txt index cab5733..79704b0 100644 --- a/ovm/CMakeLists.txt +++ b/ovm/CMakeLists.txt @@ -37,8 +37,8 @@ ADD_EXECUTABLE(ovmjit ADD_EXECUTABLE(task1 bin1.c - task.c task1.c + task.c trace.c ) SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed") diff --git a/ovm/ovm.c b/ovm/ovm.c index 92a5548..aa6e314 100644 --- a/ovm/ovm.c +++ b/ovm/ovm.c @@ -2,6 +2,8 @@ #include "ovm.h" #include +#undef CMPEPS + void ovm_free(ovm_t *ovm) { if (!ovm) return; g_slice_free1(ovm->limit * sizeof(instruction_t), ovm->instructions); @@ -23,7 +25,7 @@ ovm_t* ovm_load(const gchar *filename) { ovm->values = g_slice_alloc0(ovm->limit * sizeof(gdouble)); if (!g_file_get_contents(filename, &buf, &len, &err)) { - fprintf (stderr, "Unable to read file: %s\n", err->message); + fprintf (stderr, "Unable to read file %s: %s\n", filename, err->message); g_error_free (err); exit(1); } @@ -50,7 +52,7 @@ ovm_t* ovm_load(const gchar *filename) { } void ovm_print_c(ovm_t *ovm, const gchar *filename) { - guint i; + guint i, max_in=0, max_out=0; instruction_t *oi = ovm->instructions; gdouble *vi = ovm->values; guint64 *uvi = (guint64*) ovm->values; @@ -64,9 +66,11 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { } g_string_append_len(buf, CONST_STR_LEN( - "void ovm_step(gdouble scenario, gdouble *in, gdouble *out) {\n" + "void ovm_step(guint scenario, gdouble *in, gdouble *out) {\n" )); #define USED(i) (usedv[i] = TRUE, i) +#define USED_IN(i) (max_in = max_in > i ? max_in : i, i) +#define USED_OUT(i) (max_out = max_out > i ? max_out : i, i) for (i = 0; i < ovm->used; i++) { g_string_printf(str, "\t/* Invalid command: 0x%X */\n", (guint) oi[i]); switch (instr_dop(oi[i])) { @@ -78,6 +82,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { break; case SOP_CMPZ: switch (instr_sop_cmp(oi[i])) { +#if CMPEPS /* cmp with eps */ case CMP_LTZ: g_string_printf(str, "\tovm_status = (v%u.d < -eps);\n", USED(instr_sop_r1(oi[i]))); break; @@ -88,11 +93,28 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { g_string_printf(str, "\tovm_status = (fabs(v%u.d) <= eps);\n", USED(instr_sop_r1(oi[i]))); break; case CMP_GEZ: - g_string_printf(str, "\tovm_status = (v%u.d > eps);\n", USED(instr_sop_r1(oi[i]))); - break; - case CMP_GTZ: g_string_printf(str, "\tovm_status = (v%u.d >= -eps);\n", USED(instr_sop_r1(oi[i]))); break; + case CMP_GTZ: + g_string_printf(str, "\tovm_status = (v%u.d > eps);\n", USED(instr_sop_r1(oi[i]))); + break; +#else + case CMP_LTZ: + g_string_printf(str, "\tovm_status = (v%u.d < 0);\n", USED(instr_sop_r1(oi[i]))); + break; + case CMP_LEZ: + g_string_printf(str, "\tovm_status = (v%u.d <= 0);\n", USED(instr_sop_r1(oi[i]))); + break; + case CMP_EQZ: + g_string_printf(str, "\tovm_status = (v%u.d == 0);\n", USED(instr_sop_r1(oi[i]))); + break; + case CMP_GEZ: + g_string_printf(str, "\tovm_status = (v%u.d >= 0);\n", USED(instr_sop_r1(oi[i]))); + break; + case CMP_GTZ: + g_string_printf(str, "\tovm_status = (v%u.d > 0);\n", USED(instr_sop_r1(oi[i]))); + break; +#endif } break; case SOP_SQRT: @@ -105,7 +127,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { if (0x3e80 == instr_sop_r1(oi[i])) { g_string_printf(str, "\tv%u.d = scenario;\n", USED(i)); } else { - g_string_printf(str, "\tv%u.d = in[%u];\n", USED(i), instr_sop_r1(oi[i])); + g_string_printf(str, "\tv%u.d = in[%u];\n", USED(i), USED_IN(instr_sop_r1(oi[i]))); } break; } @@ -120,10 +142,14 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { g_string_printf(str, "\tv%u.d = v%u.d * v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_DIV: +#if CMPEPS g_string_printf(str, "\tv%u.d = (fabs(v%u.d) < eps) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i])); +#else + g_string_printf(str, "\tv%u.d = (v%u.d == 0) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i])); +#endif break; case OP_OUT: - g_string_printf(str, "\tout[%u] = v%u.d;\n", instr_dop_r1(oi[i]), USED(instr_dop_r2(oi[i]))); + g_string_printf(str, "\tout[%u] = v%u.d;\n", USED_OUT(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_PHI: g_string_printf(str, "\tv%u.d = ovm_status ? v%u.d : v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); @@ -145,8 +171,18 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) { "typedef union { gdouble d; guint64 i; } double_int;\n" "\n" "static gboolean ovm_status;\n" + "\n" + )); +#if CMPEPS + write(f, CONST_STR_LEN( "static const gdouble eps = 1e-300;\n" "\n" + )); +#endif + g_string_printf(str, "const guint ovm_outs = %u, ovm_ins = %u;\n", max_out+1, max_in+1); + write(f, GSTR_LEN(str)); + write(f, CONST_STR_LEN( + "\n" "static double_int v0" )); for (i = 1; i < ovm->used; i++) { diff --git a/ovm/ovm.h b/ovm/ovm.h index c1ca6bc..932a1d4 100644 --- a/ovm/ovm.h +++ b/ovm/ovm.h @@ -45,7 +45,7 @@ static inline guint instr_dop_r2(instruction_t i) { } static inline cmp_t instr_sop_cmp(instruction_t i) { - return (i >> 20) & 0xF; + return (i >> 21) & 0x7; } static inline guint instr_sop_r1(instruction_t i) { diff --git a/ovm/physics.h b/ovm/physics.h new file mode 100644 index 0000000..8dfe8dc --- /dev/null +++ b/ovm/physics.h @@ -0,0 +1,13 @@ +#ifndef OVM_PHYSICS_H +#define OVM_PHYSICS_H + +#include "base.h" + +#include + +#define G 6.67428e-11 +#define Me 6.0e24 +#define Re 6.357e6 + + +#endif diff --git a/ovm/task.c b/ovm/task.c index d5c11a2..6fe57f6 100644 --- a/ovm/task.c +++ b/ovm/task.c @@ -1,20 +1,78 @@ #include "task.h" +#include void task_free(task_t *task) { if (!task) return; + g_slice_free1(task->in_size * sizeof(gdouble), task->in_old); g_slice_free1(task->in_size * sizeof(gdouble), task->in); g_slice_free1(task->out_size * sizeof(gdouble), task->out); g_slice_free(task_t, task); } -task_t* task_new(gdouble scenario, guint in_size, guint out_size) { +task_t* task_new(guint scenario) { task_t *task = g_slice_new(task_t); task->scenario = scenario; task->timestamp = 0; - task->in_size = in_size; - task->out_size = out_size; + task->in_size = ovm_ins; + task->out_size = ovm_outs; task->in = g_slice_alloc0(task->in_size * sizeof(gdouble)); + task->in_old = g_slice_alloc0(task->in_size * sizeof(gdouble)); task->out = g_slice_alloc0(task->out_size * sizeof(gdouble)); return task; } + +void task_trace_start(task_t *task, const gchar *tracefile) { + guint32 buf[3]; + task->tracefd = g_open(tracefile, O_CREAT | O_TRUNC | O_WRONLY, 0644); + + if (-1 == task->tracefd) { + fprintf(stderr, "Couldn't open file %s: %s\n", tracefile, g_strerror(errno)); + exit(2); + } + + buf[0] = 0xCAFEBABE; + buf[1] = 439; + buf[2] = (guint32) task->scenario; + write(task->tracefd, buf, 12); +} + +void task_trace_end(task_t *task) { + guint32 buf[2]; + buf[0] = task->timestamp; + buf[1] = 0; + write(task->tracefd, buf, 8); +} + +void task_trace_step(task_t *task) { + gboolean ch2 = task->in_old[2] != task->in[2], ch3 = task->in_old[3] != task->in[3]; + if ((0 == task->timestamp) || ch2 || ch3) { + guint32 buf[2+3*3], *cur = buf; + buf[0] = task->timestamp; + buf[1] = 0; + cur = &buf[2]; + + if (ch2) { + buf[1]++; + *cur++ = 2; + memcpy(cur, &task->in[2], sizeof(gdouble)); + task->in_old[2] = task->in[2]; + cur += 2; + } + if (ch3) { + buf[1]++; + *cur++ = 3; + memcpy(cur, &task->in[3], sizeof(gdouble)); + task->in_old[3] = task->in[3]; + cur += 2; + } + if (0 == task->timestamp) { + gdouble s = task->scenario; + buf[1]++; + *cur++ = 0x3e80; + memcpy(cur, &s, sizeof(gdouble)); + cur += 2; + } + write(task->tracefd, buf, (cur-buf)*4); + } +} diff --git a/ovm/task.h b/ovm/task.h index 5fb37f0..a220e3f 100644 --- a/ovm/task.h +++ b/ovm/task.h @@ -4,27 +4,22 @@ #include "base.h" typedef struct { - gdouble scenario; + guint scenario; guint64 timestamp; guint in_size, out_size; - gdouble *in, *out; + gdouble *in, *out, *in_old; + int tracefd; } task_t; -typedef void (*task_app_t)(task_t *task); - -task_t* task_new(gdouble scenario, guint in_size, guint out_size); +task_t* task_new(guint scenario); void task_free(task_t *task); -void ovm_init(); -void ovm_step(gdouble scenario, gdouble *in, gdouble *out); +void task_trace_start(task_t *task, const gchar *tracefile); +void task_trace_end(task_t *task); +void task_trace_step(task_t *task); -static inline gdouble task_run(task_t *task, task_app_t app) { - ovm_init(); - for ( ; task->out[0] == 0.0 && task->timestamp < 3000000; task->timestamp++) { - app(task); - ovm_step(task->scenario, task->in, task->out); - } - return task->out[0]; -} +void ovm_init(); +void ovm_step(guint scenario, gdouble *in, gdouble *out); +extern const guint ovm_outs, ovm_ins; #endif \ No newline at end of file diff --git a/ovm/task1.c b/ovm/task1.c index 8f9dec2..47fced1 100644 --- a/ovm/task1.c +++ b/ovm/task1.c @@ -1,26 +1,81 @@ -#include "task.h" +#include "task_main.h" +#include "physics.h" + +/* +Output Ports: +Address Sensor +0x0 Score +0x1 Fuel Remaining +0x2 s_x Relative to Earth +0x3 s_y Relative to Earth +0x4 Target Orbit Radius +*/ + +#define SCORE (task->out[0]) +#define FUEL (task->out[1]) +#define S_X (task->out[2]) +#define S_Y (task->out[3]) +#define RADIUS (task->out[4]) + +#define DV_X (task->in[2]) +#define DV_Y (task->in[3]) + +static const gdouble mu = G * Me; static void debug(task_t * task) { - gdouble *o = task->out; + gdouble rad = sqrt(S_X*S_X+S_Y*S_Y); printf( - "Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f\n", - task->timestamp, o[0], o[1], o[2], o[3], o[4]); + "Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f (cur: %5f)\n", + task->timestamp, SCORE, FUEL, S_X, S_Y, RADIUS, rad); } -static void run(task_t *task) { +gdouble init_rad, last_x, last_y; +gboolean running = FALSE, started = FALSE; +gdouble dv, dv_tic; + +static void run(task_t *task, gpointer userdata) { + gdouble cur_rad; + UNUSED(userdata); + + if (0 == task->timestamp) return; + + cur_rad = sqrt(S_X*S_X+S_Y*S_Y); + DV_X = DV_Y = 0.0; + + if (!running) { + running = TRUE; + started = TRUE; + init_rad = cur_rad; + dv = sqrt(mu/init_rad)*(sqrt(2*RADIUS/(init_rad + RADIUS))-1); + dv_tic = sqrt(mu/RADIUS)*(1-sqrt(2*init_rad/(init_rad + RADIUS))); + printf("Orbit: %f -> %f; dv = %f, dv' = %f\n", init_rad, RADIUS, dv, dv_tic); + } else if (started) { + gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy); + started = FALSE; + DV_X = -vx * (dv / v); + DV_Y = -vy * (dv / v); +// printf("v: %f / %f\n", vx, vy); + printf("Dv: %f / %f\n", DV_X, DV_Y); + } else if (fabs(cur_rad - RADIUS) < 1000.0) { + gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy); + running = FALSE; + printf("Reached target radius\n"); + DV_X = -vx * (dv_tic / v); + DV_Y = -vy * (dv_tic / v); + printf("Dv: %f / %f\n", DV_X, DV_Y); + } + + last_x = S_X; + last_y = S_Y; +} + +static void run_debug(task_t *task, gpointer userdata) { debug(task); + run(task, userdata); } int main(int argc, char **argv) { - task_t *task; - gdouble score; - - UNUSED(argc); - UNUSED(argv); - - task = task_new(1002.0, 4, 5); - score = task_run(task, run); - printf("Final Score: %f\n", score); + task_main(argc, argv, run, run_debug, NULL, 1001); return 0; -} \ No newline at end of file +} diff --git a/ovm/task_main.h b/ovm/task_main.h new file mode 100644 index 0000000..b960ca9 --- /dev/null +++ b/ovm/task_main.h @@ -0,0 +1,92 @@ +#ifndef OVM_TASK_MAIN_H +#define OVM_TASK_MAIN_H + +#include "task.h" +#include "trace.h" + +typedef void (*task_app_t)(task_t *task, gpointer userdata); + +static inline void trace_simulate(task_t *task, gpointer userdata) { + trace_t *trace = (trace_t*) userdata; + trace_entry_t *te; + + if (trace->pos > trace->data->len) { + fprintf(stderr, "Unexpected end of solution\n"); + exit(11); + } + + te = g_ptr_array_index(trace->data, trace->pos); + if (te->timestamp == task->timestamp) { + guint32 i; + trace->pos++; + for (i = 0; i < te->count; i++) { + task->in[te->data[i].addr] = te->data[i].value; + } + } +} + +static inline gdouble task_run(task_t *task, task_app_t app, gpointer userdata, const gchar *tracefile) { + gboolean dotrace = (NULL != tracefile); + ovm_init(); + if (dotrace) { + task_trace_start(task, tracefile); + } + for ( ; task->out[0] == 0.0 && task->timestamp < 3000000; task->timestamp++) { + app(task, userdata); + if (dotrace) task_trace_step(task); + ovm_step(task->scenario, task->in, task->out); + } + if (dotrace) task_trace_end(task); + return task->out[0]; +} + +static inline void task_main(int argc, char **argv, task_app_t app, task_app_t debug_app, gpointer userdata, guint default_scenario) { + GError *error = NULL; + GOptionContext *context; + gboolean res; + gdouble score; + task_t *task; + + guint scenario = default_scenario; + const gchar *tracefile = NULL; + const gchar *simulate_file = NULL; + gboolean debug = FALSE; + + GOptionEntry entries[] = { + { "scenario", 's', 0, G_OPTION_ARG_INT, &scenario, "run scenario", "number" }, + { "simulate", 'm', 0, G_OPTION_ARG_FILENAME, &simulate_file, "Save trace in file", "PATH" }, + { "trace", 't', 0, G_OPTION_ARG_FILENAME, &tracefile, "Run input data (trace from another run)", "PATH" }, + { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Show debug", NULL }, + { NULL, 0, 0, 0, NULL, NULL, NULL } + }; + + context = g_option_context_new("- ovm task runner"); + g_option_context_add_main_entries(context, entries, NULL); + + res = g_option_context_parse(context, &argc, &argv, &error); + + g_option_context_free(context); + + if (!res) { + g_printerr("failed to parse command line arguments: %s\n", error->message); + g_error_free(error); + exit(1); + } + + if (simulate_file) { + trace_t *trace = trace_load(simulate_file); + userdata = trace; + app = trace_simulate; + scenario = trace->scenario; + fprintf(stderr, "Simulating solution: Team #%u, Scenario %u\n\n", (guint) trace->team, (guint) trace->scenario); + } else if (debug) { + app = debug_app; + } + + task = task_new(scenario); + score = task_run(task, app, userdata, tracefile); + fprintf(stderr, "Finale score: %f\n", score); + task_free(task); +} + +#endif \ No newline at end of file diff --git a/ovm/trace.c b/ovm/trace.c new file mode 100644 index 0000000..e2fe3cf --- /dev/null +++ b/ovm/trace.c @@ -0,0 +1,82 @@ + +#include "trace.h" + +static void trace_entry_free(trace_entry_t *te) { + g_slice_free1(te->count*12 + 8, te); +} + +static void _trace_entry_free(gpointer p, gpointer x) { + UNUSED(x); + trace_entry_free(p); +} + + +static trace_entry_t *trace_entry_new(guint32 timestamp, guint32 count) { + trace_entry_t *te = g_slice_alloc(count*12 + 8); + te->timestamp = timestamp; + te->count = count; + return te; +} + +trace_t *trace_load(const gchar *filename) { + GError *err = NULL; + guint32 *buf = NULL; + gsize len = 0, i; + trace_t *trace = g_slice_new0(trace_t); + trace->data = g_ptr_array_new(); + + if (!g_file_get_contents(filename, (gchar**) &buf, &len, &err)) { + fprintf (stderr, "Unable to read file %s: %s\n", filename, err->message); + g_error_free (err); + exit(1); + } + + if (len % 4 > 0) { + fprintf (stderr, "Solution: length not aligned\n"); + exit(10); + } + + len /= 4; + + if (len < 10) { + fprintf (stderr, "Solution too short\n"); + exit(10); + } + + if (buf[0] != 0xCAFEBABE) { + fprintf (stderr, "Wrong magic in solution: 0x%X\n", (guint) buf[0]); + exit(10); + } + + trace->magic = buf[0]; + trace->team = buf[1]; + trace->scenario = buf[2]; + + for (i = 3; i < len; ) { + guint32 timestamp, count; + trace_entry_t *te; + if (i+1 >= len) { + fprintf(stderr, "Solution: unexpected end of file (%i+1 >= %i)\n", (guint) i, (guint) len); + exit(10); + } + timestamp = buf[i++]; + count = buf[i++]; + if (i+count*3 > len) { + fprintf(stderr, "Solution: unexpected end of file (%i+%i*3 >= %i\n", (guint) i, (guint) count, (guint) len); + exit(10); + } + te = trace_entry_new(timestamp, count); + if (count > 0) memcpy(te->data, &buf[i], count * 12); + i += 3*count; + g_ptr_array_add(trace->data, te); + if (count == 0 && i < len) { + fprintf (stderr, "Solution: expected end of file (count = 0)\n"); + } + } + + return trace; +} + +void trace_free(trace_t *trace) { + g_ptr_array_foreach(trace->data, _trace_entry_free, NULL); +} diff --git a/ovm/trace.h b/ovm/trace.h new file mode 100644 index 0000000..1b3fdcc --- /dev/null +++ b/ovm/trace.h @@ -0,0 +1,24 @@ +#ifndef OVM_TRACE_H +#define OVM_TRACE_H + +#include "base.h" + +typedef struct { + guint32 timestamp; + guint32 count; + struct { + guint32 addr; + gdouble value; + } data[]; +} trace_entry_t; + +typedef struct { + guint32 magic, team, scenario; + GPtrArray *data; + gsize pos; +} trace_t; + +trace_t *trace_load(const gchar *filename); +void trace_free(trace_t *trace); + +#endif