sat-solver/main.c
2025-03-07 09:45:39 -06:00

1642 lines
31 KiB
C

#if 0
#define _GNU_SOURCE
#include <stdarg.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
#include <avl.h>
#define argv0 \
program_invocation_name
#define TODO \
assert(!"TODO");
#define CHECK \
assert(!"CHECK");
#ifdef DEBUG
unsigned debug_depth = 0;
#define ENTER \
printf("%*s" "<%s>\n", debug_depth++, "", __PRETTY_FUNCTION__);
#define EXIT \
printf("%*s" "</%s>\n", --debug_depth, "", __PRETTY_FUNCTION__);
#define dpvs(x) \
printf("%*s" "%s = \"%s\"\n", debug_depth, "", #x, x);
#define dpvu(x) \
printf("%*s" "%s = %u\n", debug_depth, "", #x, x);
#define dpvlu(x) \
printf("%*s" "%s = %lu\n", debug_depth, "", #x, x);
#define dpvi(x) \
printf("%*s" "%s = %i\n", debug_depth, "", #x, x);
#define dpvb(x) \
printf("%*s" "%s = %s\n", debug_depth, "", #x, (x) ? "true" : "false");
#define ddprintf(fmt, ...) \
printf("%*s" fmt, debug_depth, "", ## __VA_ARGS__);
#else
#define ENTER ;
#define EXIT ;
#define dpvs(x) ;
#define dpvu(x) ;
#define dpvlu(x) ;
#define dpvi(x) ;
#define dpvb(x) ;
#define ddprintf(fmt, ...) ;
#endif
void* smalloc(size_t size)
{
void* ptr = malloc(size);
if (!ptr)
{
TODO;
}
return ptr;
}
void* srealloc(void* oldptr, size_t newsize)
{
void* newptr = realloc(oldptr, newsize);
if (!newptr)
{
TODO;
}
return newptr;
}
struct cmdln_flags
{
const char* input_file;
bool dump_automata, verbose;
};
struct cmdln_flags* parse_args(
int argc, char* const* argv)
{
ENTER;
const char* input_file = NULL;
bool dump_automata = false;
bool verbose = false;
int i = 1;
while (i < argc)
{
const char* arg = argv[i];
dpvs(arg);
if (arg[0] == '-')
{
if (!strcmp(arg, "-d"))
{
dump_automata = true, i++;
}
else if (!strcmp(arg, "-v"))
{
verbose = true, i++;
}
else
{
TODO;
}
}
else if (input_file)
{
TODO;
}
else
{
input_file = arg, i++;
}
}
if (!input_file)
{
printf("%s: missing input file!\n", argv0);
exit(1);
}
struct cmdln_flags* flags = smalloc(sizeof(*flags));
flags->input_file = input_file;
flags->dump_automata = dump_automata;
flags->verbose = verbose;
EXIT;
return flags;
}
void free_cmdln_flags(
struct cmdln_flags* this)
{
TODO;
}
struct quack
{
void** data;
size_t i, n, cap;
};
struct quack* new_quack(void)
{
ENTER;
struct quack* this = smalloc(sizeof(*this));
this->data = NULL;
this->i = 0;
this->n = 0;
this->cap = 0;
EXIT;
return this;
}
void quack_append(
struct quack* this,
void* element)
{
ENTER;
dpvlu(this->i);
dpvlu(this->n);
dpvlu(this->cap);
if (this->n == this->cap)
{
size_t oldcap = this->cap;
size_t newcap = oldcap << 1 ?: 1;
this->data = srealloc(this->data, sizeof(*this->data) * newcap);
if (this->i)
{
TODO;
}
this->cap = newcap;
dpvlu(this->cap);
}
size_t index = ((this->i + this->n++) % this->cap);
// ddprintf("wrote to index %lu\n", index);
this->data[index] = element;
dpvlu(this->i);
dpvlu(this->n);
dpvlu(this->cap);
EXIT;
}
void* quack_pop(
struct quack* this)
{
ENTER;
assert(this->n);
dpvlu(this->i);
dpvlu(this->n);
dpvlu(this->cap);
/* ddprintf("reading from index %lu\n", this->i);*/
void* retval = this->data[this->i];
this->i = (this->i + 1) % this->cap, this->n--;
dpvlu(this->i);
dpvlu(this->n);
dpvlu(this->cap);
EXIT;
return retval;
}
void free_quack(
struct quack* this)
{
ENTER;
free(this);
EXIT;
}
struct automata;
struct automataset
{
struct avl_tree_t* tree;
size_t refcount;
};
int ptrcmp(const void* a, const void* b)
{
if (a > b)
return +1;
if (a < b)
return -1;
return +0;
}
struct automataset* new_automataset(void)
{
ENTER;
struct automataset* this = smalloc(sizeof(*this));
this->tree = avl_alloc_tree(ptrcmp, NULL);
this->refcount = 1;
EXIT;
return this;
}
bool automataset_is_nonempty(
struct automataset* this)
{
return !!this->tree->head;
}
bool automataset_add(
struct automataset* this,
struct automata* automata)
{
bool retval;
ENTER;
errno = 0;
struct avl_node_t* node = avl_insert(this->tree, automata);
if (node)
{
retval = true;
}
else if (errno == EEXIST)
{
retval = false;
}
else
{
TODO;
}
EXIT;
return retval;
}
void automataset_foreach(
struct automataset* this,
void (*callback)(
struct automata*))
{
ENTER;
for (struct avl_node_t* node = this->tree->head; node; node = node->next)
{
callback(node->item);
}
EXIT;
}
struct automata* automataset_pop(
struct automataset* this)
{
ENTER;
assert(this->tree->head);
struct automata* retval = this->tree->head->item;
avl_delete_node(this->tree, this->tree->head);
EXIT;
return retval;
}
void free_automataset(
struct automataset* this)
{
ENTER;
if (!--this->refcount)
{
avl_free_tree(this->tree);
free(this);
}
EXIT;
}
struct automata
{
bool is_accepting;
struct automata *on[2];
};
struct automata* new_automata(void)
{
ENTER;
struct automata* this = malloc(sizeof(*this));
this->is_accepting = false;
this->on[0] = NULL;
this->on[1] = NULL;
EXIT;
return this;
}
void dump_automata(
struct automata* start,
const char* fmt, ...)
{
ENTER;
char path[PATH_MAX];
static size_t dump_id = 0;
snprintf(path, PATH_MAX, "/tmp/%05lu.dot", dump_id++);
FILE* stream = fopen(path, "w");
fprintf(stream, ""
"digraph {" "\n"
"\t" "rankdir = LR;" "\n"
"\t"
"\t" "node [" "\n"
"\t" "\t" "shape = circle" "\n"
"\t" "\t" "label = \"\"" "\n"
"\t" "];" "\n"
"\t" "\n"
"");
va_list va;
va_start(va, fmt);
vfprintf(stream, fmt, va);
va_end(va);
struct quack* todo = new_quack();
struct automataset* queued = new_automataset();
if (automataset_add(queued, start))
{
quack_append(todo, start);
}
while (todo->n)
{
struct automata* state = quack_pop(todo);
if (state->is_accepting)
{
fprintf(stream, "\"%p\" [ shape = doublecircle ];\n", state);
}
for (int on = 0; on < 2; on++)
{
struct automata* to = state->on[on];
if (to)
{
fprintf(stream, "\"%p\" -> \"%p\" [label = \"%i\"];\n", state, to, on);
if (automataset_add(queued, to))
{
quack_append(todo, to);
}
}
}
}
fprintf(stream, ""
"}" "\n"
"");
free_quack(todo);
free_automataset(queued);
fclose(stream);
EXIT;
}
struct automata* create_variable_automata(
int depth,
const struct cmdln_flags* flags,
unsigned variable_index,
bool value,
unsigned number_of_variables)
{
ENTER;
assert(variable_index < number_of_variables);
if (flags->verbose)
{
printf("%*s" "variable(index = %u, value = %s):\n",
depth++, "", variable_index, value ? "true" : "false");
}
size_t total_number_of_states = 0;
struct automata* start = new_automata();
struct automata* moving = start;
total_number_of_states++;
for (unsigned i = 0; i < number_of_variables; i++)
{
struct automata* new = new_automata();
total_number_of_states++;
if (i == variable_index)
{
moving->on[value] = new;
}
else
{
moving->on[0] = new;
moving->on[1] = new;
}
moving = new;
}
moving->is_accepting = true;
if (flags->verbose)
{
printf("%*s" "returned automata with %lu states.\n",
depth, "", total_number_of_states);
}
EXIT;
return start;
}
struct automata* automata_union(
int depth,
const struct cmdln_flags* flags,
const struct automata* left,
const struct automata* right)
{
ENTER;
if (flags->verbose)
{
printf("%*s" "union():\n", depth++, "");
}
struct bundle
{
const struct automata *left, *right; // key
struct automata* new;
};
struct bundle* new_bundle(
const struct automata *left,
const struct automata* right,
struct automata* new)
{
ENTER;
struct bundle* this = smalloc(sizeof(*this));
this->left = left;
this->right = right;
this->new = new;
EXIT;
return this;
}
int compare(const void* a, const void* b)
{
const struct bundle *A = a, *B = b;
return ptrcmp(A->left, B->left) ?: ptrcmp(A->right, B->right);
}
void append(struct bundle* bundle)
{
ENTER;
EXIT;
}
size_t total_number_of_states = 0;
struct avl_tree_t* mapping = avl_alloc_tree(compare, free);
struct automata* start = new_automata();
total_number_of_states++;
struct quack* todo = new_quack();
// initial state:
{
struct bundle* new = new_bundle(left, right, start);
quack_append(todo, new);
avl_insert(mapping, new);
}
while (todo->n)
{
struct bundle* bundle = quack_pop(todo);
const struct automata *const left = bundle->left;
const struct automata *const right = bundle->right;
struct automata* const new = bundle->new;
new->is_accepting = false
|| (left && left->is_accepting)
|| (right && right->is_accepting);
for (int value = 0; value < 2; value++)
{
struct automata* left_to = left ? left->on[value] : NULL;
struct automata* right_to = right ? right->on[value] : NULL;
if (left_to || right_to)
{
struct avl_node_t* node = avl_search(mapping,
&(struct bundle) {left_to, right_to, NULL});
if (node)
{
struct bundle* bundle_to = node->item;
new->on[value] = bundle_to->new;
}
else
{
struct automata* new_to = new_automata();
total_number_of_states++;
new->on[value] = new_to;
struct bundle* bundle_to = new_bundle(
left_to, right_to, new_to);
avl_insert(mapping, bundle_to);
quack_append(todo, bundle_to);
}
}
}
if (flags->dump_automata)
{
dump_automata(start, "label = \"automata_union\"");
}
}
if (flags->verbose)
{
printf("%*s" "returned automata with %lu states" "\n",
depth, "", total_number_of_states);
}
avl_free_tree(mapping);
free_quack(todo);
EXIT;
return start;
}
struct automata* automata_intersection(
const struct cmdln_flags* flags,
const struct automata* left,
const struct automata* right)
{
TODO;
}
struct automata* automata_simplify(
int depth,
const struct cmdln_flags* flags,
struct automata* original)
{
ENTER;
if (flags->verbose)
{
printf("%*s" "simplify():\n", depth++, "");
}
struct pair
{
struct automata *a, *b;
};
struct pair* new_pair(struct automata* a, struct automata* b)
{
ENTER;
struct pair* this = smalloc(sizeof(*this));
assert(a < b);
this->a = a;
this->b = b;
EXIT;
return this;
}
struct dependent_of_node
{
struct pair pair;
struct avl_tree_t* dependent_of; // tree of pairs
};
struct dependent_of_node* new_dependent_of_node(
struct automata* a, struct automata* b)
{
ENTER;
TODO;
#if 0
struct dependent_of_node* this = smalloc(sizeof(*this));
this->pair.a = a;
this->pair.b = b;
this->dependent_of = avl_alloc_tree(compare_pairs, free);
EXIT;
return this;
#endif
}
int compare_dependent_of_nodes(const void* a, const void* b)
{
TODO;
#if 0
int cmp = 0;
const struct dependent_of_node *A = a, *B = b;
ENTER;
cmp = compare_pairs(&A->pair, &B->pair);
EXIT;
return cmp;
#endif
}
void free_dependent_of_node(void* ptr)
{
TODO;
#if 0
struct dependent_of_node* this = ptr;
ENTER;
avl_free_tree(this->dependent_of);
free(this);
EXIT;
#endif
}
struct task
{
struct pair pair;
unsigned hopcount;
};
struct task* new_task(
struct automata* a, struct automata* b,
unsigned hopcount)
{
ENTER;
struct task* this = smalloc(sizeof(*this));
this->pair.a = a;
this->pair.b = b;
this->hopcount = hopcount;
EXIT;
return this;
}
int compare_tasks(const void* a, const void* b)
{
const struct task* A = a, *B = b;
int cmp;
ENTER;
if (A->hopcount > B->hopcount)
cmp = +1;
else if (A->hopcount < B->hopcount)
cmp = -1;
else
cmp = +0;
EXIT;
return cmp;
}
struct heap
{
void** data;
unsigned n, cap;
int (*cmp)(const void*, const void*);
};
struct heap* new_heap(
int (*cmp)(const void*, const void*))
{
ENTER;
struct heap* this = malloc(sizeof(*this));
this->cmp = cmp;
this->data = NULL;
this->n = 0;
this->cap = 0;
EXIT;
return this;
}
void* heap_pop(struct heap* this)
{
ENTER;
assert(this->n);
void* retval = this->data[0], *swap;
if (--this->n)
{
unsigned l, r, smallest, i = 0;
void** const data = this->data;
data[0] = data[this->n];
again: l = 2 * i + 1, r = 2 * i + 2, smallest = i;
if (l < this->n && this->cmp(data[l], data[i]) < 0)
smallest = l;
if (r < this->n && this->cmp(data[r], data[smallest]) < 0)
smallest = r;
if (smallest != i)
{
swap = data[i];
data[i] = data[smallest];
data[smallest] = swap;
i = smallest;
goto again; // forgive my father for I have sinned.
}
}
EXIT;
return retval;
}
void heap_push(struct heap* this, void* new)
{
ENTER;
if (this->n + 1 > this->cap)
{
this->cap = this->cap << 1 ?: 1;
this->data = realloc(this->data, sizeof(*this->data) * this->cap);
}
size_t i = this->n++, j;
void** const data = this->data, *swap;
data[i] = new;
for (; i > 0 && this->cmp(data[j = (i - 1) / 2], data[i]) > 0; i = j)
{
swap = data[i];
data[i] = data[j];
data[j] = swap;
}
EXIT;
}
void add_dep(
struct avl_tree_t* dependent_of,
struct automata* a_on, struct automata* b_on,
struct automata* a_of, struct automata* b_of)
{
ENTER;
assert(a_on < b_on);
if (a_of > b_of)
{
struct automata* swap = b_of;
b_of = a_of, a_of = swap;
}
struct avl_node_t* node = avl_search(dependent_of,
&(struct pair){a_of, b_of});
if (node)
{
struct dependent_of_node* old = node->item;
if (!avl_search(old->dependent_of, &(struct pair){a_on, b_on}))
{
struct pair* dep = new_pair(a_on, b_on);
avl_insert(old->dependent_of, dep);
}
}
else
{
struct dependent_of_node* new = new_dependent_of_node(a_of, b_of);
struct pair* dep = new_pair(a_on, b_on);
avl_insert(new->dependent_of, dep);
avl_insert(dependent_of, new);
}
EXIT;
}
struct automataset* build_universe(struct automata* start)
{
ENTER;
struct automataset* universe = new_automataset();
struct quack* todo = new_quack();
quack_append(todo, start);
automataset_add(universe, start);
while (todo->n)
{
struct automata* node = quack_pop(todo);
for (int value = 0; value < 2; value++)
{
struct automata* const to = node->on[value];
if (to && automataset_add(universe, to))
{
quack_append(todo, to);
}
}
}
free_quack(todo);
EXIT;
return universe;
}
struct avl_tree_t* dependent_of = avl_alloc_tree(
compare_dependent_of_nodes, free_dependent_of_node);
struct automataset* universe = build_universe(original);
struct heap* todo = new_heap(compare_tasks);
automataset_foreach(universe, ({
void runme(struct automata* a) {
automataset_foreach(universe, ({
void runme(struct automata* b) {
if (a < b)
{
bool unequal = false;
if (a->is_accepting != b->is_accepting)
{
unequal = true;
}
else for (int value = 0; !unequal && value < 2; value++)
{
struct automata* a_to = a->on[value];
struct automata* b_to = b->on[value];
if (!a_to != !b_to)
{
unequal = true;
}
else if (a_to && b_to)
{
add_dep(dependent_of, a, b, a_to, b_to);
}
}
if (unequal)
{
heap_push(todo, new_task(a, b, 0));
}
}
}
runme;
}));
}
runme;
}));
TODO;
#if 0
#ifdef VERBOSE
void handler12(int _)
{
char ptr[200] = {};
size_t len = snprintf(ptr, 200,
"\e[K" "zebu: automata simplify (allocating sets): %ju of %ju (%.2f%%)\r",
count, n, (((double) count * 100) / n));
if (write(1, ptr, len) != len)
{
abort();
}
}
{
count = 0, n = automataset_len(universe);
#ifdef LINUX_PLATFORM
signal(SIGALRM, handler12);
#else
#ifdef WINDOWS_PLATFORM
timer_handler = handler12;
#else
#error bad platform
#endif
#endif
}
#endif
struct avl_tree_t* connections = avl_alloc_tree(compare_same_as_nodes, free_same_as_node);
automataset_foreach(universe, ({
void runme(void* ptr) {
struct automata* a = ptr;
struct automataset* uni = automataset_clone(universe);
struct same_as_node* sa = new_same_as_node(a, uni);
avl_insert(connections, sa);
#ifdef VERBOSE
count++;
#endif
}
runme;
}));
struct avl_tree_t* connections = avl_alloc_tree(compare_same_as_nodes, free_same_as_node);
automataset_foreach(universe, ({
void runme(void* ptr) {
struct automata* a = ptr;
struct automataset* uni = automataset_clone(universe);
struct same_as_node* sa = new_same_as_node(a, uni);
avl_insert(connections, sa);
#ifdef VERBOSE
count++;
#endif
}
runme;
}));
#ifdef VERBOSE
unsigned completed = 0;
void handler2(int _)
{
char buffer[1000] = {};
unsigned total = completed + heap_len(todo);
size_t len = snprintf(buffer, sizeof(buffer),
"\e[K" "zebu: automata simplify (percolate): %u of %u (%.2f%%)\r",
completed, total,
(double) completed * 100 / total);
if (write(1, buffer, len) != len)
{
abort();
}
}
#ifdef LINUX_PLATFORM
signal(SIGALRM, handler2);
#else
#ifdef WINDOWS_PLATFORM
timer_handler = handler2;
#else
#error bad platform
#endif
#endif
#endif
while (heap_is_nonempty(todo))
{
#ifdef VERBOSE
completed++;
#endif
struct task* task = heap_pop(todo);
if (mark_as_unequal(connections, &task->pair))
{
struct avl_node_t* node = avl_search(dependent_of, &task->pair);
if (node)
{
struct dependent_of_node* dep = node->item;
unsigned hopcount = task->hopcount + 1;
avl_tree_foreach(dep->dependent_of, ({
void runme(void* ptr) {
const struct pair* pair = ptr;
heap_push(todo, new_task(pair->a, pair->b, hopcount));
}
runme;
}));
}
}
free(task);
}
// consider which states can reach any accepting state.
struct automata* new_start = clone(connections, original);
avl_free_tree(dependent_of);
free_automataset(universe);
avl_free_tree(connections);
free_heap(todo);
#ifdef VERBOSE
#ifdef LINUX_PLATFORM
signal(SIGALRM, default_sighandler);
#else
#ifdef WINDOWS_PLATFORM
timer_handler = default_sighandler;
#else
#error bad platform
#endif
#endif
#endif
EXIT;
return new_start;
#endif
size_t total_number_of_states = 0;
TODO;
if (flags->verbose)
{
printf("%*s" "returned automata with %lu states" "\n",
depth, "", total_number_of_states);
}
EXIT;
}
void free_automata(
struct automata* this)
{
TODO;
}
struct clause
{
struct clause_bundle {
unsigned variable;
bool value;
}* data;
size_t n, cap;
};
struct clause* new_clause(void)
{
struct clause* this = smalloc(sizeof(*this));
this->data = NULL;
this->n = 0;
this->cap = 0;
return this;
}
void clause_append(
struct clause* this,
unsigned variable,
bool value)
{
ENTER;
if (this->n == this->cap)
{
this->cap = this->cap << 1 ?: 1;
this->data = srealloc(this->data, sizeof(*this->data) * this->cap);
}
this->data[this->n++] = (struct clause_bundle) {variable, value};
EXIT;
}
void free_clause(
struct clause* this)
{
TODO;
}
struct problem
{
unsigned number_of_variables;
struct {
struct clause** data;
size_t n, cap;
} clauses;
};
struct problem* new_problem(
unsigned number_of_variables)
{
ENTER;
struct problem* this = smalloc(sizeof(*this));
this->number_of_variables = number_of_variables;
this->clauses.data = NULL;
this->clauses.n = 0;
this->clauses.cap = 0;
EXIT;
return this;
}
void problem_append(
struct problem* this,
struct clause* clause)
{
ENTER;
if (this->clauses.n == this->clauses.cap)
{
this->clauses.cap = this->clauses.cap << 1 ?: 1;
this->clauses.data = srealloc(
this->clauses.data,
sizeof(*this->clauses.data) * this->clauses.cap);
}
this->clauses.data[this->clauses.n++] = clause;
EXIT;
}
void free_problem(
struct problem* this)
{
TODO;
}
struct problems
{
struct problem** data;
size_t n, cap;
};
struct problems* new_problems(void)
{
ENTER;
struct problems* this = smalloc(sizeof(*this));
this->data = NULL;
this->n = 0;
this->cap = 0;
EXIT;
return this;
}
void problems_append(
struct problems* this,
struct problem* problem)
{
ENTER;
if (this->n == this->cap)
{
this->cap = this->cap << 1 ?: 1;
this->data = srealloc(this->data, sizeof(*this->data) * this->cap);
}
this->data[this->n++] = problem;
EXIT;
}
void free_problems(
struct problems* this)
{
TODO;
}
struct problems* parse(const char* file)
{
ENTER;
dpvs(file);
struct problems* problems = new_problems();
FILE* stream = fopen(file, "r");
char *line = NULL;
size_t len = 0;
ssize_t nread;
while ((nread = getline(&line, &len, stream)) > 0)
{
line[--nread] = 0;
dpvs(line);
if (line[0] == '\0') continue;
if (line[0] == 'c') continue;
if (line[0] != 'p')
{
TODO;
exit(1);
}
unsigned number_of_variables;
unsigned number_of_clauses;
int r = sscanf(line, " p %u %u ", &number_of_variables, &number_of_clauses);
if (r < 2)
{
TODO;
exit(1);
}
dpvu(number_of_variables);
dpvu(number_of_clauses);
struct problem* problem = new_problem(number_of_variables);
for (unsigned i = 0; i < number_of_clauses; i++)
{
nread = getline(&line, &len, stream);
if (nread < 0)
{
TODO;
exit(1);
}
line[--nread] = 0;
dpvs(line);
struct clause* clause = new_clause();
char *moving = line;
for (char* word; (word = strtok_r(NULL, " ", &moving)); )
{
dpvs(word);
errno = 0;
char* m;
signed variable = strtol(word, &m, 10);
if (errno || *m)
{
TODO;
exit(1);
}
bool value = true;
if (variable < 0)
{
variable = -variable;
value = !value;
}
dpvi(variable);
dpvb(value);
assert(variable > 0);
clause_append(clause, variable, value);
}
problem_append(problem, clause);
}
problems_append(problems, problem);
}
free(line);
fclose(stream);
EXIT;
return problems;
}
struct automata* build_automata(
struct cmdln_flags* flags,
struct problem* problem)
{
ENTER;
unsigned number_of_variables = problem->number_of_variables;
struct {
unsigned* data;
size_t n, cap;
} variable_lookup = {};
unsigned variable_to_index(signed variable)
{
unsigned retval;
ENTER;
assert(variable > 0);
dpvi(variable);
dpvlu(variable_lookup.cap);
if ((unsigned) variable < variable_lookup.cap)
{
dpvu(variable_lookup.data[variable]);
if (variable_lookup.data[variable] == (unsigned) -1)
{
variable_lookup.data[variable] = variable_lookup.n++;
}
dpvu(variable_lookup.data[variable]);
retval = variable_lookup.data[variable];
}
else
{
while ((unsigned) variable >= variable_lookup.cap)
{
size_t oldcap = variable_lookup.cap;
size_t newcap = oldcap << 1 ?: 1;
variable_lookup.data = srealloc(
variable_lookup.data,
sizeof(*variable_lookup.data) * newcap);
for (size_t i = oldcap; i < newcap; i++)
{
variable_lookup.data[i] = -1;
}
variable_lookup.cap = newcap;
dpvlu(variable_lookup.cap);
}
retval = variable_lookup.data[variable] = variable_lookup.n++;
}
dpvu(retval);
EXIT;
return retval;
}
int depth = 0;
for (unsigned i = 0, n = problem->clauses.n; i < n; i++)
{
struct clause* clause = problem->clauses.data[i];
struct automata* clause_automata = NULL;
depth++;
for (unsigned j = 0, m = clause->n; j < m; j++)
{
depth++;
struct clause_bundle bundle = clause->data[j];
unsigned index = variable_to_index(bundle.variable);
struct automata* variable_automata = create_variable_automata(
depth, flags,
index, bundle.value, number_of_variables);
if (flags->dump_automata)
{
dump_automata(variable_automata,
"label = \"%i (%u) = %s\"", bundle.variable, index,
bundle.value ? "true" : "false");
}
if (clause_automata)
{
struct automata* old = clause_automata;
struct automata* new = automata_union(
depth, flags, old, variable_automata);
struct automata* simp = automata_simplify(
depth, flags, new);
clause_automata = simp;
free_automata(new);
free_automata(old);
}
else
{
clause_automata = variable_automata;
}
depth--;
}
TODO;
/* if args.dump_automata:*/
/* title = " or ".join(f"{a} = {b}" for a, b in clause);*/
/* */
/* dump_automata(clause_automata, title);*/
/* */
/* clause_automatas.append(clause_automata); */
depth--;
}
TODO;
free(variable_lookup.data);
EXIT;
}
int main(
int argc,
char* const* argv)
{
ENTER;
struct cmdln_flags* flags = parse_args(argc, argv);
struct problems* problems = parse(flags->input_file);
for (unsigned i = 0, n = problems->n; i < n; i++)
{
struct problem* problem = problems->data[i];
struct automata* automata = build_automata(flags, problem);
TODO;
free_automata(automata);
}
free_problems(problems);
free_cmdln_flags(flags);
EXIT;
return 0;
}
#endif