added printing stats
This commit is contained in:
parent
3f161b9630
commit
14be1007c5
2 changed files with 111 additions and 71 deletions
180
main.c
180
main.c
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -46,6 +47,8 @@ bool verbose = false;
|
|||
|
||||
bool print_with_color = false;
|
||||
|
||||
bool print_stats = false;
|
||||
|
||||
bool force_rebuild = false;
|
||||
|
||||
bool quiet = false;
|
||||
|
|
@ -56,7 +59,7 @@ static void parse_args(int argc, char* const* argv)
|
|||
|
||||
print_with_color = isatty(1);
|
||||
|
||||
for (int opt; (opt = getopt(argc, argv, "pyqvc:eEo:C:B")) != -1; ) switch (opt)
|
||||
for (int opt; (opt = getopt(argc, argv, "pyqmvc:eEo:C:B")) != -1; ) switch (opt)
|
||||
{
|
||||
case 'p':
|
||||
print_all_and_quit = true;
|
||||
|
|
@ -70,6 +73,10 @@ static void parse_args(int argc, char* const* argv)
|
|||
quiet = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
print_stats = true;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
|
@ -158,14 +165,14 @@ static void parse_args(int argc, char* const* argv)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'B':
|
||||
{
|
||||
force_rebuild = true;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
assert(!"TODO");
|
||||
break;
|
||||
|
|
@ -189,7 +196,7 @@ static void parse_args(int argc, char* const* argv)
|
|||
|
||||
enum kind {
|
||||
ek_unreachable,
|
||||
|
||||
|
||||
ek_0,
|
||||
ek_1,
|
||||
ek_W,
|
||||
|
|
@ -222,7 +229,7 @@ struct expr {
|
|||
enum kind kind;
|
||||
|
||||
uint16_t cond, left, right;
|
||||
|
||||
|
||||
int cost;
|
||||
} lookup[N];
|
||||
|
||||
|
|
@ -254,7 +261,7 @@ static void print(uint16_t truthtable, int depth)
|
|||
assert(!"NOPE");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ek_0:
|
||||
{
|
||||
printf(print_with_color ? LITERAL_ESCAPE "0" RESET_ESCAPE : "0");
|
||||
|
|
@ -377,30 +384,30 @@ void calculate_simplifications(void)
|
|||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
lookup[i].kind = ek_unreachable;
|
||||
|
||||
|
||||
lookup[i].cost = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// heap of truthtables; key = cost
|
||||
struct {
|
||||
uint16_t data[N];
|
||||
int n;
|
||||
|
||||
|
||||
// truthtable -> index in 'todo'
|
||||
int reverse[N];
|
||||
} todo;
|
||||
|
||||
|
||||
// init 'todo':
|
||||
{
|
||||
todo.n = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
todo.reverse[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t pop(void)
|
||||
{
|
||||
assert(todo.n > 0);
|
||||
|
|
@ -465,11 +472,11 @@ void calculate_simplifications(void)
|
|||
|
||||
index = new_index;
|
||||
}
|
||||
|
||||
|
||||
todo.data[index] = truthtable;
|
||||
|
||||
|
||||
todo.reverse[truthtable] = index;
|
||||
|
||||
|
||||
lookup[truthtable].cost = cost;
|
||||
}
|
||||
|
||||
|
|
@ -495,60 +502,60 @@ void calculate_simplifications(void)
|
|||
|
||||
lookup[truthtable].cost = cost;
|
||||
}
|
||||
|
||||
|
||||
// create a list of the "done" truthtables
|
||||
struct {
|
||||
int headtails[N], next[N], head;
|
||||
|
||||
|
||||
// for debugging:
|
||||
#if ZDEBUG
|
||||
bool in[N];
|
||||
#endif
|
||||
} done = {};
|
||||
|
||||
|
||||
// init 'done':
|
||||
{
|
||||
done.head = -1;
|
||||
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
done.headtails[i] = -1;
|
||||
|
||||
|
||||
#if ZDEBUG
|
||||
done.in[i] = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void insert(int index)
|
||||
{
|
||||
#if ZDEBUG
|
||||
assert(!done.in[index]);
|
||||
#endif
|
||||
|
||||
|
||||
int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1;
|
||||
|
||||
|
||||
while (done.headtails[head] == -1 || index < done.headtails[head])
|
||||
{
|
||||
done.headtails[head] = index;
|
||||
|
||||
|
||||
prevhead = head, head = head & ~(head & -head);
|
||||
}
|
||||
|
||||
|
||||
if (done.headtails[head] < index)
|
||||
{
|
||||
if (prevhead == -1)
|
||||
{
|
||||
assert(done.headtails[head] == head);
|
||||
|
||||
|
||||
done.next[head] = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
int tophalftail = done.headtails[prevhead - 1];
|
||||
|
||||
|
||||
assert(tophalftail != -1);
|
||||
|
||||
|
||||
done.next[tophalftail] = index;
|
||||
}
|
||||
}
|
||||
|
|
@ -556,35 +563,35 @@ void calculate_simplifications(void)
|
|||
{
|
||||
done.head = index;
|
||||
}
|
||||
|
||||
|
||||
int n = ~index & M;
|
||||
int tail = index & 1 ? index : index | (n & -n), prevtail = -1;
|
||||
|
||||
|
||||
while (done.headtails[tail] == -1 || done.headtails[tail] < index)
|
||||
{
|
||||
done.headtails[tail] = index;
|
||||
|
||||
|
||||
prevtail = tail, tail = tail | (n = ~tail & M, n & -n);
|
||||
}
|
||||
|
||||
|
||||
if (index < done.headtails[tail])
|
||||
{
|
||||
if (prevtail == -1)
|
||||
{
|
||||
assert(done.headtails[tail] == tail);
|
||||
|
||||
|
||||
#if ZDEBUG
|
||||
assert(done.in[tail]);
|
||||
#endif
|
||||
|
||||
|
||||
done.next[index] = tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bottomhalfhead = done.headtails[prevtail + 1];
|
||||
|
||||
|
||||
assert(bottomhalfhead != -1);
|
||||
|
||||
|
||||
done.next[index] = bottomhalfhead;
|
||||
}
|
||||
}
|
||||
|
|
@ -592,26 +599,26 @@ void calculate_simplifications(void)
|
|||
{
|
||||
done.next[index] = -1;
|
||||
}
|
||||
|
||||
|
||||
#if ZDEBUG
|
||||
done.in[index] = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
append(W, 0), lookup[W].kind = ek_W;
|
||||
append(X, 0), lookup[X].kind = ek_X;
|
||||
append(Y, 0), lookup[Y].kind = ek_Y;
|
||||
append(Z, 0), lookup[Z].kind = ek_Z;
|
||||
|
||||
|
||||
append(0, 1), lookup[0].kind = ek_0;
|
||||
append(M, 1), lookup[M].kind = ek_1;
|
||||
|
||||
|
||||
for (int iterations = 1; todo.n && iterations <= N; iterations++)
|
||||
{
|
||||
uint16_t truthtable = pop();
|
||||
|
||||
|
||||
insert(truthtable);
|
||||
|
||||
|
||||
int cost = lookup[truthtable].cost;
|
||||
|
||||
if (verbose)
|
||||
|
|
@ -893,9 +900,9 @@ void get_simplifications(void)
|
|||
"This may take a while." "\n"
|
||||
"");
|
||||
}
|
||||
|
||||
|
||||
rebuild: {};
|
||||
|
||||
|
||||
if (!quiet && !verbose)
|
||||
{
|
||||
puts("re-run with '-v' to watch progress");
|
||||
|
|
@ -1439,6 +1446,61 @@ int main(int argc, char* const* argv)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (print_stats)
|
||||
{
|
||||
printf("statistics:" "\n");
|
||||
|
||||
uintmax_t total_cost = 0;
|
||||
int n = 0;
|
||||
int max_cost = 0;
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
int cost = lookup[i].cost;
|
||||
|
||||
if (cost != INT_MAX)
|
||||
{
|
||||
if (max_cost < cost)
|
||||
{
|
||||
max_cost = cost;
|
||||
}
|
||||
|
||||
total_cost += cost;
|
||||
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (n)
|
||||
{
|
||||
printf("minimum operators needed: 1" "\n");
|
||||
printf("maximum operators needed: %i" "\n", max_cost);
|
||||
|
||||
double average = (double) total_cost / n;
|
||||
|
||||
printf("average operators needed: %g" "\n", average);
|
||||
|
||||
double working = 0.0;
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
int cost = lookup[i].cost;
|
||||
|
||||
if (cost != INT_MAX)
|
||||
{
|
||||
working += pow(cost - average, 2);
|
||||
}
|
||||
}
|
||||
|
||||
double stddev = sqrt(working / (n - 1));
|
||||
|
||||
printf("standard deviation: %g" "\n", stddev);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("everything unreachable: no statistics to give");
|
||||
}
|
||||
}
|
||||
else if (command)
|
||||
{
|
||||
uint16_t truthtable = evaluate(command);
|
||||
|
|
@ -1456,28 +1518,6 @@ int main(int argc, char* const* argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Let's humble-brag just a little.
|
||||
#if 0
|
||||
{
|
||||
int max_cost = 0;
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
int cost = lookup[i].cost;
|
||||
|
||||
if (cost != INT_MAX && max_cost < cost)
|
||||
{
|
||||
max_cost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
puts("");
|
||||
printf("I can simplify any tree down to %i operators or less.\n",
|
||||
max_cost);
|
||||
puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!quiet)
|
||||
{
|
||||
puts("Use C-style syntax for boolean operators and expressions.");
|
||||
|
|
@ -1486,13 +1526,13 @@ int main(int argc, char* const* argv)
|
|||
puts("Comparison operators are also suppported.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (char* line; (line = readline(">>> ")); free(line))
|
||||
{
|
||||
if (!*line) continue;
|
||||
|
||||
|
||||
add_history(line);
|
||||
|
||||
|
||||
uint16_t truthtable = evaluate(line);
|
||||
|
||||
// printf("truthtable = 0b%016b\n", truthtable);
|
||||
|
|
|
|||
2
makefile
2
makefile
|
|
@ -16,7 +16,7 @@ cflags += -O3
|
|||
|
||||
cflags += -Wno-unused
|
||||
|
||||
ldflags += -lreadline
|
||||
ldflags += -lreadline -lm
|
||||
|
||||
/tmp/4-variable-simplifier: main.c
|
||||
$(cc) $(cppflags) $(cflags) $< -o $@ $(ldflags)
|
||||
|
|
|
|||
Loading…
Reference in a new issue