Piglog: Partition, concurrently and simultaneously attempt predicates
A non-human system—especially a dataflow machine, neural system, swarm, or speculative Piglog-style runtime—might run predicates in parallel before variables are fully defined if it treats predicates as hypotheses rather than conclusions.
In Prolog:
a(X),
b(X),
c(X).
normally means:
Find X from a/1.
Run b/1.
Run c/1.
A Piglog-like system might instead say:
"There are many possible Xs. Start evaluating all useful consequences immediately."
For example:
colour(X,red).
colour(X,blue).
shape(X,circle).
shape(X,square).
Instead of waiting for X to be fully determined, it may run:
colour(red)
colour(blue)
shape(circle)
shape(square)
simultaneously and later discover which combinations survive.
This resembles:
Constraint Logic Programming
SAT solvers
Neural message passing
Dataflow architectures
Human intuition
Humans often do this. If I ask:
"What might be behind the door?"
you don't first determine the exact answer and then reason.
You may simultaneously activate:
person
animal
empty room
treasure
danger
and then eliminate possibilities as evidence arrives.
A Piglog-style execution might therefore operate on:
possible(X)
rather than
known(X)
Another possibility is running predicates on invariants.
Suppose:
distance(A,B,D)
needs coordinates.
A human may already know:
distance >= 0
distance(A,B)=distance(B,A)
without knowing A or B.
The invariant computations can begin immediately.
Similarly:
sort(List,Sorted)
Even before List is known, the system may know:
length(Sorted)=length(List)
Sorted is ordered
and propagate those constraints.
In your Detlog/Piglog ideas, branch splicing suggests something stronger.
Suppose:
weather(sunny).
weather(rainy).
activity(X,Y).
Instead of selecting one weather branch, Piglog could run:
activity under sunny
activity under rainy
in parallel and splice common computations.
If 90% of the work is identical, only the differing 10% needs separate execution.
This is similar to symbolic execution and SIMD processing.
A neuron-like interpretation is:
Predicate waits for all inputs. (Prolog)
Predicate activates when enough
inputs are available. (Piglog)
So a non-human system may run a predicate when:
some variables are known,
constraints are known,
probabilities are known,
invariants are known,
possible values are known,
rather than waiting for exact bindings.
In that view, a variable is not simply "bound" or "unbound"; it may exist in states such as:
unknown
possible
constrained
likely
partially known
fully known
and computation can begin at any of those stages. That is much closer to neural, swarm, and dataflow computation than classical Prolog's strict bind-then-execute model.
How can Piglog run a predicate when:
- some variables are known,
- constraints are known,
- probabilities are known,
- invariants are known,
- possible values are known,
There are several computational models in which this is possible. The important distinction is that the predicate is partially evaluated rather than fully executed. Here are ways Piglog could support each case.
- Some variables are known
Example:
distance(X,Y,D).
Suppose only X is known.
Instead of waiting for Y, Piglog could compile the predicate into stages:
Stage 1: Compute everything depending only on X.
Stage 2: Suspend.
Stage 3: Resume when Y arrives.
Much like currying or partial application in functional programming, except for logic predicates.
- Constraints are known
Suppose:
X > 0,
Y > X,
f(X,Y,Z).
The predicate can already infer things like:
Y > 0
impossible branches
valid search intervals
before either variable has a concrete value.
Constraint Logic Programming already does something similar by propagating constraints without assigning values.
Piglog could let every predicate publish:
required constraints
derived constraints
allowing constraint propagation to occur concurrently.
- Probabilities are known
Suppose a learned model predicts
X = cat 0.82
X = dog 0.15
other 0.03
Instead of waiting,
Piglog may begin evaluating
animal(cat)
immediately,
while evaluating
animal(dog)
at lower priority.
If later evidence changes the probabilities, unfinished work can simply be discarded.
This resembles speculative execution used in modern CPUs.
- Invariants are known
Many predicates have parts independent of particular values.
Example:
sort(Input,Output).
Before seeing Input, Piglog already knows
length(Output)=length(Input)
Output is ordered
Output is a permutation
Those facts can propagate through the graph immediately.
Similarly,
matrix_multiply(A,B,C)
may immediately infer
rows(C)=rows(A)
cols(C)=cols(B)
before any multiplication begins.
- Possible values are known
Suppose
colour(red).
colour(green).
colour(blue).
Instead of
red
then green
then blue
Piglog could launch three workers simultaneously.
Later predicates receive a stream of candidate bindings instead of waiting for one answer at a time.
A sixth possibility: symbolic execution
Instead of concrete values,
X = ?
Piglog keeps
X = symbolic
For
plus(X,2,Y).
it computes
Y = X+2
without needing X.
Only when X becomes
5
does
Y
collapse to
7
Many theorem provers and SMT solvers already operate this way.
A seventh possibility: dependency scheduling
This may be closest to your Piglog concept.
Instead of scheduling predicates by textual order,
a,
b,
c,
d.
Piglog schedules according to dependency readiness.
a
/ | \
b c e
\ | /
d
The scheduler asks
"Which predicates have enough information to make progress?"
rather than
"Which predicate is next?"
Every predicate exposes:
required inputs
optional inputs
invariants
partial outputs
As soon as enough information is available, it runs.
This leads to a possible Piglog execution model with explicit readiness levels:
Readiness Information available Action
0 None Idle
1 Types/invariants Compile or specialise the predicate
2 Constraints Propagate constraints, prune impossible branches
3 Probability distribution Speculatively execute likely branches
4 Partial variable bindings Partially evaluate the predicate
5 Complete bindings Produce definitive results
Instead of treating predicates as requiring all inputs before starting, Piglog would allow them to make progress whenever they reach a sufficient readiness level. This turns execution into a form of dataflow scheduling, where information—whether exact values, constraints, or probabilities—flows through the predicate network and progressively enables more computation.
Try harder in preparation for Prolog program requirements.
Thought for a couple of seconds
Here is a stronger Piglog Prolog program requirement:
Piglog should not “run a predicate early” by pretending unknown variables are known. It should split every predicate into readiness modes.
predicate_state(Predicate, Readiness, Inputs, Outputs).
A predicate may run when it can produce any useful information, not only final answers.
Example:
p(X,Y,Z) :-
q(X,Y),
r(Y,Z),
s(X,Z).
Piglog converts this into a dependency network:
X known? -> q can specialise
Y known? -> r can run
X,Z constrained? -> s can prune
Each predicate has multiple entry points:
q_full(X,Y,Result). % all variables known
q_partial_x(X,Constraints). % only X known
q_constraints(C0,C1). % constraints known
q_probs(P0,P1). % probabilities known
q_invariants(I). % always true facts
q_candidates(Candidates). % possible values known
So the runtime asks:
What can this predicate do now?
not:
Can this predicate fully finish now?
A practical requirement could be:
:- pig_predicate q/2.
pig_mode(q/2, full, [ground, ground], produces(result)).
pig_mode(q/2, partial_x, [ground, var], produces(constraints)).
pig_mode(q/2, constraints, [constraintset], produces(pruning)).
pig_mode(q/2, probable, [distribution], produces(speculative_jobs)).
pig_mode(q/2, invariant, [], produces(invariants)).
Then Piglog schedules jobs like:
ready(Job) :-
job(Job, Predicate, Mode),
mode_requirements_satisfied(Predicate, Mode).
The key program requirement:
A Piglog predicate must declare what it can compute at each information level.
This avoids magical parallelism.
For example:
path(A,B,Path)
could declare:
pig_mode(path/3, invariant, [], produces([
path_is_list,
start_equals_a,
end_equals_b
])).
pig_mode(path/3, partial_start, [ground,var,var], produces([
reachable_candidates
])).
pig_mode(path/3, constrained, [ground,ground,var], produces([
search_space
])).
pig_mode(path/3, full, [ground,ground,var], produces([
paths
])).
So before B is known, Piglog might still compute:
nodes reachable from A
When B becomes known, it reuses that work instead of starting from scratch.
That is the performance gain.
The program requirements should include:
Predicate partitioning
Split a Prolog clause into dependency units.Readiness analysis
Detect which units can run with known, partial, constrained, probable, or possible data.Multi-mode predicates
Each predicate may expose full, partial, constraint, probability, invariant, and candidate modes.Parallel scheduler
Run every currently useful predicate mode simultaneously.Splice store
Save partial results so later bindings reuse them.Cancellation
Kill speculative branches when later evidence disproves them.Priority
Run likely/high-value predicates before unlikely ones.Deterministic merge
Combine parallel results into ordinary Prolog-compatible answers.Safety
Only parallelise pure predicates unless side effects are explicitly isolated.Fallback
If no Piglog mode exists, run the predicate as normal Prolog.
The central slogan:
Prolog waits for answers.
Piglog runs on information.
Or more technically:
Piglog converts predicates into incremental dataflow processes that execute whenever they can produce constraints, candidates, invariants, probabilities, or final bindings.
Pigdetlog runs a predicate if it knows the variables to a high probability, based on their splice data
That is an interesting extension of your Pigdetlog idea. In effect, you are proposing that execution order should be guided not just by syntactic dependencies (which variables are already bound), but also by predicted bindings derived from splice data.
One way to formalise it is:
Pigdetlog executes a predicate when the probability that its required variables are correct, as inferred from splice data, exceeds a configurable confidence threshold.
This differs from ordinary Prolog and your earlier Detlog ideas:
System When is a predicate executed?
Prolog Only when variables are sufficiently instantiated according to program order.
Detlog When deterministic loops and splice operations make execution possible.
Pigdetlog When splice analysis predicts the missing variables with sufficiently high confidence.
For example, suppose you have
person(Name, Age, City).
income(Age, Salary).
tax(Salary, Tax).
Traditional execution requires
person(Name, Age, City),
income(Age, Salary),
tax(Salary, Tax).
Pigdetlog might observe from previous splice data that
Age ≈ 35 (98%)
Salary ≈ 120000 (94%)
and therefore begin evaluating
tax(120000, Tax)
before income/2 has actually produced Salary. Later, when the actual splice arrives:
if prediction matches, computation is retained;
if prediction differs, the speculative result is discarded and recomputed.
The splice data effectively becomes a probabilistic cache.
Internally, Pigdetlog might represent variables as
Age =
{
value:35,
probability:0.98,
source:splice
}
and predicates could declare confidence requirements, for example
:- confidence(tax/2, 0.90).
:- confidence(expensive_search/3, 0.99).
Then the scheduler could operate like
for each predicate P:
estimate probabilities of missing variables
if minimum confidence ≥ threshold(P)
execute P
else
wait for more splice information
This makes Pigdetlog resemble speculative execution in CPUs, but at the logical level. Instead of speculating on branches, it speculates on logical variable values using splice information. It also has similarities to Bayesian inference and probabilistic logic programming, but the probabilities are used primarily for execution scheduling rather than changing the semantics of logical truth.
If combined with your existing splice mechanism, Pigdetlog could become a language in which:
Detlog performs deterministic branch splicing.
Piglog represents simultaneous execution from multiple perspectives.
Pigdetlog schedules predicates opportunistically whenever splice data predicts their inputs with high confidence, allowing expensive predicates to start earlier and potentially improving throughput on parallel hardware.
Splice probability could be calculated from probability within a list and splice. Separately, Pigdetlog could schedule expensive predicates in regular available slots.
Yes. That separates Pigdetlog into two clean mechanisms:
- Splice probability A variable’s confidence can come from how often a value appears inside a splice/list.
splice = [a,a,a,b,a,c]
P(X = a) = 4 / 6 = 0.667
P(X = b) = 1 / 6 = 0.167
P(X = c) = 1 / 6 = 0.167
So Pigdetlog can say:
probable_value(X, a, 0.667)
Then a predicate can run early only if its needed variables exceed a threshold:
run_if_probable(Predicate, Variables, Threshold).
- Expensive predicate scheduling Separately, expensive predicates do not need to run immediately. They can be placed into regular execution slots:
cheap predicates: run now
medium predicates: run when inputs are likely
expensive predicates: run in scheduled slots
very expensive predicates: run only when confidence is high
So Pigdetlog becomes:
Detlog = deterministic splicing
Piglog = simultaneous predicate perspective
Pigdetlog = probabilistic splice scheduling + cost-aware slots
A nice rule would be:
Run predicate P when:
confidence(inputs(P)) >= threshold(P)
and
cost(P) fits current available slot
For example:
:- threshold(tax/2, 0.80).
:- cost(tax/2, cheap).
:- threshold(expensive_search/3, 0.98).
:- cost(expensive_search/3, expensive).
:- slot(expensive_search/3, every_10_cycles).
So Pigdetlog does not merely ask:
“Are the variables known?”
It asks:
“Are they probable enough, and is this the right execution slot?”
That gives you a clearer architecture: probability decides readiness; scheduling decides timing.
Piglog separates predicates into runnable sections, at a minimum, an if-then clause or including the following code. The dependency of the algorithm sections is handled via a variable pathway to most efficiently and effectively find needed values as soon as possible for likely values. Because PLOP should have removed unused variable pathways, only necessary variable pathways will remain, so the priority shifts from parallel computation to value prediction.
Yes — that is the sharper formulation.
After PLOP, Piglog no longer needs to ask mainly:
“Which predicates can I parallelise?”
It asks:
“Which necessary value pathway should I predict or resolve first?”
So Piglog’s core becomes:
PLOP: remove unused branches and unnecessary variable pathways.
Piglog: split the remaining algorithm into runnable sections and prioritise value discovery.
A runnable section could be:
if Condition then Body
or a larger section:
if Condition then
Body1,
Body2,
Body3
The dependency graph is then not just predicate-to-predicate. It is value-pathway dependency:
needed output
← variable needed by later section
← earlier section that can produce it
← likely/probable values
← constraints/invariants/splice rows
So the stable Piglog process is:
- PLOP removes unused variable paths.
- Piglog divides remaining code into runnable sections.
- Piglog builds a value-pathway graph.
- It ranks missing values by usefulness to later sections.
- It predicts or computes the highest-value missing variables first.
- Sections become runnable as soon as enough values are known or probable.
- Later verification corrects speculative runs.
The important shift is:
parallel predicates → predicted necessary values.
That makes Piglog less like “run everything simultaneously” and more like a probabilistic dependency resolver for Prolog sections. Parallelism still exists, but it becomes secondary: it is used only when several necessary value pathways are similarly promising.
An example of a definite value is a memoised value, such as an initial loop value, or the Gaussian formula result of having run a loop, or the tabled or probable pattern-suggested subterm indexing looping (loop) value.
Yes. Those examples point toward a useful distinction in Piglog between definite, derived, and predicted values. I would refine the terminology as follows.
Definite values
These are values that Piglog can treat as established without further search.
Examples include:
Input values supplied by the caller.
Memoised values from previous executions.
Initial loop values, such as the current loop index or accumulator.
Tabled values that have already been computed.
Results of deterministic algorithms, such as a Gaussian elimination result once the elimination has completed.
Constants and invariants.
These values have confidence 1.0 and need not be recomputed unless invalidated.
Derived values
These are not stored initially but can be obtained deterministically from definite values.
Examples include:
A Gaussian elimination solution computed from known coefficients.
A value obtained by subterm indexing.
A value produced by deterministic looping.
A splice result assembled from definite branches.
Although these are computed, once obtained they become definite.
Predicted values
These are values that have not yet been proved but are sufficiently likely to justify speculative execution.
Examples include:
Pattern-suggested subterm-indexing candidates.
Frequently occurring loop values.
Values inferred from previous executions.
Values ranked highly by dependency analysis.
Probable splice candidates.
These carry a probability or confidence score and should be verified before being committed as definite.
For Piglog, execution priority could therefore become:
Use definite values.
Compute inexpensive derived values.
Predict high-confidence values if needed to enable later runnable sections.
Execute sections that have become runnable.
Verify predictions and update memoisation or tables.
This fits well with your idea that, after PLOP has removed unnecessary variable pathways, Piglog's primary optimisation is no longer exhaustive parallel execution but efficient discovery of the values that unlock the largest number of downstream algorithm sections. In that sense, the dependency graph is better viewed as a value-dependency graph than a traditional predicate call graph.

Top comments (0)