Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,448 changes: 2,448 additions & 0 deletions .aider.chat.history.md

Large diffs are not rendered by default.

195 changes: 195 additions & 0 deletions .aider.input.history
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@

# 2024-08-05 09:54:07.407946
+/chat-mode ask

# 2024-08-05 09:54:28.999312
+I would like to understand this codebase.

# 2024-08-05 09:55:05.072542
+/add README.md

# 2024-08-05 09:57:23.283604
+Let's start with Deliverable 1. If i should add more files to the context say so.

# 2024-08-05 09:59:51.108630
+/add experiments/expr/bytestring/src/lib.rs experiments/expr/bytestring/src/main.rs

# 2024-08-05 10:03:41.267616
+/add experiments/expr/dyck/src/lib.rs experiments/expr/dyck/src/main.rs

# 2024-08-05 10:03:50.698226
+/drop

# 2024-08-05 10:03:53.402657
+/add experiments/expr/dyck/src/lib.rs experiments/expr/dyck/src/main.rs

# 2024-08-05 10:08:35.968329
+/drop

# 2024-08-05 10:08:39.454500
+/add benchmarks/aunt-kg/src/main.rs

# 2024-08-05 11:45:09.243720
+/drop

# 2024-08-05 11:45:18.955521
+/add frontend/src/lib.rs

# 2025-08-27 10:39:53.475349
+N

# 2025-08-27 10:40:47.613828
+/add kernel/src/main.rs

# 2025-08-27 10:46:27.575565
+/ask explain how the code in SPACE

# 2025-08-27 10:46:38.449783
+/ask explain how the code in `SPACE_EXPRS` works.

# 2025-08-27 10:58:28.464193
+/add kernel/src/existential.txt

# 2025-08-27 10:58:47.839059
+/architect How can we implement the changes described in existential.txt

# 2025-08-27 11:08:24.011216
+N

# 2025-08-27 11:08:43.120324
+/add kernel/src/explainer.txt

# 2025-08-27 11:08:47.907216
+/architect

# 2025-08-27 11:09:43.323598
+You are not supposed to modify the rust code but the mm2 code in the SPACE_EXPRS string.

# 2025-08-27 11:44:54.319720
+/ask

# 2025-08-27 11:44:58.520559
+Can you explain that change.

# 2025-08-27 16:24:35.949865
+/reset

# 2025-08-27 16:26:05.339353
+/add kernel/src/explainer kernel/src/main.rs

# 2025-08-27 16:26:09.634620
+N

# 2025-08-27 16:26:13.598523
+/add kernel/src/explainer.txt

