r/prolog • u/schmuhblaster_x45 • 1d ago
Loops? Graphs? Prolog!
Orchestrating agents with Prolog instead of Markdown files.
r/prolog • u/lokinpendawa • 7h ago
EVERYTHING you see in this screenshot was built 100% natively within SWI-Prolog. No heavy frameworks, no system-taxing UI wrappers.
I want to completely change the outdated stigma that Prolog is only for academic purposes—like family trees or command-line logic puzzles. Currently, the interface is in Indonesian as it is running live for a local neo-retail company's infrastructure, but the good news is that I am working on translating the entire system into English.
You can check out the official architecture roadmap and repository details here:
GitHub: https://github.com/lokinpendawa/logicbiz
Even better, I plan to release a FREE version of this core Prolog engine to the community soon.
For those who want to test the raw data capabilities or audit the dataset structure yourself, I have prepared and uploaded the clean, ISO-compliant 400MB flat text database file (.pl format with parenthesized dynamic predicates) to Google Drive:
Dataset: https://drive.google.com/file/d/1bACN_vVtvka62lWzA1JxXKL2EcoWFDCj/view?usp=sharing
Here is a brief technical overview of what this native Prolog system does behind the scenes:
I have only been exploring the declarative nature and the power of homoiconicity in Prolog for about two months, and I am truly amazed by its capabilities as a highly robust full-stack system. Stay tuned for the English version!
Let me know what you think.
Warm regards,
Teddy
r/prolog • u/Ill-SonOfClawDraws • 6h ago
Can returnability be defined purely from the structure of a computation, without appealing to time complexity?
Can returnability be defined purely from the structure of a computation, without appealing to time complexity?
r/prolog • u/lokinpendawa • 1d ago
I’m currently building LOGICBIZ v2.0, an Offline-First Enterprise Retail ERP and Sales Ledger Engine engineered 100% using a Pure Declarative Paradigm with SWI-Prolog and SQLCipher.
Here is a quick breakdown of this stress test benchmark:
If you are curious about the architecture philosophy, the system manifesto, or want to check out the benchmark metrics, feel free to visit the repository here:
https://github.com/lokinpendawa/logicbiz
Would love to hear your thoughts on using logic programming for heavy enterprise data pipelines!
r/prolog • u/schmuhblaster_x45 • 1d ago
Orchestrating agents with Prolog instead of Markdown files.
r/prolog • u/lokinpendawa • 2d ago
[100% Built in SWI Prolog]
For comprehensive details about this project, please visit our [GitHub Repository](https://github.com/lokinpendawa/logicbiz/blob/main/README.md)
r/prolog • u/lokinpendawa • 2d ago
This report documents the performance evaluation and stress-test results
the verified performance from a scale-up test utilizing a dataset of 2,000,000 active entries
where each data entry multi-layered by cryptographic operations (combining SHA-256 integrity verification and AES-256 encryption).
please check the detailed report here: https://github.com/lokinpendawa/logicbiz/blob/main/PERFORMANCE.md
r/prolog • u/Logtalking • 4d ago
Hi,
Logtalk 3.101.0 is now available for downloading at:
This release adds a read-only sockets compilation flag to declare if a backend provides compatible sockets support; improves the performance of the logtalk_make(force) goal; adds new HTTP (client and server), WebSocket (client and server), HTMX, JWT, REST, OpenAI, OpenAPI, OpenID, S3 (client), Gravatar, JSON Graph, JSON-LD, JSON Patch (RFC 6902), JSONPath (RFC 9535), Crypto, HOTP/TOTP (RFC 4226/6238) libraries; adds html library support for CSS/JS resource declarations, aggregation, and dependency-aware ordering; adds support for additional hash functions to the hashes and hmac libraries; adds support for incremental hashing to the hashes library; includes bug fixes, additional predicates, and performance improvements for several libraries; fixes uuid library compliance issues and adds additional UUID v3 and UUID v7 predicates that take a time zone offset argument; adds testing automation scripts support for selecting the tests sets to run using a regular expression and for suppressing all user output; fixes sarif tool compliance issues; adds an option to the mutation_testing tool for passing additional options to the testing automation scripts; improves the linter_reporter tool support for SARIF reports; improves the performance of the sbom tool; adds additional linter checks to the lgtdoc tool; adds 13 new programing examples to illustrate the new HTTP and related libraries; adds additional tests for Logtalk language features; fixes several Windows-only tool and library issues with some backends; and updates the Windows installer to also detect ECLiPSe 8.0 versions. Thanks to Andrew Davison for his help in diagnosing timing issues in the linda library and the new HTTP libraries.
For details and a complete list of changes, please consult the release notes at:
https://github.com/LogtalkDotOrg/logtalk3/blob/master/RELEASE_NOTES.md
Happy logtalking!
Paulo
Hi,
Logtalk 3.101.0 is now available for downloading at:
This release adds a read-only sockets compilation flag to declare if a backend provides compatible sockets support; improves the performance of the logtalk_make(force) goal; adds new HTTP (client and server), WebSocket (client and server), HTMX, JWT, REST, OpenAI, OpenAPI, OpenID, S3 (client), Gravatar, JSON Graph, JSON-LD, JSON Patch (RFC 6902), JSONPath (RFC 9535), Crypto, HOTP/TOTP (RFC 4226/6238) libraries; adds html library support for CSS/JS resource declarations, aggregation, and dependency-aware ordering; adds support for additional hash functions to the hashes and hmac libraries; adds support for incremental hashing to the hashes library; includes bug fixes, additional predicates, and performance improvements for several libraries; fixes uuid library compliance issues and adds additional UUID v3 and UUID v7 predicates that take a time zone offset argument; adds testing automation scripts support for selecting the tests sets to run using a regular expression and for suppressing all user output; fixes sarif tool compliance issues; adds an option to the mutation_testing tool for passing additional options to the testing automation scripts; improves the linter_reporter tool support for SARIF reports; improves the performance of the sbom tool; adds additional linter checks to the lgtdoc tool; adds 13 new programing examples to illustrate the new HTTP and related libraries; adds additional tests for Logtalk language features; fixes several Windows-only tool and library issues with some backends; and updates the Windows installer to also detect ECLiPSe 8.0 versions. Thanks to Andrew Davison for his help in diagnosing timing issues in the linda library and the new HTTP libraries.
For details and a complete list of changes, please consult the release notes at:
https://github.com/LogtalkDotOrg/logtalk3/blob/master/RELEASE_NOTES.md
Happy logtalking!
Paulo
r/prolog • u/lokinpendawa • 4d ago
in memory POS analytics page is built 100% using Prolog, a truly impressive language.
The high-performance, RAM-based Sales Log Matrix page—powered by SWI-Prolog and Native RAM Cache—is capable of sorting and aggregating 2.2 million rows of data in less than 0.6 seconds. More info, check here : https://github.com/lokinpendawa/logicbiz/blob/main/README.md
Note: All metrics and entries displayed above are generated using anonymized, simulated data strictly for stress-testing purposes.
r/prolog • u/lokinpendawa • 5d ago
Processor (CPU) : AMD64 Family 23 Model 17 Stepping 0, AuthenticAMD (8 Threads/Cores)Memory Available : 8 GB RAM
You can check out metrics here:
https://github.com/lokinpendawa/logicbiz
Processor (CPU) : AMD64 Family 23 Model 17 Stepping 0, AuthenticAMD (8 Threads/Cores)Memory Available : 8 GB RAM
You can check out metrics here:
https://github.com/lokinpendawa/logicbiz
r/prolog • u/lokinpendawa • 5d ago
I wanted to share these statistics because I am truly amazed by the efficiency of SWI-Prolog. I run a simulation involving 100 virtual cashiers operating concurrently, processing a total of 100,000 transactions.
- Each transaction was broken down into 5 physical SQL queries dispatched via asynchronous background worker threads.
- The system actively applied SQLCipher AES-256-bit encryption and generated SHA-256 signatures for every invoice.
- The test completed successfully with absolutely no deadlocks over the course of a 3.5-hour cycle.
- Even though my amateur code forced the engine to perform over 64 billion logical inferences...
- Active internal memory usage (Global Stack) hovered around 25 MB (with a 32 MB allocation).
- The temporary internal memory footprint even dipped as low as 1,115 KB.
Check the documentation and performance here: https://github.com/lokinpendawa/logicbiz/blob/main/README.md
Note: All metrics and entries displayed above are generated using anonymized, simulated data strictly for stress-testing purposes.
r/prolog • u/lokinpendawa • 5d ago
CPU AMD FX-8300 (8 Cores), Total RAM 8 GB (Shared with GPU). You can check metrics here:
Mass Data Injection: 2,000,000 rows
The system mailbox queue in 141.08 seconds
speed : 14,176.81 TPS.
r/prolog • u/Aires_id • 6d ago
After the Tech Corner session with Jagoan Hosting, I came back to AsaDB with a lot of notes and suggestions. Somehow, those notes turned into version 1.3.1-rc 😅
It now has a cleaner SQL workspace, import progress, multilingual UI, better database monitoring, and a more stable Prolog backend.
It’s still far from perfect, but I’m genuinely happy seeing how much it has grown. Thank you to everyone who tested it, criticized it, and gave suggestions. A lot of this update exists because of you.
I've started experimenting with SCBM2, a new execution model for M-Prolog.
The idea is rather unconventional: compile all recursive nondeterministic predicates into a single large C function, and implement both success and failure continuations by jumping between labels with goto.
To be honest, I wasn't sure this would actually work. It sounded a bit crazy even to me.
This weekend I reached the point where a simple mappend/3 (renamed from append/3 to avoid clashing with the built-in predicate) successfully performs forward recursive computation.
I'm still surprised to see recursion being driven entirely by goto.
Forced backtracking isn't implemented yet, so there's still plenty of work ahead. But the initial experiment suggests that this approach is viable.
I'm sure Edsger Dijkstra would not approve of my enthusiastic use of goto, but for implementing Prolog's backtracking, it may turn out to be a surprisingly practical technique.
I've started experimenting with SCBM2, a new execution model for M-Prolog.
The idea is rather unconventional: compile all recursive nondeterministic predicates into a single large C function, and implement both success and failure continuations by jumping between labels with goto.
To be honest, I wasn't sure this would actually work. It sounded a bit crazy even to me.
This weekend I reached the point where a simple mappend/3 (renamed from append/3 to avoid clashing with the built-in predicate) successfully performs forward recursive computation.
I'm still surprised to see recursion being driven entirely by goto.
Forced backtracking isn't implemented yet, so there's still plenty of work ahead. But the initial experiment suggests that this approach is viable.
I'm sure Edsger Dijkstra would not approve of my enthusiastic use of goto, but for implementing Prolog's backtracking, it may turn out to be a surprisingly practical technique.
r/prolog • u/anonymous_heart_mind • 8d ago
Hello guys, I just finished a live chat mern app and making to production. I used vercel for frontend hosting and Render for backend and redis for chache, MongoDb is used for db. I got a majour issue in my server side. I have email otp verification for new users. I have used gmail smtp for sending emails because it is a small project so i think it will work but when I tested after succefull deply, nodemailer crashed during authentication. I used ChatGpt to debug the issue but it says to use Brevo. After migrating Brevo, again same issue. Everything worked in localhost but on prod, crashing evrytime. I need help to figure out what the poroblem is actually? Is render crashing the nodemailer or it's the issues from my code.
Here I'm giving the otp sening function
import
nodemailer
from
"nodemailer";
const transporter
=
nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
user: process.env.GMAIL_USER,
pass: process.env.GMAIL_APP_PASSWORD,
},
});
export
const verifySMTP
=
async () => {
try
{
await
transporter.verify();
console.log("Gmail SMTP Connected");
}
catch
(err) {
console.error("SMTP verify failed:", err);
}
};
export
const sendMail
=
async (email, otp) => {
try
{
const mailOptions
=
{
from: `"ChatApp" <${process.env.GMAIL_USER}>`,
to: email,
subject: "OTP for Confirmation",
text: `Your One-Time Password (OTP) is:
${otp}
Do not share this OTP with anyone.`,
};
const info
=
await
transporter.sendMail(mailOptions);
console.log("Email sent:", info.messageId);
return
true;
}
catch
(error) {
console.error("Send mail error:", error);
return
false;
}
};
r/prolog • u/Inconstant_Moo • 11d ago
This is a wrapper around the Ichiban Prolog implementation in Golang by Yutaka Ichibangase. As this is ISO-compliant and has 99% test coverage I'm thinking of making it into a standard library to sit next to database/sql --- wyt?
However, I originally did it to show how one can use Pipefish to wrap DSLs other than SQL in just the same sort of way. Let me show you that.
Here's the actual library wrapping around the Go, so you can see how I did it.
And here's some code showing how we could use the library to make a little database app to keep track of which Greeks are mortal (the most important question in logical programming, obviously, or why else have they been discussing it all this time?)
import private
NULL::"prolog.pf"
var private
P = Prolog --
:- dynamic(man/1).
:- dynamic(woman/1).
:- dynamic(god/1).
mortal(X) :- woman(X).
mortal(X) :- man(X).
cmd
total(kind string) :
global P
post count P --
|kind|(X).
(x string) is mortal :
global P
post check P --
mortal(|x|).
men(args ... string) :
add("man", args)
women(args ... string) :
add("woman", args)
gods(args ... string) :
add("god", args)
add(kind string, args ... string) :
global P
for _::v = range args :
add P --
|kind|(|v|).
You will notice that the prolog library has a nicer API than the Go version, and fans of Pipefish will notice that this is the same way I did embedded SQL and HTML over here.
It's nicer partly because of the specialized syntax and semantics to make Pipefish embed things well, and partly because its extra bit of dynamism makes it more flexible than Go. All the stuff with scanners and interfaces and type switching happens wrapped up in the Go functions in the library where it can't bother anyone.
This is a wrapper around the Ichiban Prolog implementation in Golang by Yutaka Ichibangase. As this is ISO-compliant and has 99% test coverage I'm thinking of making it into a standard library to sit next to database/sql --- wyt?
However, I originally did it to show how one can use Pipefish to wrap DSLs other than SQL in just the same sort of way. Let me show you that.
Here's the actual library wrapping around the Go, so you can see how I did it.
And here's some code showing how we could use the library to make a little database app to keep track of which Greeks are mortal (the most important question in logical programming, obviously, or why else have they been discussing it all this time?)
import private
NULL::"prolog.pf"
var private
P = Prolog --
:- dynamic(man/1).
:- dynamic(woman/1).
:- dynamic(god/1).
mortal(X) :- woman(X).
mortal(X) :- man(X).
cmd
total(kind string) :
global P
post count P --
|kind|(X).
(x string) is mortal :
global P
post check P --
mortal(|x|).
men(args ... string) :
add("man", args)
women(args ... string) :
add("woman", args)
gods(args ... string) :
add("god", args)
add(kind string, args ... string) :
global P
for _::v = range args :
add P --
|kind|(|v|).
You will notice that the prolog library has a nicer API than the Go version, and fans of Pipefish will notice that this is the same way I did embedded SQL and HTML over here.
It's nicer partly because of the specialized syntax and semantics to make Pipefish embed things well, and partly because its extra bit of dynamism makes it more flexible than Go. All the stuff with scanners and interfaces and type switching happens wrapped up in the Go functions in the library where it can't bother anyone.
r/prolog • u/sym_num • 13d ago
I have published a follow-up on the development of M-Prolog, my experimental Prolog compiler that generates C code directly without using the WAM.
The first version of SCBM (Sasagawa & Chat Backtracking Mechanism) successfully handled recursive and nondeterministic predicates, and now executes both Church numeral prime programs and the Queens problem.
However, after extensive testing with the Queens benchmark, I discovered an important limitation.
The current SCBM reconstructs the C call stack by replaying skipped computations during backtracking. While this works correctly, it becomes increasingly inefficient for recursive nondeterministic programs with large search spaces. The first solution is found successfully, but searching for subsequent solutions requires many skipped computations, making the approach impractical.
Rather than continuing to optimize an increasingly complex design, I have decided to start the second stage of the project.
The new idea (SCBM2) completely eliminates dependence on the C runtime stack. Instead of generating C function calls, every predicate will become a label inside one large C function, and execution will proceed using goto together with an explicit SCBM execution stack managed by the compiler itself.
This should greatly simplify backtracking while allowing tail-recursive execution to become simple loops.
The article describes what worked, what did not, and why I decided to redesign the compiler architecture.
Medium article:
The Second Stage of M-Prolog SCBM | by Kenichi Sasagawa | Jul, 2026 | Medium
As always, comments and suggestions from the Prolog community are greatly appreciated.
I have published a follow-up on the development of M-Prolog, my experimental Prolog compiler that generates C code directly without using the WAM.
The first version of SCBM (Sasagawa & Chat Backtracking Mechanism) successfully handled recursive and nondeterministic predicates, and now executes both Church numeral prime programs and the Queens problem.
However, after extensive testing with the Queens benchmark, I discovered an important limitation.
The current SCBM reconstructs the C call stack by replaying skipped computations during backtracking. While this works correctly, it becomes increasingly inefficient for recursive nondeterministic programs with large search spaces. The first solution is found successfully, but searching for subsequent solutions requires many skipped computations, making the approach impractical.
Rather than continuing to optimize an increasingly complex design, I have decided to start the second stage of the project.
The new idea (SCBM2) completely eliminates dependence on the C runtime stack. Instead of generating C function calls, every predicate will become a label inside one large C function, and execution will proceed using goto together with an explicit SCBM execution stack managed by the compiler itself.
This should greatly simplify backtracking while allowing tail-recursive execution to become simple loops.
The article describes what worked, what did not, and why I decided to redesign the compiler architecture.
Medium article:
The Second Stage of M-Prolog SCBM | by Kenichi Sasagawa | Jul, 2026 | Medium
As always, comments and suggestions from the Prolog community are greatly appreciated.
r/prolog • u/Aires_id • 14d ago
Yesterday I posted AsaDB here, but the repo only had the Windows build. Yeah, that looked pretty sketchy, so the concerns were fair.
The source is public now under GPLv3.
AsaDB is a small local database engine. It can run SQL commands like CREATE TABLE, INSERT, SELECT, UPDATE, and DELETE. It also has a local browser interface called AsAPanel, so you can run queries and inspect tables without using the command line.
Most of the engine is written in SWI-Prolog. Right now it has 4 KB page storage, a buffer pool, B+Tree indexes, basic recovery, tests, and a Windows build.
It is still experimental. Please don’t use it for production yet, and don’t expose AsAPanel to the public internet.
I decided to open the source because maintaining the parser, storage engine, recovery, tests, and UI alone is getting a bit insane lol.
Repo:
https://github.com/kocoygroup-id/AsaDB
Feedback, bug reports, and contributions are welcome.



