6 ms·
Prolog Basics Explained with Pokémon
- Modified3019 6mo agoWas initially nonplussed, but toward the end I realized the choice of pokemon for an example actually works out well for showing how prologue can solve problems. I’m now a bit curious about trying it out somewhere.
- gobdovan 6mo agoAll examples shown in the article can be ran with Datalog too (with stratified negation and arithmetic comparison), which has a clearer execution model and looks almost identical to Prolog. Prolog underneath is doing backtracking, while Datalog is finding a least fixed point of derived relations where iterating on data won't produce more relations, and is akind to SQL (but usually stronger because of recursion).
- ModernMech 6mo agoImportantly, Datalog is not Turing-complete though.
- gobdovan 6mo agoExactly :) It is terminating due to the LFP semantics I was pointing out, it's more akin to SQL than to Prolog. The article doesn't even show the usage of the Prolog cut (`!`). And yet Prolog can express all examples in the article. For these kinds of problems, giving up TC is mostly a feature. And if you need more expressiveness, there's a lot of practical Datalog-ish systems that can recover Turing completeness (Flix, Formulog, parts of Souffle), while still being saner than SWI Prolog and co. for this type of work, as you generally don't have to care about atom order or search order in the same way. They act so much more predictably.
- AlotOfReading 6mo agoYou can get Turing completeness by wrapping your datalog query in a while loop, so that's not particularly restrictive.
- ModernMech 6mo agoIn the case of Datalog, it not being Turing-complete is usually seen as a feature rather than restrictive.
- Dylan16807 6mo agoYou can get Turing completeness by wrapping basically any math or logic system in a while loop, even arithmetic. So that doesn't tell us much about the restrictiveness of the overall system since I'd call "you can only use arithmetic" pretty damn restrictive.
- baq 6mo agoIt’s surprisingly hard to design a useful language which isn’t Turing-complete, so it should be seen as a compliment, not a problem to fix
- YeGoblynQueenne 5mo agoAhem. "Prolog underneath" is doing SLD-Resolution implemented as a Depth-First Search with backtracking. Saying it's "doing backtracking" is really fudging quite a bit. Datalog, instead, is "underneath" implementing a TP-Operator, a procedure that finds the fix-point of a Datalog program which happens to be the same as its Least Herbrand Model, which is what SLD-Resolution also finds, except that SLD-Resolution allows functions and does not guarantee termination, like Datalog does. The big advantage of a TP Operator is the termination guarantees and it can be implemented so that it's efficient, but it's still limited, and the fact that there are many different flavours of Datalog (with or without stratified negation, arithmetic, lists etc) is testament to the difficulty of improving on Prolog's efficiency without breaking its soundness or completeness. Or, like I always say, "sound, complete, efficient: choose two".
- gobdovan 5mo agoBy the same logic, would you say that the fact that there's only one mainstream Rust is testament to the simplicity of implementing a macro-heavy, borrow checked language without breaking safety, performance and expressiveness?
- YeGoblynQueenne 5mo agoI... don't really have an opinion on Rust. I have no idea, honest. Mostly what I mean above is that Prolog is a hard balancing act, specifically balancing efficient execution with the practicalities of programming (e.g. lists, database asserts/retracts, I/O etc) and the theoretical underpinnings of Horn logic and SLD-Resolution. There's a lot of stuff that went into Prolog and its development process is quite distinct to any other language I'm aware of, where there wasn't like a central committee or an enlightened dictator, or a small band of hard-headed academics (...Haskell...) and so on, but instead there was a decades-long academic research process of going from First-Order Logic to Herbrand semantics, to definite logic, to Resolution, to Linear Resolution, to Linear Resolution with a Selection Rule, to Linear Resolution with a Selection Rule restricted to Definite clauses, to Negation-As-Failure under a Closed World Assumption, and finally to a language with an automated theorem prover as an interpreter and a clunky mockery of FOL syntax and terminology that isn't even complete (despite Resolution being complete); a process with no centralised structure instead split across multiple acadmics in several universities in the UK, in France, and in Japan. Another way to see Prolog is that it's the result of a very peculiar academic process that is hard to replicate and that yielded a result that is difficult to outdo, with all its compromises; because of its compromises. Because its particular compromises were made to solve hard problems and were arrived at after a long, collaborative process that won't be easily outdone. Not that attempts haven't been made. For example, in logic programming circles Prolog is now considered a little bit quaint, even outdated. Most of the activity has shifted to Answer Set Programming (ASP). And that makes sense, Prolog is old news. ASP is the new kid on the block, it's only 30 years old! And like normal programming languages it was designed by a couple of people before being adopted by a wider community. I just really don't know how any of that maps to Rust.
- tannhaeuser 6mo agoProlog is actually a perfect fit for all kinds of adventure, role playing, strategy, and classic board/card games, with clauses representing game rules and facts representing the game state and universe in the most natural way. Simple general-purpose opponents can be coded using just recursive backtracking search, while more advanced ones (supporting moves that need to destructively change state) can still be conveniently modelled by reifying facts and thereby enable backtracking over assert/retract-like Prolog DB modifications, as used in discrete combinatorial planners [1]. [1]: https://quantumprolog.sgml.net/container-planning-demo/part1.html#finding-loading-plans-with-multiple-stops https://quantumprolog.sgml.net/container-planning-demo/part1...
- satvikpendem 6mo agoNonplussed like initially surprised? It does not mean bored or nonchalant which many people seem to think, probably due to the non- prefix.
- Modified3019 6mo agoInteresting, it seems I learned/am using a modern American mutated version of the word. https://www.broadlearners.com/t/understanding-the-meaning-of-nonplussed-and-its-confusion/3418 https://www.broadlearners.com/t/understanding-the-meaning-of... https://www.merriam-webster.com/grammar/whole-nother https://www.merriam-webster.com/grammar/whole-nother https://old.reddit.com/r/etymology/comments/13s19j0/wtf_happened_to_plussednonplussed/jlnk4iw/?context=10000 https://old.reddit.com/r/etymology/comments/13s19j0/wtf_happ... In my case, I was using it as almost a blend of the two meanings, something mostly meaning “unimpressed”, with a touch of “and a bit perplexed why such effort is going into this”. Basically a shoulder shrug and “okay…?” I now find myself nonplussed, wondering if I should be using the word at all given it seems to have two opposite meanings.
- Almondsetat 6mo agoAre there public tournaments of games like Pokemon where contestants have to compete with eachother using a specific class of algorithms (e.g., logic programming, neural nets, linear programming, etc.)?
- macintux 6mo agoIt continues to be immensely surprising to me that Joe Armstrong was able to write the initial Erlang implementation in Prolog. I wish I’d asked him about getting a copy of the source code.
- Joker_vD 6mo agoWhat does this say about Forth? Not much except that it isn't for me. Take Prolog. I know few things more insulting than having to code in Prolog. Whereas Armstrong developed Erlang in Prolog and liked it much better than reimplementing Erlang in C for speed. I can't imagine how this could be, but this is how it was. People are different. from Yossi Kreinin's "My history with Forth & stack machines" [0]. Some people write APL and enjoy it. Some can't bear Lisp even after 10 years of working with it. [0] https://yosefk.com/blog/my-history-with-forth-stack-machines.html https://yosefk.com/blog/my-history-with-forth-stack-machines...
- triska 6mo agoRegarding distributed systems, I find Torbjörn Lager's recent work on Web Prolog particularly interesting. He recently posted about it here: https://github.com/mthom/scryer-prolog/discussions/3322 https://github.com/mthom/scryer-prolog/discussions/3322 and also in the course of a discussion on various approaches to implement concurrency in Prolog: https://github.com/mthom/scryer-prolog/discussions/3307 https://github.com/mthom/scryer-prolog/discussions/3307
- zombot 6mo agoAre there pokémon with backtracking and unification traits? Those could do real Prolog!
- lagrange77 6mo agoWhen i was in uni, the course teaching Prolog and Lisp was called "Artificial Intelligence for Engineers".
- sevenseacat 6mo agoSame! Man, where was a post like this when I was struggling trying to learn Prolog, modelling something with knights and knaves...
- chamomeal 6mo agoI’ve always heard the first wave of AI was all lisp. Why is that? Just cause it had superpowers over the other languages of the day? I can see why someone would think prolog could bring an AI wave. Even after messing around with it for a few hours, I feel like there are things I could build in prolog that I couldn’t build in typescript.
- SilentM68 6mo agoThat's very helpful & easy to follow. Do you have an Odin tutorial that's as easy to digest? Sol
- triska 6mo agoVery nice! In the Scryer Prolog discussions, Alex has shared a few ideas and considerations for possible improvements to the Prolog code, including the use of metaprogramming to automatically generate more general relations: https://github.com/mthom/scryer-prolog/discussions/3221 https://github.com/mthom/scryer-prolog/discussions/3221 I hope for an interesting followup article! Another very interesting Prolog program by Alex is factgraph.pl: https://github.com/alexpetros/factgraph.pl https://github.com/alexpetros/factgraph.pl It's a Prolog implementation of the IRS Fact Graph, an application of Law as Code.
- admeliora01 6mo agoLove this use case, makes me want to implement something similar for Magic the Gathering. I love using scryfall, but I think a more cli first approach with descriptive rules would suffice much better for brewing in eternal formats like Commander with ever growing card pools. I mostly work off of keyword search.
- alexpetros 6mo agoI'm not as familiar with Magic, but I've always been curious if that community has tooling at a comparable level of maturity to Pokemon Showdown.
- LelouBil 5mo agoFor Yu-Gi-Oh! You have ygopro
- deosjr 6mo agoThis might be your jam. I should revisit this, most of it is unimplemented. But the parsing part was interesting, since MTG has such a codified language for explaining the rules. My idea here was to take a card's rules text from the official API and parse it into smth that can be used in the game, so you could keep up with new sets with implementation. The weird rule-breaking edge cases will always fail, but a large set of design space can fit, I think. See https://github.com/deosjr/pmtg/blob/master/parse.pl https://github.com/deosjr/pmtg/blob/master/parse.pl
- YeGoblynQueenne 5mo agoHey, that's cool! I had the same idea too: https://github.com/stassa/Gleemin https://github.com/stassa/Gleemin Although the code is nigh-on unreadable now ^_^@ >> The weird rule-breaking edge cases will always fail, but a large set of design space can fit, I think. Well, in that case you just update the parser or the rules engine. That's precisely how M:tG Arena works and they 've managed to keep up with new sets at a pace never before seen in official M:tG engines. There was a time when writing an M:tG parser was considered impossible [1] and M:tG engines, both official and community ones, each had their own little DSL that they had to manually translate ability text into which could take months especially if the engine also had to be updated to use the new rules in a set. Eventually someone in Wizards realised this is just dumb and they did it the way you go about it above. ______________ [1] Source: my conversations with the folks behind Forge and other community-made M:tG engines.
- jodrellblank 6mo ago> "Don't be bothered with by the fact that the solutions end with "or false" here. It's a function of how the search algorithms work; the solver looked for more solutions, then failed. I'll admit, I don't totally understand why it only sometimes does this, but it's expected." I think this is explained in The Power of Prolog[1] that the answers coming from Prolog are not printing text to a terminal, they are valid Prolog terms(/data/code). That's why the result uses the same `;` for OR as code does. Answer (x ; y ; false) is "query can be answered by x or y or no other answer found". (This would let you do meta-programming, reasoning about the results and rewriting the results in a LISPy data-as-code way, if you were more advanced than I am). Prolog systems do optimisations to jump to the correct answer without searching, if they can, (e.g. database style indexing on the facts and rules) and in those cases there is no code left to search after showing the first answer, no need to prompt the user "should I search for more answers in the remaining code?", and so no need for an output "false" to say "I finished searching and found no more solutions". [1] https://www.metalevel.at/prolog https://www.metalevel.at/prolog
- Bratmon 6mo agoThis embodies why I don't like Prolog. Prolog's philosophy is that you should just write the predicates without thinking about how the engine works. But as soon as you do something actually complicated, you realize that the different optimization modes of the engine give different results, and shortly after that you'll find yourself in the "exhaustively try every possible combination until we get one that satisfies the predicates" mode, and your code will go from taking 1 second to run to taking 8 days. And because you don't control the engine (you're not supposed to think about it, after all), there's nothing you can do but rewrite the whole thing in a traditional programming language.
- triska 6mo agoHow is this different from other programming languages though? One example I often think about is from Ken Silverman: "sub eax, 128" → "add eax, -128". So equivalent ways to write the same program may have different performance characteristics also depending on the tools that are applied. How many people could tell without trying which way to write this example is preferable? The same phenomenon will be encountered in all kinds of languages, where engine and compiler improvements make existing code faster or slower.
- stellartux 6mo agoIf this is your article, you have a typo in learns_priority/3, "move_priority #> 0" should be "P #> 0".
- alexpetros 6mo agoThank you!
- LelouBil 5mo agoSince you're here, I have a small question: Why use pokemon showdowns API directly and not https://pokeapi.co/ https://pokeapi.co/ ?
- Joker_vD 6mo ago> Then query it like so: SELECT DISTINCT pokemon, special_attack FROM pokemon as p WHERE p.special_attack > 120 AND EXISTS ( SELECT 1 FROM pokemon_moves as pm WHERE p.pokemon_name = pm.pokemon_name AND move = 'freezedry' ) AND EXISTS ( SELECT 1 FROM pokemon_types as pt WHERE p.pokemon_name = pt.pokemon_name AND type = 'ice' ); Hmm. I wonder if this SELECT DISTINCT pokemon, special_attack FROM pokemon as p NATURAL JOIN pokemon_moves as pm NATURAL JOIN pokemon_types as pt WHERE p.special_attack > 120 AND pm.move = 'freezedry' AND pt.type = 'ice' ; would work instead.
- sgarland 6mo agoIt would, but it forces the requirement of DISTINCT. With the original, if there were declared PKs (pokemon_name is fine for the main table, with a composite for others), the semi-join (EXISTS) would eliminate the need for DISTINCT entirely. I think. Doing this in my head, but you could verify it trivially with SQLite or any other RDBMS.
- deleted 6mo ago[deleted]
- fl1pper 6mo agoI'm not familiar with Pokemon universe :( Can somebody please explain Pokemon using Prolog?
- wk_end 6mo agoOne of the neat things about Prolog is that queries can be run both forwards and backwards, so I believe this article should already have you covered ;)
- zzo38computer 6mo agoThere is a lot more than only what they explain in that article (I don't know of any full implementation of Pokemon in Prolog, although there is an implementation in TypeScript). For example, you can also switch out (to activate a different pokemon) instead of attacking (switching has priority over attacking, so if you switch out then the opponent's attack will hit your newly active pokemon). There are also many calculations involved, and it can be helpful to know how most of them work.
- cluckindan 6mo ago”I am about to describe the mechanics of a children’s video game in great detail” Prolog must be an adult programming language :)
- deosjr 6mo agoA while ago I was playing the romhack Run&Bun, which drastically ups the difficulty of Pokemon Emerald. Watching others play, most of the game was doing 'calcs': calculating how to approach a battle. This was done using a javascript frontend to a simulator, and a lot of excel sheets. So I forked the calculator and added a Prolog wrapper so I could find solutions to battles based on the team of Pokemon that I caught. https://github.com/deosjr/runbuncalc/blob/master/main.pl https://github.com/deosjr/runbuncalc/blob/master/main.pl My runs died pretty early, but there are some notes here as I was implementing that are fun to read. I implemented each battle as a test case and let my solver find a solution, then amended the plan and commented on what actually happened. For example: https://github.com/deosjr/runbuncalc/blob/master/run10.pl#L21 https://github.com/deosjr/runbuncalc/blob/master/run10.pl#L2...
- Fokamul 6mo agoWhere "Getting C&D from Nintendo for a blog post" fits in?
- LelouBil 6mo agoI always wanted to read about logic programming, and this was a great introduction ! Thank you !