Clingo C API
C API for clingo providing high level functions to control grounding and solving.
backend.c

The example shows how to used the backend to extend a grounded program.

Output

./backend 0
Model: a b
Model: a b c
Model:
Model: a
Model: b

Code

#include <clingo.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
bool on_model(clingo_model_t *model, void *data, bool *goon) {
(void)data;
bool ret = true;
clingo_symbol_t *atoms = NULL;
size_t atoms_n;
clingo_symbol_t const *it, *ie;
char *str = NULL;
size_t str_n = 0;
// determine the number of (shown) symbols in the model
if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
// allocate required memory to hold all the symbols
if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
goto error;
}
// retrieve the symbols in the model
if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
printf("Model:");
for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
size_t n;
char *str_new;
// determine size of the string representation of the next symbol in the model
if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
if (str_n < n) {
// allocate required memory to hold the symbol's string
if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
goto error;
}
str = str_new;
str_n = n;
}
// retrieve the symbol's string
if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
printf(" %s", str);
}
printf("\n");
*goon = true;
goto out;
error:
ret = false;
out:
if (atoms) { free(atoms); }
if (str) { free(str); }
return ret;
}
int main(int argc, char const **argv) {
char const *error_message;
int ret = 0;
size_t offset;
clingo_backend_t *backend;
clingo_atom_t atom_ids[4];
char const *atom_strings[] = {"a", "b", "c"};
clingo_part_t parts[] = {{ "base", NULL, 0 }};
// create a control object and pass command line arguments
if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
// add a logic program to the base part
if (!clingo_control_add(ctl, "base", NULL, 0, "{a; b; c}.")) { goto error; }
// ground the base part
if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
// get the container for symbolic atoms
if (!clingo_control_symbolic_atoms(ctl, &atoms)) { goto error; }
// get the ids of atoms a, b, and c
offset = 0;
for (char const **it = atom_strings, **ie = it + sizeof(atom_strings) / sizeof(*atom_strings); it != ie; ++it) {
bool equal;
// lookup the atom
if (!clingo_symbol_create_id(*it, true, &sym)) { goto error; }
if (!clingo_symbolic_atoms_find(atoms, sym, &atom_it)) { goto error; }
if (!clingo_symbolic_atoms_end(atoms, &atom_ie)) { goto error; }
if (!clingo_symbolic_atoms_iterator_is_equal_to(atoms, atom_it, atom_ie, &equal)) { goto error; }
assert(!equal); (void)equal;
// get the atom's id
if (!clingo_symbolic_atoms_literal(atoms, atom_it, &lit)) { goto error; }
atom_ids[offset++] = lit;
}
// get the backend
if (!clingo_control_backend(ctl, &backend)) { goto error; }
// add an additional atom (called d below)
if (!clingo_backend_add_atom(backend, &atom_ids[3])) { goto error; }
// add rule: d :- a, b.
body[0] = atom_ids[0];
body[1] = atom_ids[1];
if (!clingo_backend_rule(backend, false, &atom_ids[3], 1, body, sizeof(body)/sizeof(*body))) { goto error; }
// add rule: :- not d, c.
body[0] = -(clingo_literal_t)atom_ids[3];
body[1] = atom_ids[2];
if (!clingo_backend_rule(backend, false, NULL, 0, body, sizeof(body)/sizeof(*body))) { goto error; }
// solve using a model callback
if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
goto out;
error:
if (!(error_message = clingo_error_message())) { error_message = "error"; }
printf("%s\n", error_message);
out:
if (ctl) { clingo_control_free(ctl); }
return ret;
}