Paper deep dive
WAMpy: Efficient Synthesis of Prolog Programs in Python
Dominik Magiera, Lukas Röhrig, Frank Jäkel
Intelligence
Status: not_run | Model: - | Prompt: - | Confidence: 0%
Entities (0)
Relation Signals (0)
No relation signals yet.
Cypher Suggestions (0)
No Cypher suggestions yet.
Abstract
Abstract:We present WAMpy, a Python framework optimized for synthesizing Prolog programs. Unlike general-purpose Prolog systems, WAMpy targets workloads that repeatedly generate and evaluate small candidate programs. WAMpy compiles Prolog clauses into NumPy array-based WAM instructions and supports partial recompilation of hypotheses against fixed background knowledge. Performance-critical routines are accelerated using Numba just-in-time (JIT) compilation. In a benchmark of repeated compilation-and-evaluation workloads, WAMpy improves end-to-end performance compared with SWI-Prolog accessed from Python using Janus.
Tags
Links
- Source: https://arxiv.org/abs/2610.03234v1
- Canonical: https://arxiv.org/abs/2610.03234v1
Trouble viewing inline? Open PDF directly →
Full Text
10,018 characters extracted from source content.
Expand or collapse full text
WAMpy: Efficient Synthesis of Prolog Programs in Python Dominik Magiera [0009−0002−0643−9973] , Lukas Röhrig [0009−0009−9664−8226] , and Frank Jäkel [0000−0002−1355−7663] Centre for Cognitive Science & Institute of Psychology, Technische Universität Darmstadt, Germany Abstract. We present WAMpy, a Python framework optimized for synthesizing Prolog programs. Unlike general-purpose Prolog systems, WAMpy targets workloads that repeatedly generate and evaluate small candidate programs. WAMpy compiles Prolog clauses into NumPy array-based WAM instructions and supports partial recompilation of hypotheses against fixed background knowledge. Performance-critical routines are accelerated using Numba just-in-time (JIT) compilation. In a benchmark of repeated compilation-and-evaluation workloads, WAMpy improves end-to-end performance compared with SWI-Prolog accessed from Python using Janus. WAMpy is available on github.com/cognitive-modeling/WAMpy. 1 Usage and Implementation Program synthesis constructs programs from incomplete specifications, such as examples or constraints [1]. This process often involves repeatedly compiling and evaluating candidate programs while the background knowledge remains unchanged. Existing general-purpose Prolog systems such as SWI-Prolog [2] are not optimized for this workload. We therefore present WAMpy, a specialized exe- cution framework based on the Warren Abstract Machine (WAM) [3,4]. WAMpy is implemented in Python and uses Prolog as its source language, enabling direct integration with program-synthesis and machine-learning workflows. It compiles programs into a targeted subset of array-based WAM instructions. Performance- critical routines are accelerated using Numba JIT compilation [5]. Usage. WAMpy is used as a Python library rather than as a standalone Prolog interpreter. The following example compiles Prolog source into WAM instruc- tions and evaluates a query through the high-level API: import wampy as wam prolog = wam.Prolog("parent(anakin, luke).") list(prolog.query("parent(X, luke).")) The high-level API manages parsing, compilation, and query backtracking. arXiv:2610.03234v1 [cs.PL] 2 Oct 2026 2D. Magiera et al. b. 34child 1 21child 0 12540 Node i6543210 parent(anakin, luke). c. parent(anakin, luke). parent(padme, luke). parent(anakin, luke). Compile Onto Entry Points parent/2: 03 1 2parent/2: 00 Entry Points parent/2: 00 1 Compiled Program Abstract Representation male(anakin). parent(anakin, luke). father(A, B):- parent(A, B), male(A). Source Program 0 4 5 2 1 parent Clause anakinluke True ... GET_CONST 0 0 0 GET_CONST 1 1 0 PROCEED 0 0 0 TRY 7 0 0 GET_CONST 3 0 0 GET_CONST 1 1 0 PROCEED 0 0 0 JMP_TRUST 0 0 0 ... Stack male/1 01 parent/2 10 father/2 19 ... Entry Points Compiler Parser Interpreter 00: GET_CONST 0 0 0 01: GET_CONST 1 1 0 02: PROCEED 0 0 0 00: GET_CONST 0 0 0 01: PROCEED 0 0 0 02: GET_CONST 0 0 0 03: TRY 7 0 0 04: GET_CONST 3 0 0 05: GET_CONST 1 1 0 06: PROCEED 0 0 0 07: JMP_TRUST 0 0 0 00: GET_CONST 0 0 0 01: GET_CONST 1 1 0 02: PROCEED 0 0 0 03: TRY 7 0 0 04: GET_CONST 3 0 0 05: GET_CONST 1 1 0 06: PROCEED 0 0 0 07: JMP_TRUST 0 0 0 ?- father(X, luke). X = anakin. Runtime a. Fig. 1. WAMpy compilation and execution workflow. a. Pipeline from Prolog source code to query results. b. NumPy-based representation of a parsed term. c. Par- tial recompilation adds a candidate clause to precompiled background knowledge. Implementation. Uncompiled programs are represented as fixed-size arrays of top-level term trees. Each parsed term is stored as a separate AST with its own root node and integer identifier. Programs can be parsed from Prolog source code, but are primarily intended to be modified directly at the AST level during synthesis. Each program is constrained by fixed upper bounds on the number of terms, nodes per term, and children per node. Memory is allocated according to these bounds, so all programs share the same array layout. This increases memory use, but enables efficient processing by Numba-compiled routines. In- ternally, programs use fixed-size NumPy arrays: a symbol array indexed by term and node, and a child array indexed by term, node, and child slot. The number of child slots is configured in advance (Fig. 1b). Compilation lowers these AST’s into a two-dimensional array, where each row represents one instruction in our WAM subset. Each instruction consists of an opcode followed by three arguments. The compiler also constructs a predicate entry table that maps functor-arity pairs to program locations. The resulting instruction array and predicate entry table are illustrated in Fig. 1a. Multiple clauses for the same predicate are handled using WAM-style choice instructions to support backtracking. At runtime, queries are evaluated using Selective Linear Definite (SLD) clause resolution [6], where unification produces bindings and backtracking ex- plores alternative clauses. The framework provides built-in tracing of predicate calls during execution, which can be used to evaluate candidate hypotheses. WAMpy: Efficient Synthesis of Prolog Programs in Python3 Efficient Partial Recompilation. WAMpy reduces compilation overhead by compiling background knowledge once and recompiling only candidate hypothe- ses. Candidate clauses are appended to the fixed instruction sequence and tried before background clauses for the same predicate. In the single-clause case shown in Fig. 1c, the compiler appends a JMP_TRUST bridge that transfers backtrack- ing to the precompiled background clause. Predicates with multiple background clauses use JMP_RETRY to preserve further alternatives. Limitations. WAMpy implements only an X-register subset of the WAM [4], for repeated compilation and evaluation in logic program-synthesis workloads. This subset supports atoms, variables, compound structures, predicate calls, tail calls, unification, and linear clause backtracking. It does not provide a general SWI-Prolog built-in predicate library, including facilities such as arithmetic and meta-calls. 2 Evaluation We use pytest for automated validation of WAMpy’s main components and end- to-end behavior. The tests run Prolog programs to check that parsing, com- pilation, unification, backtracking, and query evaluation produce the expected answers. 110100100010000 Iterations 10 1 10 2 Time [μs, log] a. End-to-end time 110100100010000 Iterations 0 20 40 Time [μs] 14.0 3.6 b. Compilation time WAMpy partial recompilationWAMpy full compilationJanus SWI-Prolog Fig. 2. Performance benchmark of WAMpy and Janus SWI-Prolog. a. End- to-end runtime, including compilation and query execution. b. WAMpy compilation time for full-program compilation and partial hypothesis-only recompilation. Benchmark. We evaluate WAMpy on a small family-relation benchmark that mimics a synthesis loop. The program contains 13 gender facts, 13 parent facts, and seven rules. 1 For partial recompilation, the final three rules are treated as 1 The full source is available online: https://github.com/cognitive-modeling/WAMpy. 4D. Magiera et al. the hypothesis, while the remaining 30 clauses form the background knowledge. Evaluation is simulated by repeatedly querying father(X, luke). We compare against Janus 1.5.3 2 , using SWI-Prolog 10.0.2 and Python 3.13, as a Python- hosted Prolog baseline rather than evaluating standalone SWI-Prolog. All bench- marks were performed on a MacBook Pro with an Apple M3 Max processor (16 CPU cores) and 64 gigabytes of unified memory. For each iteration count N, the program was compiled and evaluated N times, with 10 samples collected per set- ting. Both WAMpy compilation modes outperform Janus in end-to-end runtime, including compilation and query execution, as shown in Fig. 2a. With increasing iterations, compilation costs become amortized, leaving Janus nearly constant at around 240μs while WAMpy decreases to (16.51± 0.13)μs with full compila- tion and (6.17± 0.03)μs with partial recompilation. Fig. 2b isolates WAMpy’s compilation time. Both compilation modes start at around 54μs, but partial re- compilation increasingly outperforms full compilation, reaching (3.64± 0.03)μs compared with (13.98± 0.13)μs. Conclusion. WAMpy is a modern Python framework for program synthesis built on NumPy data structures and Numba just-in-time (JIT) compilation. For program synthesis workloads, WAMpy is approximately 38.5 times faster than Janus SWI-Prolog by leveraging partial recompilation. Future work will extend Prolog support, explore GPU acceleration with Numba CUDA, and evaluate larger inductive logic programming benchmarks. Acknowledgments. This work was supported by the Honda Research Institute Eu- rope (HRI-EU). Disclosure of Interests. The authors have no competing interests to declare that are relevant to the content of this article. References 1. Flener, P.: Logic Program Synthesis from Incomplete Information. Springer US (1995). https://doi.org/10.1007/978-1-4615-2205-8 2. Wielemaker, J.: An overview of the SWI-prolog programming environment. In: Mes- nard, F., Serebrenik, A. (eds.) Proceedings of the 13th international workshop on logic programming environments (WLPE 2003). Report CW 371, Department of Computer Science, Katholieke Universiteit Leuven (2003) 3. Warren, D.H.D.: An abstract prolog instruction set. Tech. rep., Menlo Park, CA, USA (oct 1983), archived PDF, original published October 1983 4. Aït-Kaci, H.: Warren’s Abstract Machine: A Tutorial Reconstruction. The MIT Press (aug 1991). https://doi.org/10.7551/mitpress/7160.001.0001 5. Lam, S.K., Pitrou, A., Seibert, S.: Numba: A LLVM-based python JIT compiler. In: Proceedings of the second workshop on the LLVM compiler infrastructure in HPC. p. 1–6. SC15, ACM (nov 2015). https://doi.org/10.1145/2833157.2833162 6. Kowalski, R., Kuehner, D.: Linear resolution with selection function. Artificial Intel- ligence 2(3-4), 227–260 (dec 1971). https://doi.org/10.1016/0004-3702(71)90012-9 2 We use janus-swi 1.5.3 with SWI-Prolog 10.0.2, available on PyPI.