# 2025-08-27 16:29:13.931962
+add a new function to work on skolemization (i want to preprocess facts/rule before adding them to the kb) create a new rust function to test that. The main work should be done in mm2 (SPACE_EXPRS) but we can use rust if there is no way around it. For example i want to take the input (-> (Dog $d) (And (Cat $c) (Chase $d $c))) here $c is unbound/existentially quantified and turn it into (-> (Dog $d) (And (Cat (f $d)) (Chase $d (f $d)))

# 2025-08-28 11:56:23.106837
+N

# 2025-08-28 11:56:31.980386
+/add kernel/src/main.rs

# 2025-08-28 11:58:59.288604
+I am working on the `skolemize_test` which works except for one last issue if we have multipe universialy quanitefed variables we end up with multipe (out $old $new) mappings for each of them. Which results in multipe fcls . Do you have any idea on how to solve that?

# 2025-08-28 12:01:18.073907
+N

# 2025-08-28 12:05:39.315908
+That doesn't quite work and also i would have prefereed a version that does that in mm2 (the code in the string) and not rust. Currently i am getting (Pred2 &a (f &a)) (Pred2 &a (f &c)) but i want to get only (Pred2 &a (f &a &b))

# 2025-08-28 13:18:23.919231
+Oh yes i ment (Pred &a (f &a &c))

# 2025-08-28 13:22:00.144205
+N

# 2025-08-28 13:22:18.082326
+Alright and now implement the soklemization in pure rust as a seperate function.

# 2025-08-28 13:37:10.530198
+Okay so i didn't want you to replace the old code but create a seperate function so i can compare them. The pure rust code shouldn't use a Space at all. Instead start with a String and instead of doing your own tokenization use the SExp type from MORK

# 2025-08-28 13:41:44.673776
+/undo

# 2025-08-28 13:43:08.648956
+/add kernel/src/space.rs

# 2025-08-28 13:44:36.601640
+Two strings for premies and conclusion but without the prefix. Yes for now return it as a string but again without the prefix fcls. For the which sexp / parser to use have a look in space.rs specifiaclly in load_all_sexpr.

# 2025-08-28 13:50:11.462057
+/run cargo run -p kernel

# 2025-08-28 13:50:11.469813
+/run cargo run -p kernel

# 2025-08-28 13:50:16.324848
+N

# 2025-08-28 13:50:23.333528
+!cd kernel && cargo run

# 2025-08-28 13:50:31.545432
+What's wrong? Fix

# 2025-08-28 13:54:35.583514
+/run cd kernel && cargo run

# 2025-08-28 13:54:35.591370
+/run cd kernel && cargo run

# 2025-08-28 13:55:12.638230
+What's wrong? Fix

# 2025-08-28 13:56:50.846229
+/run cd kernel && cargo run

# 2025-08-28 13:56:50.854044
+/run cd kernel && cargo run

# 2025-08-28 13:58:06.768376
+Seems you are just guessing should i add more files to the context?

# 2025-08-28 14:08:22.304262
+/run cd kernel && cargo run

# 2025-08-28 14:08:22.311934
+/run cd kernel && cargo run

# 2025-08-28 14:08:34.965532
+N

# 2025-09-22 15:22:15.995662
+/add kernel/src/main.rs

# 2025-09-22 15:22:46.198699
+Extend the run command so we can load multiple files instead of only a single input_path

# 2025-09-22 15:23:15.961755
+/edit

# 2025-09-22 15:24:54.607748
+N

# 2025-09-22 15:25:12.540595
+/add kernel/src/main.rs

# 2025-09-22 15:25:16.098359
+Extend the run command so we can load multiple files instead of only a single input_path

# 2025-09-22 15:50:39.882717
+/ask currently we are dumping everything in the space into the output file with `dump_all_sexpr` instead i would like to use s.dump_sexpr(expr!(s, "[2] ev $"), expr!(s, "_1"), &mut v)which takes an expression to match in the space and another expression to transform into. That way we could extract only what we need but i'm not sure how to best pass that info to the executable. Idea?

# 2025-09-22 15:54:32.811298
+you were in ask mode please implement that change

# 2025-09-22 15:55:16.148524
+If i only provide a list of files as inputs it assume the last one is the outputfile can we make sure that distingish that with -o or something

# 2025-09-22 16:09:24.782786
+/commit
Binary file added .aider.tags.cache.v3/cache.db
Binary file not shown.
Binary file added .aider.tags.cache.v3/cache.db-shm
Binary file not shown.
Binary file added .aider.tags.cache.v3/cache.db-wal
Binary file not shown.
Binary file added .aider.tags.cache.v4/cache.db
Binary file not shown.
Binary file added .aider.tags.cache.v4/cache.db-shm
Binary file not shown.
Binary file added .aider.tags.cache.v4/cache.db-wal
Binary file not shown.
Binary file not shown.
12 changes: 12 additions & 0 deletions kernel/src/existential.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
I have a logic system and i want to change the way i deal with existentials.
up till now if we hade a rule like (Implication (Dog $d) (And (Cat $c) (Chase $d $c)))
where the $c variable is unbound in the conclusion we just generate a new object/token for it.
That works but requires us to later proof that that object is the same as some other object.
Instead i realized if we just leave the unbound variable as is It can just be unified with that
other object simplifying the process significantly. But this only works if we keep track of all
Properties of $c. So if we are trying to proof who (Chase $who me) ["who is chasing me"] that
could unify with the result of the above impliction lets just assum a dog blacky so
(And (Cat $c) (Chase blacky $c)) we project out the Chase and could get (Chase blacky me)
after unification. Thats what the would happen right now if we just leave the variables
unbound but this could be wrong. To make it right after that unification we would need to
proof (Cat me) aswell. (as the $c appears both in (Cat $c) and (Chase _ $c)).
76 changes: 76 additions & 0 deletions kernel/src/explainer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

Short version: SPACE_EXPRS defines a tiny logic-programming/goal-reduction calculus as data (rules and a
strategy) that the Space.metta_calculus engine executes. It uses three predicates to represent the
state:

• kb (: proof proposition) — facts you already know (knowledge base)
• goal (: proof proposition) — things you want to prove
• ev (: proof proposition) — things you have derived (evidence/proofs)

Notation:

• Variables start with $ and unify across a rule.
• (: p t) pairs a proof term p with its type/proposition t.
• (-> a b) is a function type a → b.
• (@ f x) is function application, i.e., apply f to x.
• (, a b c …) is just a list/tuple grouping multiple premises/effects.
• (step name) identifies a rule; each rule is written as ( (step name) (, Premise1 Premise2 …) (,
Effect1 Effect2 …) )

What each rule does

1 step base Premises: goal (: $proof $conclusion) and kb (: $proof $conclusion) Effect: ev (:
$proof $conclusion)

Meaning: if your current goal matches a fact in the KB, you can promote it to evidence immediately.

2 step abs Premise: goal (: $proof $conclusion) Effect: goal (: $lhs (-> $synth $conclusion))

Meaning: to prove a conclusion, you may instead try to find a function that, when given something
($synth), produces the conclusion. This is a backward-chaining/introduction step that sets up searching
for a function.

3 step rev Premises: ev (: $lhs (-> $a $r)) and goal (: $k $r) Effect: goal (: $rhs $a)

Meaning: if you already have a function of type a → r and your goal is r, reduce the goal to “produce an
a” (so you can feed it to the function). This is backward-chaining via a known function.

4 step app Premises: ev (: $lhs (-> $a $r)) and ev (: $rhs $a) Effect: ev (: (@ $lhs $rhs) $r)

Meaning: if you have a function a → r and an a, you can produce an r, recording the proof term as an
application (@ lhs rhs).

5 exec zealous (the strategy) Premises:
• ((step $x) $p0 $t0) a step (its name and its prem/effect lists)
• (exec zealous $p1 $t1) continue running zealous on the rest Effects:
• (exec $x $p0 $t0) schedule execution of that concrete step
• (exec zealous $p1 $t1) keep the rest of the agenda

Meaning: a driver that repeatedly picks available steps and runs them, keeping the strategy itself in
the queue. It’s a “keep applying steps greedily” scheduler.

How it runs in this program

• load_all_sexpr parses and indexes these rules and the KB/goal facts.
• metta_calculus looks for exec … triples (strategy, program-list, todo-list) and applies the above
rules to transform the state, deriving new ev/goal items, until it runs out of steps or hits the
budget (47 here).
• The KB you load is:
• kb (: a A)
• kb (: ab (R A B))
• kb (: bc (R B C))
• kb (: MP (-> (R $p $q) (-> $p $q))) and the initial goal is goal (: $proof C).

From these, the calculus derives a proof of C:

• base gives ev (: a A), ev (: ab (R A B)), ev (: bc (R B C)), and ev of MP (polymorphic).
• app specializes and applies MP twice:
• ev (: (@ MP bc) (-> B C)) from MP and bc
• ev (: (@ MP ab) (-> A B)) from MP and ab
• ev (: (@ (@ MP ab) a) B) apply the second to a
• ev (: (@ (@ MP bc) (@ (@ MP ab) a)) C) apply the first to that B
• rev/app/abs guide the backward/forward chaining as needed.

Finally, dump_sexpr searches for ev (: $ C) and prints just the proof term ($). You should see a term
like: (@ (@ MP bc) (@ (@ MP ab) a)) which is exactly the composed proof of C from the KB via two uses of
MP.
56 changes: 56 additions & 0 deletions kernel/src/gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
def generate_abs(n):
if n == 1:
args_str = '$arg'
goals = '(goal $arg)'
else:
args_list = [f'$arg{i}' for i in range(1, n+1)]
args_str = ' '.join(args_list)
goals = ' '.join(f'(goal {arg})' for arg in args_list)
kb = f'(kb ((({args_str}) $dep) -> $ccls))'
left = f'(, (goal $ccls) {kb} )'
ev = f'(ev ((({args_str}) $dep) -> $ccls))'
right = f'(, {ev} {goals} )'
return f'((step abs{n})\n {left}\n {right} )'

def generate_app(a, d):
arg_list = [f'$arg{i}' for i in range(1, a+1)]
args_str = ' '.join(arg_list)
ev_args = ' '.join(f'(ev {arg})' for arg in arg_list)
if d == 0:
dep_struct = 'Empty'
right = '(ev $r)'
right_goals = ''
else:
if d == 1:
darg_list = ['$deparg1']
else:
darg_list = [f'$darg{i}' for i in range(1, d+1)]
dargs_str = ' '.join(darg_list)
dep_struct = f'(({dargs_str}) $dep)'
right = f'(ev ( {dep_struct} -> $r ))'
right_goals = ' ' + ' '.join(f'(goal {darg})' for darg in darg_list)
left_ev = f'(ev ((({args_str}) ({dep_struct})) -> $r))'
left = f'(, {left_ev} {ev_args})'
right_full = f'(, {right}{right_goals} )'
return f'((step app{a}_{d})\n {left}\n {right_full} )'

# Examples: modify or add calls here to generate others
print(generate_abs(3))
print('\n')
print(generate_app(3,0))
print('\n')
print(generate_app(3,1))
print('\n')
print(generate_app(3,2))
print('\n')
print(generate_app(3,3))
print('\n')
print(generate_abs(4))
print('\n')
print(generate_app(4,0))
print('\n')
print(generate_app(4,1))
print('\n')
print(generate_app(4,2))
print('\n')
print(generate_app(4,3))
Loading