From: ametama Date: Mon, 2 Feb 2026 20:44:25 +0000 (+0100) Subject: task: readstream append 0-byte, score passing fixed X-Git-Url: https://git.wafflesoft.org/?a=commitdiff_plain;h=35c5853eb22589d31458231897647278d54c2897;p=ngsolve.git task: readstream append 0-byte, score passing fixed --- diff --git a/Makefile b/Makefile index 719aad9..3cce430 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ compile_flags: echo "-Iinclude -lcgo -lm -fopenmp" | perl -pe 's|(-.*?)\s|\1\n|g' > compile_flags.txt executable: $(wildcard src/*.c) - gcc $(shell cat compile_flags.txt) -o ngsolve $(shell ls src/*.c) + gcc $(shell ls src/*.c) $(shell cat compile_flags.txt) -o ngsolve clear: rm -f compile_flags.txt diff --git a/include/def.h b/include/def.h index 7cd100c..4395857 100644 --- a/include/def.h +++ b/include/def.h @@ -14,7 +14,5 @@ typedef struct { char *netlist; int agentc; int dvarc; - int mvarc; design_var *dvars; - measure_var *mvars; } task_def; diff --git a/src/main.c b/src/main.c index 528b74f..42ab57d 100644 --- a/src/main.c +++ b/src/main.c @@ -2,25 +2,26 @@ #include #include #include +#include #include #include "argph.h" #include "def.h" typedef struct { pid_t pid; - int input_read; - int input_write; - int output_read; - int output_write; + int input[2]; + int output[2]; } ngspice_process; task_def taskg; +// ngspice .func replacements have some undesirable +// behaviours, gcc macros used instead. char *macros = \ "#define Minimize(expr) let __ngsolve_f=__ngsolve_f+expr\n" - "#define Maximize(expr) Minimize(-expr)\n" + "#define Maximize(expr) let __ngsolve_f=__ngsolve_f-(expr)\n" "#define Constrain(expr) let __ngsolve_c=__ngsolve_c+expr\n" - "#define Lt(a, b) max(exp(a - b) - 1, 0)\n" + "#define Lt(a, b) Constrain(max(0, exp(a - b) - 1))\n" "#define Gt(a, b) Lt(b, a)\n" "#define Band(v, lo, hi) Lt(lo, v) + Lt(v, hi)\n"; @@ -38,18 +39,23 @@ char *readfile(FILE *f) { char *readstream(int fd) { int s = 128; + int r; char *buf = malloc(s * 2); - if (read(fd, buf, s) != s) return buf; + if ((r = read(fd, buf, s)) != s) { + *(buf + r) = 0; + return buf; + }; char *pos = buf + s; - while (read(fd, pos, s) == s) { + while ((r = read(fd, pos, s)) == s) { buf = realloc(buf, (s *= 2) * 2); pos = buf + s; } + *(pos + r) = 0; return buf; } void load_netlist(task_def *task) { - FILE *netlist = fopen(taskg.netlist_file, "r"); + FILE *netlist = fopen( task->netlist_file, "r"); char *netlist_raw = readfile(netlist); fclose(netlist); int in[2]; @@ -62,7 +68,7 @@ void load_netlist(task_def *task) { close(out[0]); dup2(in[0], STDIN_FILENO); dup2(out[1], STDOUT_FILENO); - if (execlp("gcc", "gcc", "-E", "-P", "-x", "c", "-", NULL)) { + if (execlp("gcc", "gcc", "-E", "-P", "-x", "c", "/dev/fd/0", NULL)) { printf("ngsolve: FATAL EXCEPTION\n gcc invocation unsuccessful. Check that a working binary is added to PATH as `gcc`."); exit(1); } @@ -77,41 +83,44 @@ void load_netlist(task_def *task) { } void spawn_ngspice(ngspice_process *chp) { - if (pipe(&chp->input_read) || pipe(&chp->output_read)) { + if (pipe(chp->input) || pipe(chp->output)) { printf("ngsolve: FATAL EXCEPTION\n pipe creation unsuccessful."); exit(1); } pid_t p = fork(); if (!p) { - close(chp->input_write); - close(chp->output_read); - // STDOUT is not linked to chp->output_write as this - // would pollute the pipe with ngspice logs. - dup2(chp->input_read, STDIN_FILENO); + int null_fd = open("/dev/null", O_WRONLY); + close(chp->input[1]); + close(chp->output[0]); + dup2(chp->input[0], STDIN_FILENO); + dup2(null_fd, STDOUT_FILENO); + dup2(null_fd, STDERR_FILENO); // Convert to an ngspice process; // execlp does not (!) return to caller if successful. - if (execlp("ngspice", "ngspice", "<&0", NULL)) { + if (execlp("ngspice", "ngspice", "-b", "/dev/fd/0", NULL)) { printf("ngsolve: FATAL EXCEPTION\n ngspice invocation unsuccessful. Check that a working binary is added to PATH as `ngspice`."); exit(1); } } - close(chp->input_read); - close(chp->output_write); + close(chp->input[0]); + close(chp->output[1]); chp->pid = p; } double fitness(double *x) { ngspice_process chp; spawn_ngspice(&chp); - dprintf(chp.input_write, "ngsolve\n"); + dprintf(chp.input[1], "ngsolve\n\n.CONTROL\nlet __ngsolve_f=0\nlet __ngsolve_c=0\n.ENDC\n"); for (size_t d = 0; d < taskg.dvarc; d++) - dprintf(chp.input_write, ".PARAM %s=%f\n", taskg.dvars[d].symbol, x[d]); + // .PARAM lines are used by circuit definition but cannot be used in + // .CONTROL blocks. .CSPARAM lines vice-versa (therefore both necessary). + dprintf(chp.input[1], ".PARAM %s=%f\n.CSPARAM %s=%s\n", taskg.dvars[d].symbol, x[d], taskg.dvars[d].symbol, taskg.dvars[d].symbol); // Note: ngspice manual specifies input files have to end on ".END\n". // This seems to not be enforced, so this control statement can be appended after it. - dprintf(chp.input_write, "*%s\n.CONTROL\necho \"$&__ngsolve_c $&__ngsolve_f\" >&%d\nexec %d>&-\n.ENDC\n", taskg.netlist, chp.output_write, chp.output_write); - close(chp.input_write); // Done writing (writes EOF to ngspice on chp.input_write). - char *outp = readstream(chp.output_read); - close(chp.output_read); + dprintf(chp.input[1], "*%s\n.CONTROL\necho \"$&__ngsolve_c $&__ngsolve_f\" >> /dev/fd/%d\n.ENDC\n.END\n", taskg.netlist, chp.output[1]); + close(chp.input[1]); // Done writing (writes EOF to ngspice on chp.input_write). + char *outp = readstream(chp.output[0]); + close(chp.output[0]); char *pos = outp; double constraints = strtod(pos, &pos); double fitness = strtod(pos, &pos); @@ -121,32 +130,49 @@ double fitness(double *x) { return constraints + fitness; } -void optimize() { - double *sample_range_min = malloc(sizeof(double) * taskg.dvarc); - double *sample_range_max = malloc(sizeof(double) * taskg.dvarc); - for (size_t d = 0; d < taskg.dvarc; d++) { - sample_range_min[d] = taskg.dvars[d].sample_min; - sample_range_max[d] = taskg.dvars[d].sample_max; +void optimize(task_def *task) { + double *sample_range_min = malloc(sizeof(double) * task->dvarc); + double *sample_range_max = malloc(sizeof(double) * task->dvarc); + for (size_t d = 0; d < task->dvarc; d++) { + sample_range_min[d] = task->dvars[d].sample_min; + sample_range_max[d] = task->dvars[d].sample_max; } - load_netlist(&taskg); cgo_de_parameters par = { - taskg.dvarc, - taskg.agentc, + task->dvarc, + task->agentc, sample_range_min, sample_range_max, fitness, 0.9, 0.8 }; - double *res = malloc(sizeof(double) * taskg.dvarc); + double *res = malloc(sizeof(double) * task->dvarc); cgo_de(&par, res); printf("ngsolve: converged at x=("); - for (size_t d = 0; d < taskg.dvarc - 1; d++) printf("%s=%f, ", taskg.dvars[d].symbol, res[d]); - printf("%s=%f) with f(x)=%f\n", taskg.dvars[taskg.dvarc - 1].symbol, res[taskg.dvarc - 1], fitness(res)); + for (size_t d = 0; d < task->dvarc - 1; d++) printf("%s=%f, ", task->dvars[d].symbol, res[d]); + printf("%s=%f) with f(x)=%f\n", task->dvars[task->dvarc - 1].symbol, res[task->dvarc - 1], fitness(res)); } int main(int argc, char *argv[]) { struct arguments args; argp_parse(&argp, argc, argv, 0, 0, &args); + design_var dvars[] = { + { + "a", + -10, + 10 + }, + { + "b", + -10, + 10 + } + }; + taskg.netlist_file = "test.ngs"; + taskg.agentc = 10; + taskg.dvarc = 2; + taskg.dvars = dvars; + load_netlist(&taskg); + optimize(&taskg); return 0; } diff --git a/test.ch b/test.ch deleted file mode 100644 index fb348f3..0000000 --- a/test.ch +++ /dev/null @@ -1,3 +0,0 @@ -#define A 123 - -A