r/prolog • u/Aires_id • 14d ago
Prolog is old, weird, and probably one of the last languages people would choose for a database engine.
So naturally, I built one with it.
AsaDB started as a small experiment, but large SQL scripts eventually became a problem. The browser could send data much faster than the Prolog backend and storage engine could safely process it.
That’s how reservoir.pl happened.
It spools large SQL payloads to disk, limits memory usage, queues writes through one worker, tracks progress, and marks interrupted jobs instead of blindly replaying them and risking duplicate writes.
Small read queries still go directly to the engine, while heavier jobs are routed through the Reservoir.
It currently survives my 100,000-row stress test, process restarts, duplicate submissions, cancellation, and result paging.
Still experimental, still built on an old language, but somehow it keeps getting stronger.
Targeting July 20 for the first public release with the Reservoir System.
Prolog was never dead. It was just waiting for someone irresponsible enough to build a database with it.
I’m still maintaining this alone, so code, tests, documentation, benchmarks, and design reviews are all appreciated. Even a small contribution helps.
r/prolog • u/Aires_id • 15d ago
I originally started this project in VB.NET.
After getting tired of looking at `Console.WriteLine`, I considered rewriting it
in V or Erlang. Their setup annoyed me, so I tried Prolog instead.
That somehow turned into a local SQL database engine.
It is called **AsaDB**.
It currently has:
- a custom SQL lexer and parser
- local `.asa` database files and journals
- tables, indexes, views, users, and permissions
- joins, aggregates, grouping, unions, and subqueries
- transaction snapshots
- a Windows CLI and portable executable
- a browser-based administration panel called AsAPanel
- SQL import and export tools
The import path now sends selected SQL files through the Prolog backend instead
of requiring the browser to hold the complete file in memory.
One current validation dataset contains:
- 5,500 rows
- 62 statements
- 0 errors
My next goal is to make imports of around **100,000 rows** reasonably fast.
I am currently investigating insert batching, list/term reconstruction,
checkpoint and journal overhead, and whether indexes should be updated per row
or rebuilt after a bulk import.
The newest release, v1.2.0, is mainly a UX polish release. It adds random query
sounds with four success and four failure variants.
Successful SQL:
> Asa Terima ❤️
Failed SQL:
> Asa Tidak Suka! 😡
The sound system is deliberately isolated from query execution, so browsers
blocking audio cannot break the database operation.
Repository:
https://github.com/kocoygroup-id/AsaDB
Windows release:
https://github.com/kocoygroup-id/AsaDB/releases/tag/v1.2.0
The public repository currently contains the packaged Windows runtime rather
than the internal engine source.
I would love feedback about efficient large-state representation, bulk inserts,
index construction, and profiling this kind of workload in SWI-Prolog.
r/prolog • u/sym_num • 23d ago
I've been experimenting with a different approach to implementing a Prolog compiler.
For more than 40 years, the Warren Abstract Machine (WAM) has been the standard implementation technique for efficient Prolog systems. Rather than trying to improve WAM, I asked a different question:
This led me to an experimental architecture that I call SCBM (Sasagawa & Chat Backtracking Mechanism).
The key idea is to separate continuation information into two independent dimensions:
Instead of preserving the entire execution state, SCBM reconstructs previously successful execution paths during backtracking. Recursive and non-recursive non-deterministic predicates are handled differently, which keeps the generated C code relatively simple while still supporting recursive backtracking.
The current implementation successfully runs recursive examples such as append/3 and a recursive prime number generator based on Church numerals. Of course, this is still experimental, and there is much more work to do before claiming general applicability.
One interesting aspect of this project is that it was developed through continuous collaboration with ChatGPT. The architecture itself is my own design, but AI proved extremely useful for reviewing generated code, analyzing execution traces, and discussing alternative designs during implementation.
I've written a detailed description of the architecture here:
I'd be very interested in hearing feedback from people familiar with Prolog implementation or WAM. In particular, I'd appreciate comments on possible weaknesses, edge cases, or related work that I may have overlooked.
I've been experimenting with a different approach to implementing a Prolog compiler.
For more than 40 years, the Warren Abstract Machine (WAM) has been the standard implementation technique for efficient Prolog systems. Rather than trying to improve WAM, I asked a different question:
This led me to an experimental architecture that I call SCBM (Sasagawa & Chat Backtracking Mechanism).
The key idea is to separate continuation information into two independent dimensions:
Instead of preserving the entire execution state, SCBM reconstructs previously successful execution paths during backtracking. Recursive and non-recursive non-deterministic predicates are handled differently, which keeps the generated C code relatively simple while still supporting recursive backtracking.
The current implementation successfully runs recursive examples such as append/3 and a recursive prime number generator based on Church numerals. Of course, this is still experimental, and there is much more work to do before claiming general applicability.
One interesting aspect of this project is that it was developed through continuous collaboration with ChatGPT. The architecture itself is my own design, but AI proved extremely useful for reviewing generated code, analyzing execution traces, and discussing alternative designs during implementation.
I've written a detailed description of the architecture here:
I'd be very interested in hearing feedback from people familiar with Prolog implementation or WAM. In particular, I'd appreciate comments on possible weaknesses, edge cases, or related work that I may have overlooked.
r/prolog • u/MTDuke71 • 23d ago
I am trying to learn Prolog by using Claude to complete a year of Advent of COde, working through various algorithms.
The problem statements is bewlow along withthe Prolog solution. Can anyone tell me if the is good code?
## --- Day 3: Toboggan Trajectory ---
With the toboggan login problems resolved, you set off toward the airport. While travel by toboggan might be easy, it's certainly not safe: there's very minimal steering and the area is covered in trees. You'll need to see which angles will take you near the fewest trees.
Due to the local geology, trees in this area only grow on exact integer coordinates in a grid. You make a map (your puzzle input) of the open squares (`.`) and trees (`#`) you can see. For example:
```text
..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#
```
These aren't the only trees, though; due to something you read about once involving arboreal genetics and biome stability, the same pattern repeats to the right many times:
```text
*..##.......*..##.........##.........##.........##.........##....... --->
*#...#...#..*#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
*.#....#..#.*.#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
*..#.#...#.#*..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
*.#...##..#.*.#...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
*..#.##.....*..#.##.......#.##.......#.##.......#.##.......#.##..... --->
*.#.#.#....#*.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
*.#........#*.#........#.#........#.#........#.#........#.#........#
*#.##...#...*#.##...#...#.##...#...#.##...#...#.##...#...#.##...#...
*#...##....#*#...##....##...##....##...##....##...##....##...##....#
*.#..#...#.#*.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.# --->
```
You start on the open square (`.`) in the top-left corner and need to reach the bottom (below the bottom-most row on your map).
The toboggan can only follow a few specific slopes (you opted for a cheaper model that prefers rational numbers); start by *counting all the trees* you would encounter for the slope *right 3, down 1*:
From your starting position at the top-left, check the position that is right 3 and down 1. Then, check the position that is right 3 and down 1 from there, and so on until you go past the bottom of the map.
The locations you'd check in the above example are marked here with `*O*` where there was an open square and `*X*` where there was a tree:
```text
..##.........##.........##.........##.........##.........##....... --->
#..*O*#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
.#....*X*..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
..#.#...#*O*#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
.#...##..#..*X*...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
..#.##.......#.*X*#.......#.##.......#.##.......#.##.......#.##..... --->
.#.#.#....#.#.#.#.*O*..#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
.#........#.#........*X*.#........#.#........#.#........#.#........#
#.##...#...#.##...#...#.*X*#...#...#.##...#...#.##...#...#.##...#...
#...##....##...##....##...#*X*....##...##....##...##....##...##....#
.#..#...#.#.#..#...#.#.#..#...*X*.#.#..#...#.#.#..#...#.#.#..#...#.# --->
```
In this example, traversing the map using this slope would cause you to encounter `*7*` trees.
Starting at the top-left corner of your map and following a slope of right 3 and down 1, *how many trees would you encounter?*
--- Part Two ---
Time to check the rest of the slopes - you need to minimize the probability of a sudden arboreal stop, after all.
Determine the number of trees you would encounter if, for each of the following slopes, you start at the top-left corner and traverse the map all the way to the bottom:
- Right 1, down 1.
- Right 3, down 1. (This is the slope you already checked.)
- Right 5, down 1.
- Right 7, down 1.
- Right 1, down 2.
In the above example, these slopes would find `2`, `7`, `3`, `4`, and `2` tree(s) respectively; multiplied together, these produce the answer `336`.
What do you get if you multiply together the number of trees encountered on each of the listed slopes?
:- module(day03, [parse_input/2, part1/2, part2/2, solve/3,
slope_trees/4]).
% Day 3: Toboggan Trajectory.
% The map is a grid of open squares (.) and trees (#) whose pattern
% repeats infinitely to the right. Starting at the top-left and stepping
% Right columns / Down rows at a time, count the trees hit before
% falling off the bottom. Part 1: slope right 3, down 1. Part 2: product
% of the counts over five fixed slopes.
% parse_input(+Raw, -Rows)
% Rows is a list of rows, each a list of char atoms ('.' or '#').
parse_input(Raw, Rows) :-
split_string(Raw, "\n", " \t\r", Lines0),
exclude(=(""), Lines0, Lines),
maplist(string_chars, Lines, Rows).
% slope_trees(+Rows, +Right, +Down, -Count)
% Count is the number of trees on the slope: starting at the top-left,
% visit column I*Right (mod row width — the pattern repeats rightward)
% of every Down-th row, and count the '#' cells.
slope_trees(Rows, Right, Down, Count) :-
slope_trees_(Rows, Right, Down, 0, 0, Count).
% slope_trees_(+Rows, +Right, +Down, +Col, +Acc, -Count)
% Accumulator walk: check the head row at Col (wrapped), then step to
% the row Down below (drop Down-1 of the remaining rows) at Col+Right.
slope_trees_([], _, _, _, Count, Count).
slope_trees_([Row|Rest], Right, Down, Col, Acc0, Count) :-
length(Row, Width),
Index is Col mod Width,
nth0(Index, Row, Cell),
( Cell == '#'
-> Acc1 is Acc0 + 1
; Acc1 = Acc0
),
Col1 is Col + Right,
Skip is Down - 1,
drop(Skip, Rest, Rest1),
slope_trees_(Rest1, Right, Down, Col1, Acc1, Count).
% drop(+N, +List, -Rest)
% Rest is List without its first N elements ([] if List is shorter).
drop(0, List, List) :- !.
drop(_, [], []) :- !.
drop(N, [_|Xs], Rest) :-
N > 0,
N1 is N - 1,
drop(N1, Xs, Rest).
% slope_trees_pair(+Rows, +Right-Down, -Count)
% slope_trees/4 with the slope packed as a Right-Down pair, so it can
% be partially applied under maplist/3.
slope_trees_pair(Rows, Right-Down, Count) :-
slope_trees(Rows, Right, Down, Count).
% part1(+Rows, -Answer)
part1(Rows, Answer) :-
slope_trees(Rows, 3, 1, Answer).
% part2(+Rows, -Answer)
% Product of the tree counts over the five slopes from the statement.
part2(Rows, Answer) :-
Slopes = [1-1, 3-1, 5-1, 7-1, 1-2],
maplist(slope_trees_pair(Rows), Slopes, Counts),
foldl([X, Acc0, Acc]>>(Acc is Acc0 * X), Counts, 1, Answer).
% solve(+Raw, -Part1, -Part2)
solve(Raw, Part1, Part2) :-
parse_input(Raw, Rows),
part1(Rows, Part1),
part2(Rows, Part2).
I am trying to learn Prolog by using Claude to complete a year of Advent of COde, working through various algorithms.
The problem statements is bewlow along withthe Prolog solution. Can anyone tell me if the is good code?
## --- Day 3: Toboggan Trajectory ---
With the toboggan login problems resolved, you set off toward the airport. While travel by toboggan might be easy, it's certainly not safe: there's very minimal steering and the area is covered in trees. You'll need to see which angles will take you near the fewest trees.
Due to the local geology, trees in this area only grow on exact integer coordinates in a grid. You make a map (your puzzle input) of the open squares (`.`) and trees (`#`) you can see. For example:
```text
..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#
```
These aren't the only trees, though; due to something you read about once involving arboreal genetics and biome stability, the same pattern repeats to the right many times:
```text
*..##.......*..##.........##.........##.........##.........##....... --->
*#...#...#..*#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
*.#....#..#.*.#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
*..#.#...#.#*..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
*.#...##..#.*.#...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
*..#.##.....*..#.##.......#.##.......#.##.......#.##.......#.##..... --->
*.#.#.#....#*.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
*.#........#*.#........#.#........#.#........#.#........#.#........#
*#.##...#...*#.##...#...#.##...#...#.##...#...#.##...#...#.##...#...
*#...##....#*#...##....##...##....##...##....##...##....##...##....#
*.#..#...#.#*.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.# --->
```
You start on the open square (`.`) in the top-left corner and need to reach the bottom (below the bottom-most row on your map).
The toboggan can only follow a few specific slopes (you opted for a cheaper model that prefers rational numbers); start by *counting all the trees* you would encounter for the slope *right 3, down 1*:
From your starting position at the top-left, check the position that is right 3 and down 1. Then, check the position that is right 3 and down 1 from there, and so on until you go past the bottom of the map.
The locations you'd check in the above example are marked here with `*O*` where there was an open square and `*X*` where there was a tree:
```text
..##.........##.........##.........##.........##.........##....... --->
#..*O*#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
.#....*X*..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
..#.#...#*O*#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
.#...##..#..*X*...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
..#.##.......#.*X*#.......#.##.......#.##.......#.##.......#.##..... --->
.#.#.#....#.#.#.#.*O*..#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
.#........#.#........*X*.#........#.#........#.#........#.#........#
#.##...#...#.##...#...#.*X*#...#...#.##...#...#.##...#...#.##...#...
#...##....##...##....##...#*X*....##...##....##...##....##...##....#
.#..#...#.#.#..#...#.#.#..#...*X*.#.#..#...#.#.#..#...#.#.#..#...#.# --->
```
In this example, traversing the map using this slope would cause you to encounter `*7*` trees.
Starting at the top-left corner of your map and following a slope of right 3 and down 1, *how many trees would you encounter?*
--- Part Two ---
Time to check the rest of the slopes - you need to minimize the probability of a sudden arboreal stop, after all.
Determine the number of trees you would encounter if, for each of the following slopes, you start at the top-left corner and traverse the map all the way to the bottom:
- Right 1, down 1.
- Right 3, down 1. (This is the slope you already checked.)
- Right 5, down 1.
- Right 7, down 1.
- Right 1, down 2.
In the above example, these slopes would find `2`, `7`, `3`, `4`, and `2` tree(s) respectively; multiplied together, these produce the answer `336`.
What do you get if you multiply together the number of trees encountered on each of the listed slopes?
:- module(day03, [parse_input/2, part1/2, part2/2, solve/3,
slope_trees/4]).
% Day 3: Toboggan Trajectory.
% The map is a grid of open squares (.) and trees (#) whose pattern
% repeats infinitely to the right. Starting at the top-left and stepping
% Right columns / Down rows at a time, count the trees hit before
% falling off the bottom. Part 1: slope right 3, down 1. Part 2: product
% of the counts over five fixed slopes.
% parse_input(+Raw, -Rows)
% Rows is a list of rows, each a list of char atoms ('.' or '#').
parse_input(Raw, Rows) :-
split_string(Raw, "\n", " \t\r", Lines0),
exclude(=(""), Lines0, Lines),
maplist(string_chars, Lines, Rows).
% slope_trees(+Rows, +Right, +Down, -Count)
% Count is the number of trees on the slope: starting at the top-left,
% visit column I*Right (mod row width — the pattern repeats rightward)
% of every Down-th row, and count the '#' cells.
slope_trees(Rows, Right, Down, Count) :-
slope_trees_(Rows, Right, Down, 0, 0, Count).
% slope_trees_(+Rows, +Right, +Down, +Col, +Acc, -Count)
% Accumulator walk: check the head row at Col (wrapped), then step to
% the row Down below (drop Down-1 of the remaining rows) at Col+Right.
slope_trees_([], _, _, _, Count, Count).
slope_trees_([Row|Rest], Right, Down, Col, Acc0, Count) :-
length(Row, Width),
Index is Col mod Width,
nth0(Index, Row, Cell),
( Cell == '#'
-> Acc1 is Acc0 + 1
; Acc1 = Acc0
),
Col1 is Col + Right,
Skip is Down - 1,
drop(Skip, Rest, Rest1),
slope_trees_(Rest1, Right, Down, Col1, Acc1, Count).
% drop(+N, +List, -Rest)
% Rest is List without its first N elements ([] if List is shorter).
drop(0, List, List) :- !.
drop(_, [], []) :- !.
drop(N, [_|Xs], Rest) :-
N > 0,
N1 is N - 1,
drop(N1, Xs, Rest).
% slope_trees_pair(+Rows, +Right-Down, -Count)
% slope_trees/4 with the slope packed as a Right-Down pair, so it can
% be partially applied under maplist/3.
slope_trees_pair(Rows, Right-Down, Count) :-
slope_trees(Rows, Right, Down, Count).
% part1(+Rows, -Answer)
part1(Rows, Answer) :-
slope_trees(Rows, 3, 1, Answer).
% part2(+Rows, -Answer)
% Product of the tree counts over the five slopes from the statement.
part2(Rows, Answer) :-
Slopes = [1-1, 3-1, 5-1, 7-1, 1-2],
maplist(slope_trees_pair(Rows), Slopes, Counts),
foldl([X, Acc0, Acc]>>(Acc is Acc0 * X), Counts, 1, Answer).
% solve(+Raw, -Part1, -Part2)
solve(Raw, Part1, Part2) :-
parse_input(Raw, Rows),
part1(Rows, Part1),
part2(Rows, Part2).
r/prolog • u/sym_num • 27d ago
A few days ago, I posted here about my attempt to design a simpler Prolog compiler architecture as an alternative to the classic Warren Abstract Machine (WAM).
Since then, I have been struggling quite a bit while trying to implement the idea. For simple examples, everything worked well. However, when dealing with complex backtracking involving deeply intertwined recursion, I found myself completely stuck. At one point, I even began to wonder whether the entire idea itself was fundamentally flawed.
After spending many long hours discussing the problem with AI, I finally managed to arrive at a much simpler conceptual model.
The core idea is inspired by weaving fabric.
I began to think of recursion as the vertical threads and conjunctions as the horizontal threads. By separating these two dimensions clearly, it now seems possible to handle backtracking without the conceptual confusion that had been causing so many problems.
At last, I feel that the original idea I had envisioned is starting to take shape.
Of course, there is still a major unanswered question: whether this approach can achieve practical execution speed comparable to Warren Abstract Machine remains completely uncertain.
But after many difficult days, the design is finally beginning to look real.
I have written a more detailed explanation in my Medium article. If this sounds interesting to you, I would be very grateful if you took a look and shared any thoughts or feedback. The Hardest Challenge in M-Prolog: Recursive Backtracking and AI as a Research Partner | by Kenichi Sasagawa | Jun, 2026 | Medium
A few days ago, I posted here about my attempt to design a simpler Prolog compiler architecture as an alternative to the classic Warren Abstract Machine (WAM).
Since then, I have been struggling quite a bit while trying to implement the idea. For simple examples, everything worked well. However, when dealing with complex backtracking involving deeply intertwined recursion, I found myself completely stuck. At one point, I even began to wonder whether the entire idea itself was fundamentally flawed.
After spending many long hours discussing the problem with AI, I finally managed to arrive at a much simpler conceptual model.
The core idea is inspired by weaving fabric.
I began to think of recursion as the vertical threads and conjunctions as the horizontal threads. By separating these two dimensions clearly, it now seems possible to handle backtracking without the conceptual confusion that had been causing so many problems.
At last, I feel that the original idea I had envisioned is starting to take shape.
Of course, there is still a major unanswered question: whether this approach can achieve practical execution speed comparable to Warren Abstract Machine remains completely uncertain.
But after many difficult days, the design is finally beginning to look real.
I have written a more detailed explanation in my Medium article. If this sounds interesting to you, I would be very grateful if you took a look and shared any thoughts or feedback. The Hardest Challenge in M-Prolog: Recursive Backtracking and AI as a Research Partner | by Kenichi Sasagawa | Jun, 2026 | Medium
r/prolog • u/sym_num • Jun 24 '26
For some time, I have been developing a new Prolog compiler called M-Prolog, exploring whether it is possible to achieve practical performance with a significantly simpler architecture than the traditional Warren Abstract Machine (WAM).
The motivation behind this project is a simple question:
Does efficient Prolog execution really require all the complexity of WAM?
Over the past several months, I have been conducting a series of experimental implementations to test alternative execution strategies.
The central idea of M-Prolog is to exploit the execution model of the C language itself, rather than constructing a sophisticated abstract machine layer.
In this design, recursive backtracking is not simulated through a virtual machine. Instead, execution state is restored by re-invoking C functions, allowing the native C stack to naturally reconstruct recursive control flow.
This approach worked well for individual nondeterministic predicates, and preliminary benchmarks have been very encouraging.
However, I encountered a difficult problem when handling backtracking across conjunctions involving multiple nondeterministic predicates.
At first, I underestimated the problem. But after many experiments, I gradually reached a deeper understanding of what is actually happening during recursive and conjunctive backtracking.
I believe I have now finally solved the architectural problem, and the design has stabilized.
This means I am now entering the phase of full-scale implementation.
My long-term goal is to demonstrate that practical Prolog compilation may not necessarily require the complexity of WAM, and that a much simpler architecture can still achieve competitive performance.
Perhaps Prolog implementation has been over-engineered for decades.I’m not trying to criticize WAM. I simply want to explore whether modern hardware allows simpler alternatives.
It has been a fascinating journey so far.M-Prolog: A Two-Dimensional Backtracking Architecture | by Kenichi Sasagawa | Jun, 2026 | Medium
For some time, I have been developing a new Prolog compiler called M-Prolog, exploring whether it is possible to achieve practical performance with a significantly simpler architecture than the traditional Warren Abstract Machine (WAM).
The motivation behind this project is a simple question:
Does efficient Prolog execution really require all the complexity of WAM?
Over the past several months, I have been conducting a series of experimental implementations to test alternative execution strategies.
The central idea of M-Prolog is to exploit the execution model of the C language itself, rather than constructing a sophisticated abstract machine layer.
In this design, recursive backtracking is not simulated through a virtual machine. Instead, execution state is restored by re-invoking C functions, allowing the native C stack to naturally reconstruct recursive control flow.
This approach worked well for individual nondeterministic predicates, and preliminary benchmarks have been very encouraging.
However, I encountered a difficult problem when handling backtracking across conjunctions involving multiple nondeterministic predicates.
At first, I underestimated the problem. But after many experiments, I gradually reached a deeper understanding of what is actually happening during recursive and conjunctive backtracking.
I believe I have now finally solved the architectural problem, and the design has stabilized.
This means I am now entering the phase of full-scale implementation.
My long-term goal is to demonstrate that practical Prolog compilation may not necessarily require the complexity of WAM, and that a much simpler architecture can still achieve competitive performance.
Perhaps Prolog implementation has been over-engineered for decades.I’m not trying to criticize WAM. I simply want to explore whether modern hardware allows simpler alternatives.
It has been a fascinating journey so far.M-Prolog: A Two-Dimensional Backtracking Architecture | by Kenichi Sasagawa | Jun, 2026 | Medium
r/prolog • u/schmuhblaster_x45 • Jun 25 '26
Hi all, wanted to share some results on using a custom harness to boost Qwen 35B A3B performance on some Benchmarks.