tddlog for C¶
Exact probabilistic inference from C and C++.
tddlog computes exact probabilities for ProbLog programs, LPADs, Dice programs, Circulette netlists and Bayesian and Markov networks. This library exposes the same Rust implementation as the command line through a C interface. A program goes in as text, and the probabilities of its queries come out through an opaque solution handle.
The ABI is unstable before 1.0. Struct layouts, status codes and
signatures can change in any release. Build against the version you ship
with and check tddlog_version() at run time.
Install¶
The release has a prebuilt archive for Linux x86-64 and ARM64, macOS ARM64 and x86-64, and Windows x86-64. It needs no Rust toolchain. On Linux x86-64:
curl -L https://github.com/Tractables/tddlog/releases/download/v0.1.1/tddlog-c-v0.1.1-x86_64-unknown-linux-gnu.tar.gz | tar xz
export PKG_CONFIG_PATH=$PWD/tddlog-c-v0.1.1-x86_64-unknown-linux-gnu/lib/pkgconfig
cc prog.c $(pkg-config --cflags --libs tddlog) -o prog
A
.tar.gzholds the header ininclude/, the shared and static libraries, the CMake package andlib/pkgconfiginlib/, and the license and notices inshare/licenses/tddlog.With CMake, set
CMAKE_PREFIX_PATHto the unpacked directory, callfind_package(tddlog CONFIG REQUIRED)and linktddlog::tddlog. The CMake package is for Linux and macOS.The Windows zip holds the header,
tddlog_c.dll, its import librarytddlog_c.dll.liband the statictddlog_c.lib.NATIVE-STATIC-LIBS.txtin each archive names the system libraries a static link needs.The dynamic loader has to find the library at run time: an rpath,
LD_LIBRARY_PATHon Linux orDYLD_LIBRARY_PATHon macOS.
Getting started¶
This program answers the queries of program, a ProbLog program as
text, and the probability of its evidence:
TddlogOptions options = tddlog_options_default();
options.evidence_probability = true;
TddlogSolution *solution;
if (tddlog_solve(program, &options, &solution) != TDDLOG_OK) {
fprintf(stderr, "%s\n", tddlog_last_error_message());
return 1;
}
for (size_t i = 0; i < tddlog_solution_num_answers(solution); i++)
printf("%s:\t%f\n", tddlog_solution_query(solution, i),
tddlog_solution_probability(solution, i));
double evidence, log10_evidence;
if (tddlog_solution_evidence_probability(solution, &evidence, &log10_evidence))
printf("P(e):\t%g\tlog10 %f\n", evidence, log10_evidence);
tddlog_solution_free(solution);
examples/alarm.c runs it on the alarm example and checks the answers.
It calls log10, so it links the maths library too:
cc bindings/c/examples/alarm.c $(pkg-config --cflags --libs tddlog) -lm -o alarm
TddlogOptionsholds the command line’s options:vtree,evidence_probabilityandqueries. Null options are the defaults.formatsays what the text is:"problog"or null (LPADs included),"dice","circulette", or a network’s"bif","hugin","xdsl"or"uai".evidenceis the text of a network’s evidence file (Ace’s.instor UAI’s.evid).argumentsare strings that take the program’s places$1,$2, …tddlog_solvereturnsTDDLOG_OKor an error status, andtddlog_last_error_message()gives the command line’s message.The answers are in the order of the program’s queries. Where the evidence is inconsistent,
tddlog_solution_consistentis false and there are none.The caller frees the solution with
tddlog_solution_free. Its query strings live until then.tddlog is single-threaded. Each thread may solve its own program, and error messages are kept per thread.
The header documents every type, function and status code. The guide describes the language, and its worked examples open in the playground. The website has the benchmark results.
Build from source¶
This needs Rust 1.88 or newer (rustup installs it),
a C++20 compiler, a C compiler, make and CMake 3.16 or newer. The
guide’s
getting started
says what to do if the build fails.
git clone --depth 1 https://github.com/Tractables/tddlog
cd tddlog
cmake -S bindings/c -B build/c -DCMAKE_BUILD_TYPE=Release
cmake --build build/c --config Release
ctest --test-dir build/c -C Release --output-on-failure
cmake --install build/c --config Release --prefix /your/install/prefix
The installation is laid out as the archive above. Without CMake, as on
Windows, cargo builds the libraries in bindings/c/target/release, and
the header is bindings/c/include/tddlog.h:
cargo build --release --manifest-path bindings/c/Cargo.toml
A static link also needs the C++ runtime and the system libraries that
cargo rustc --release --manifest-path bindings/c/Cargo.toml -- --print native-static-libs
prints. On Linux:
cc -Ibindings/c/include prog.c bindings/c/target/release/libtddlog_c.a \
-lstdc++ -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc -o prog
python bindings/c/check.py builds, tests and installs the package, then
builds the example against it through CMake and pkg-config.
include/tddlog.h is generated from src/lib.rs by
cbindgen and committed. After
changing src/lib.rs, run python bindings/c/check.py --write-header.
Acknowledgements¶
This material is based upon work supported by the Defense Advanced Research Projects Agency (DARPA) under Agreement No. HR0011269E224.