Skip to main content

Active logic meets Prolog — three-valued reasoning engine

Project description

Proact

Prolog has two truth values: succeed and fail. Proact adds a third: contwork/reasoning in progress.

Every goal returns a status. Conjunction is a sequence. Disjunction is a selector. Backtracking only triggers on failure — cont and done cut the search. Between ticks, queries returning cont are automatically re-evaluated while the database persists, giving you a stateless tick loop for free.

Applications:

  • Reasoning under uncertainty. The three values map onto epistemic states: verified, undetermined, refuted. A conjunction of checks naturally implements iterative deepening — work focuses on the earliest unresolved premise. Unary operators give you cognitive control: demote means "don't commit yet" (done→cont); promote means "don't give up yet" (fail→cont). This is relevant to validation layers for LLM reasoning, where forcing every check into true/false is lossy compression of the actual epistemic state.

  • Behavior modeling. Reactive agents, planners, robot controllers — anything where logic meets time. Prolog gives you unification, backtracking, and pattern matching. Active logic adds temporal flow. You get behavior trees with the expressiveness of logic programming, without the trees.

Install

pip install git+https://github.com/eelstork/proact.git

Requires a C compiler (gcc, clang, or MSVC).

from proact import Proact

p = Proact()
p.add("mortal(X) :- human(X). human(socrates).")
print(p.query("mortal(socrates)"))  # Result(status='done')

Tutorials

Build

make

Usage

./proact                          # REPL
./proact file.pa                  # consult file, then REPL
./proact file.pa -e "goal."      # evaluate goal and exit
./proact --max-ticks 100 -e "g." # limit tick count

The Transform

Conjunction (,) — Active logic AND / Sequence

         fail  cont  done
  fail   fail  fail  fail
  cont   cont  cont  cont
  done   fail  cont  done

If the left goal is cont, the whole conjunction is cont — don't evaluate the right side yet.

Disjunction (;) — Active logic OR / Selector

         fail  cont  done
  fail   fail  cont  done
  cont   cont  cont  cont
  done   done  done  done

If the left goal is done or cont, don't try alternatives.

Clause resolution

Multiple clauses for the same predicate provide choice points. Backtracking occurs only on fail — if a clause body returns cont or done, stop searching.

Tick loop

Queries returning cont are automatically re-evaluated on the next tick with a fresh environment. The database (asserted facts) persists between ticks.

Built-ins

Predicate Status Description
done / true done Always succeeds
fail / false fail Always fails
cont cont Always continues
inv(G) / \+ G swap done/fail, keep cont Inverter
condone(G) fail→done Forgive failure
promote(G) fail→cont, cont→done Optimistic
demote(G) done→cont, cont→fail Pessimistic
par_any(A,B) max(A,B) Lenient parallel
par_all(A,B) min(A,B) Strict parallel
tick(N) done Unify N with current tick

Plus standard Prolog: write/1, writeln/1, nl, assert/1, retract/1, is/2, =/2, \=/2, </2, >/2, >=/2, =</2, call/1, consult/1.

Examples

Wait N ticks, then succeed

wait(N) :- tick(T), T >= N.
wait(N) :- tick(T), T < N, cont.
?- wait(3), writeln(hello).
[tick 0] cont
[tick 1] cont
[tick 2] cont
hello
done.

Counter (stateful, using assert/retract)

:- assert(count(0)).

count_to(Target) :- count(N), N >= Target.
count_to(Target) :-
    count(N), N < Target,
    retract(count(N)), N1 is N + 1, assert(count(N1)),
    cont.

Reactive behavior (condition-gated sequence)

:- assert(agent_pos(0)).

move_to(X) :- agent_pos(P), P =:= X.
move_to(X) :- agent_pos(P), P < X,
    retract(agent_pos(P)), P1 is P + 1, assert(agent_pos(P1)), cont.

patrol :-
    agent_pos(P), P < 3, move_to(3), cont.
patrol :-
    agent_pos(P), P >= 3, P < 5, move_to(5), cont.
patrol :-
    agent_pos(P), P >= 5.

Reasoning under uncertainty

% reason.pa — three-valued validation for multi-step arguments

:- assert(known(premise_a)).
:- assert(investigation(premise_b, 2)).
:- assert(investigation(premise_c, 1)).

check(P) :- known(P).
check(P) :- known_false(P), fail.
check(P) :-
    investigation(P, N), N > 0,
    retract(investigation(P, N)), N1 is N - 1,
    (N1 > 0 -> assert(investigation(P, N1)) ; assert(known(P))),
    cont.

argument :- check(premise_a), check(premise_b), check(premise_c).

The conjunction is the search strategy — it focuses work on the earliest unresolved premise and doesn't waste computation on steps whose preconditions haven't been met:

[tick 0] a=done, b=cont          → cont  (c never reached)
[tick 1] a=done, b=done, c=cont  → cont  (work shifts to c)
[tick 2] a=done, b=done, c=done  → done

The epistemic operators give cognitive control over the validation:

cautious(X)       :- demote(check(X)).    % "verified but needs review"  (done→cont)
keep_exploring(X) :- promote(check(X)).   % "refuted but try harder"     (fail→cont)
viable_theory     :- par_any(hyp_a, hyp_b). % first hypothesis verified wins

Relation to active-logic

This prototype implements the core operators from activelogic-cs in a logic programming context:

C# (activelogic-cs) Proact BT equivalent
status && status Goal, Goal Sequence
status || status Goal ; Goal Selector
+ (lenient) par_any(A, B) Parallel (any)
* (strict) par_all(A, B) Parallel (all)
!status inv(G) Inverter
~status condone(G) Condone
+status (unary) promote(G) Promoter
-status (unary) demote(G) Demoter
cont cont Running

The key addition over Prolog is cont — a single built-in that bridges logic programming with reactive, tick-based behavior.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

proact_py-0.1.15.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

proact_py-0.1.15-py3-none-win_amd64.whl (100.9 kB view details)

Uploaded Python 3Windows x86-64

File details

Details for the file proact_py-0.1.15.tar.gz.

File metadata

  • Download URL: proact_py-0.1.15.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for proact_py-0.1.15.tar.gz
Algorithm Hash digest
SHA256 548fe6974e3525d9bff0cd8889beaf7ed280b0413554d1dd8550c885200c2b42
MD5 b2f7ac8c953b87387c3712b57bd49c42
BLAKE2b-256 6e1638243786cc2360b0e26a62946dc54d5763e624c43b32a195f68cf609188e

See more details on using hashes here.

Provenance

The following attestation bundles were made for proact_py-0.1.15.tar.gz:

Publisher: release.yml on eelstork/proact

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file proact_py-0.1.15-py3-none-win_amd64.whl.

File metadata

  • Download URL: proact_py-0.1.15-py3-none-win_amd64.whl
  • Upload date:
  • Size: 100.9 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for proact_py-0.1.15-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 3ba4d43f9ba5450e1f9da4b50bdc59d3ae35d374046cd702a5ad5b04483df97a
MD5 83c6ac66153187041f2a18a923e17f03
BLAKE2b-256 d39974b59da94f32e193f1b6300fe43ced76b367ec88daf3e7ddf121d50e81fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for proact_py-0.1.15-py3-none-win_amd64.whl:

Publisher: release.yml on eelstork/proact

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page