1. Your first circuit

Build the C package using the commands in the package README. Your application’s CMake file needs only:

find_package(tididi CONFIG REQUIRED)
target_link_libraries(your_program PRIVATE tididi::tididi)

We will represent (x ∧ y) ∨ z: either both x and y are true, or z is true. A vtree groups the variables used by related circuits. Here it contains three variables, numbered 1 through 3.

The examples use small helpers: check prints an error and stops on failure, count queries the model count, and copy and release manage circuit handles. Their definitions appear below.

Construct the three literals, then combine them. A final NULL means no operation limits. Initialize every owned output pointer to NULL.

TididiVtree *vtree = NULL;
TididiCircuit *x = NULL, *y = NULL, *z = NULL;
TididiCircuit *xy = NULL, *formula = NULL;
check(tididi_vtree_balanced(3, &vtree));
check(tididi_literal(vtree, 1, &x, NULL));
check(tididi_literal(vtree, 2, &y, NULL));
check(tididi_literal(vtree, 3, &z, NULL));
check(tididi_and(x, y, &xy, NULL));
check(tididi_or(xy, z, &formula, NULL));
printf("Satisfying assignments: %" PRIu64 "\n", count(formula));

Output:

Satisfying assignments: 5

1.1. Keep a circuit for later

tididi_and consumes x and y; tididi_or then consumes xy and z. To keep a circuit while transforming it, copy it first. Here the copy is consumed by negation while the original formula remains available.

TididiCircuit *saved = copy(formula), *complement = NULL;
check(tididi_negate(saved, &complement, NULL));
printf("Original: %" PRIu64 "; complement: %" PRIu64 "\n",
       count(formula), count(complement));

Output:

Original: 5; complement: 3

1.2. Release handles

Consumption moves the circuit out of its handle. The empty handle still needs to be freed, along with the result handles. release calls tididi_circuit_free and checks its result.

release(x); release(y); release(z); release(xy);
release(formula); release(saved); release(complement);
tididi_vtree_free(vtree);

1.3. Example helpers

These helpers call the public API directly. An application that handles errors locally can inspect the returned error instead of exiting; see Handle operation limits.

static inline void check(TididiError *error) {
    if (error) {
        fprintf(stderr, "%s\n", tididi_error_message(error));
        tididi_error_free(error);
        exit(EXIT_FAILURE);
    }
}
static inline TididiCircuit *copy(const TididiCircuit *value) {
    TididiCircuit *result = NULL;
    check(tididi_copy(value, &result));
    return result;
}
static inline void release(TididiCircuit *value) { check(tididi_circuit_free(value)); }
static inline uint64_t count(const TididiCircuit *value) {
    uint64_t result = 0;
    check(tididi_model_count(value, &result, NULL));
    return result;
}

1.4. Complete program

Download first_circuit.c and the shared helper. The source includes cleanup for all handles. Both files are included in the source checkout.