Machine is working, working on task1

This commit is contained in:
Stefan Bühler 2009-06-27 02:21:49 +02:00
parent b51da57b7b
commit db63517f57
10 changed files with 398 additions and 43 deletions

View File

@ -37,8 +37,8 @@ ADD_EXECUTABLE(ovmjit
ADD_EXECUTABLE(task1 ADD_EXECUTABLE(task1
bin1.c bin1.c
task.c
task1.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") SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed")

View File

@ -2,6 +2,8 @@
#include "ovm.h" #include "ovm.h"
#include <glib/gstdio.h> #include <glib/gstdio.h>
#undef CMPEPS
void ovm_free(ovm_t *ovm) { void ovm_free(ovm_t *ovm) {
if (!ovm) return; if (!ovm) return;
g_slice_free1(ovm->limit * sizeof(instruction_t), ovm->instructions); 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)); ovm->values = g_slice_alloc0(ovm->limit * sizeof(gdouble));
if (!g_file_get_contents(filename, &buf, &len, &err)) { 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); g_error_free (err);
exit(1); exit(1);
} }
@ -50,7 +52,7 @@ ovm_t* ovm_load(const gchar *filename) {
} }
void ovm_print_c(ovm_t *ovm, 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; instruction_t *oi = ovm->instructions;
gdouble *vi = ovm->values; gdouble *vi = ovm->values;
guint64 *uvi = (guint64*) 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( 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(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++) { for (i = 0; i < ovm->used; i++) {
g_string_printf(str, "\t/* Invalid command: 0x%X */\n", (guint) oi[i]); g_string_printf(str, "\t/* Invalid command: 0x%X */\n", (guint) oi[i]);
switch (instr_dop(oi[i])) { switch (instr_dop(oi[i])) {
@ -78,6 +82,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
break; break;
case SOP_CMPZ: case SOP_CMPZ:
switch (instr_sop_cmp(oi[i])) { switch (instr_sop_cmp(oi[i])) {
#if CMPEPS /* cmp with eps */
case CMP_LTZ: case CMP_LTZ:
g_string_printf(str, "\tovm_status = (v%u.d < -eps);\n", USED(instr_sop_r1(oi[i]))); g_string_printf(str, "\tovm_status = (v%u.d < -eps);\n", USED(instr_sop_r1(oi[i])));
break; 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]))); g_string_printf(str, "\tovm_status = (fabs(v%u.d) <= eps);\n", USED(instr_sop_r1(oi[i])));
break; break;
case CMP_GEZ: 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]))); g_string_printf(str, "\tovm_status = (v%u.d >= -eps);\n", USED(instr_sop_r1(oi[i])));
break; 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; break;
case SOP_SQRT: case SOP_SQRT:
@ -105,7 +127,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
if (0x3e80 == instr_sop_r1(oi[i])) { if (0x3e80 == instr_sop_r1(oi[i])) {
g_string_printf(str, "\tv%u.d = scenario;\n", USED(i)); g_string_printf(str, "\tv%u.d = scenario;\n", USED(i));
} else { } 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; 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]))); 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; break;
case OP_DIV: 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])); 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; break;
case OP_OUT: 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; break;
case OP_PHI: 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]))); 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" "typedef union { gdouble d; guint64 i; } double_int;\n"
"\n" "\n"
"static gboolean ovm_status;\n" "static gboolean ovm_status;\n"
"\n"
));
#if CMPEPS
write(f, CONST_STR_LEN(
"static const gdouble eps = 1e-300;\n" "static const gdouble eps = 1e-300;\n"
"\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" "static double_int v0"
)); ));
for (i = 1; i < ovm->used; i++) { for (i = 1; i < ovm->used; i++) {

View File

@ -45,7 +45,7 @@ static inline guint instr_dop_r2(instruction_t i) {
} }
static inline cmp_t instr_sop_cmp(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) { static inline guint instr_sop_r1(instruction_t i) {

13
ovm/physics.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef OVM_PHYSICS_H
#define OVM_PHYSICS_H
#include "base.h"
#include <math.h>
#define G 6.67428e-11
#define Me 6.0e24
#define Re 6.357e6
#endif

View File

@ -1,20 +1,78 @@
#include "task.h" #include "task.h"
#include <glib/gstdio.h>
void task_free(task_t *task) { void task_free(task_t *task) {
if (!task) return; 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->in_size * sizeof(gdouble), task->in);
g_slice_free1(task->out_size * sizeof(gdouble), task->out); g_slice_free1(task->out_size * sizeof(gdouble), task->out);
g_slice_free(task_t, task); 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_t *task = g_slice_new(task_t);
task->scenario = scenario; task->scenario = scenario;
task->timestamp = 0; task->timestamp = 0;
task->in_size = in_size; task->in_size = ovm_ins;
task->out_size = out_size; task->out_size = ovm_outs;
task->in = g_slice_alloc0(task->in_size * sizeof(gdouble)); 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)); task->out = g_slice_alloc0(task->out_size * sizeof(gdouble));
return task; 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);
}
}

View File

@ -4,27 +4,22 @@
#include "base.h" #include "base.h"
typedef struct { typedef struct {
gdouble scenario; guint scenario;
guint64 timestamp; guint64 timestamp;
guint in_size, out_size; guint in_size, out_size;
gdouble *in, *out; gdouble *in, *out, *in_old;
int tracefd;
} task_t; } task_t;
typedef void (*task_app_t)(task_t *task); task_t* task_new(guint scenario);
task_t* task_new(gdouble scenario, guint in_size, guint out_size);
void task_free(task_t *task); void task_free(task_t *task);
void ovm_init(); void task_trace_start(task_t *task, const gchar *tracefile);
void ovm_step(gdouble scenario, gdouble *in, gdouble *out); 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) { void ovm_init();
ovm_init(); void ovm_step(guint scenario, gdouble *in, gdouble *out);
for ( ; task->out[0] == 0.0 && task->timestamp < 3000000; task->timestamp++) { extern const guint ovm_outs, ovm_ins;
app(task);
ovm_step(task->scenario, task->in, task->out);
}
return task->out[0];
}
#endif #endif

View File

@ -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) { static void debug(task_t * task) {
gdouble *o = task->out; gdouble rad = sqrt(S_X*S_X+S_Y*S_Y);
printf( printf(
"Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f\n", "Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f (cur: %5f)\n",
task->timestamp, o[0], o[1], o[2], o[3], o[4]); 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); debug(task);
run(task, userdata);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
task_t *task; task_main(argc, argv, run, run_debug, NULL, 1001);
gdouble score;
UNUSED(argc);
UNUSED(argv);
task = task_new(1002.0, 4, 5);
score = task_run(task, run);
printf("Final Score: %f\n", score);
return 0; return 0;
} }

92
ovm/task_main.h Normal file
View File

@ -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

82
ovm/trace.c Normal file
View File

@ -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);
}

24
ovm/trace.h Normal file
View File

@ -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