GithubHelp home page GithubHelp logo

ztangent / julog.jl Goto Github PK

View Code? Open in Web Editor NEW
168.0 9.0 11.0 207 KB

A Julia package for Prolog-style logic programming.

License: Apache License 2.0

Julia 100.00%
julia prolog first-order-logic logic logic-programming fol

julog.jl's Introduction

Julog.jl

GitHub Workflow Status GitHub release (latest SemVer) License Documentation

A Julia package for Prolog-style logic programming.

Installation

Enter the package manager by pressing ] at the Julia REPL, then run:

add Julog

The latest development version can also be installed by running:

add <link to this git repository>

Features

Usage

Terms and Horn clauses can be expressed in Prolog-like syntax using the @julog macro:

# This creates a term
@julog teacher(bodhidharma, huike)
# This creates a fact (a term which is asserted to be true)
@julog teacher(bodhidharma, huike) <<= true
# This creates a definite clause
@julog grandteacher(A, C) <<= teacher(A, B) & teacher(B, C)

The @julog macro can be also applied to a list of clauses to create a knowledge base. We use the traditional Zen lineage chart as an example:

clauses = @julog [
  ancestor(sakyamuni, bodhidharma) <<= true,
  teacher(bodhidharma, huike) <<= true,
  teacher(huike, sengcan) <<= true,
  teacher(sengcan, daoxin) <<= true,
  teacher(daoxin, hongren) <<= true,
  teacher(hongren, huineng) <<= true,
  ancestor(A, B) <<= teacher(A, B),
  ancestor(A, C) <<= teacher(B, C) & ancestor(A, B),
  grandteacher(A, C) <<= teacher(A, B) & teacher(B, C)
]

With the resolve function, we can query the knowledge base via SLD resolution (the form of backward-chaining proof search used by Prolog):

# Query: Is Sakyamuni the dharma ancestor of Huineng?
julia> goals = @julog [ancestor(sakyamuni, huineng)]; # List of terms to query or prove
julia> sat, subst = resolve(goals, clauses);
julia> sat
true

# Query: Who are the grandteachers of whom?
julia> goals = @julog [grandteacher(X, Y)];
julia> sat, subst = resolve(goals, clauses);
julia> subst
4-element Array{Any,1}:
  {Y => sengcan, X => bodhidharma}
  {Y => daoxin, X => huike}
  {Y => hongren, X => sengcan}
  {Y => huineng, X => daoxin}

Forward-chaining proof search is supported as well, using derive. We can also compute the list of n-step derivations with derivations(clauses, n):

# Facts derivable from one iteration through the rules
julia> derivations(clauses, 1)
16-element Array{Clause,1}:
 teacher(bodhidharma, huike)
 
 ancestor(sakyamuni, huike)

# The set of all derivable facts (i.e. the closure / fixed-point)
julia> derivations(clauses, Inf)
30-element Array{Clause,1}:
 teacher(bodhidharma, huike)
 
 ancestor(sakyamuni, huineng)

More examples can be found in the test folder.

Syntax

Julog uses syntax very similar to Prolog. In particular, users should note that argument-free terms with initial capitals are parsed as variables, whereas lowercase terms are parsed as constants:

julia> typeof(@julog(Person))
Var
julia> typeof(@julog(person))
Const

However, several important operators differ from Prolog, as shown by the examples below:

Julog Prolog Meaning
human(socrates) <<= true human(socrates). Socrates is human.
mortal(X) <<= human(X) mortal(X) :- human(X). If X is human, X is mortal.
!mortal(gaia) \+mortal(gaia) Gaia is not mortal.
mortal(X) <<= can_live(X) & can_die(X) mortal(X) :- can_live(X), can_die(X) X is mortal if it can live and die.

In words, <<= replaces the Prolog turnstile :-, <<= true or ' replaces . when stating facts, ! replaces \+ for negation, there is no longer a special operator for cut, & replaces , in the bodies of definite clauses, and there is no or operator like the ; in Prolog.

In addition, when constructing Prolog-style linked-lists, the syntax @julog list[a, b, c] should be used when the list is not nested within any other compound term. This is because the @julog [a, b, c] syntax is reserved for creating a Julia list of Julog objects, such as a list of Julog clauses. Lists which are nested within other term, e.g., member(b, [a, b, c]), are parsed in the same way as Prolog. (Note that list predicates like member are not built-in predicates, and have to be manually defined as a clause.)

If Prolog syntax is preferred, the @prolog macro and parse_prolog functions can be used to convert Prolog strings directly to Julog constructs, while write_prolog converts a list of Julog clauses to a Prolog string. However, this conversion cannot presently handle all of Prolog syntax (e.g., nested infix operators or comparison operators such as =:=), and should be used with caution.

Interpolation

Similar to string interpolation and expression interpolation in Julia, you can interpolate Julia expressions when constructing Julog terms using the @julog macro. Julog supports two forms of interpolation. The first form is constant interpolation using the $ operator, where ordinary Julia expressions are converted to Consts:

julia> e = exp(1)
2.718281828459045
julia> term = @julog irrational($e)
irrational(2.718281828459045)
julia> dump(term)
Compound
  name: Symbol irrational
  args: Array{Term}((1,))
    1: Const
      name: Float64 2.718281828459045

The second form is term interpolation using the : operator, where pre-constructed Julog terms are interpolated into a surrounding Julog expression:

julia> e = Const(exp(1))
2.718281828459045
julia> term = @julog irrational(:e)
irrational(2.718281828459045)
julia> dump(term)
Compound
  name: Symbol irrational
  args: Array{Term}((1,))
    1: Const
      name: Float64 2.718281828459045

Interpolation allows us to easily generate Julog knowledge bases programatically using Julia code:

julia> people = @julog [avery, bailey, casey, darcy];
julia> heights = [@julog(height(:p, cm($(rand(140:200))))) for p in people]
4-element Array{Compound,1}:
 height(avery, cm(155))
 height(bailey, cm(198))
 height(casey, cm(161))
 height(darcy, cm(175))

Custom Functions

In addition to standard arithmetic functions, Julog supports the evaluation of custom functions during proof search, allowing users to leverage the full power of precompiled Julia code. This can be done by providing a dictionary of functions when calling resolve. This dictionary can also accept constants (allowing one to store, e.g., numeric-valued fluents), and lookup-tables. An example is shown below:

funcs = Dict()
funcs[:pi] = pi
funcs[:sin] = sin
funcs[:cos] = cos
funcs[:square] = x -> x * x
funcs[:lookup] = Dict((:foo,) => "hello", (:bar,) => "world")

@assert resolve(@julog(sin(pi / 2) == 1), Clause[], funcs=funcs)[1] == true
@assert resolve(@julog(cos(pi) == -1), Clause[], funcs=funcs)[1] == true
@assert resolve(@julog(lookup(foo) == "hello"), Clause[], funcs=funcs)[1] == true
@assert resolve(@julog(lookup(bar) == "world"), Clause[], funcs=funcs)[1] == true

See test/custom_funcs.jl for more examples.

Unlike Prolog, Julog also supports extended unification via the evaluation of functional terms. In other words, the following terms unify:

julia> unify(@julog(f(X, X*Y, Y)), @julog(f(4, 20, 5)))
Dict{Var, Term} with 2 entries:
  Y => 5
  X => 4

However, the extent of such unification is limited. If variables used within a functional expression are not sufficiently instantiated at the time of evaluation, evaluation will be partial, causing unification to fail:

julia> unify(@julog(f(X, X*Y, Y)), @julog(f(X, 20, 5))) === nothing
true

Built-in Predicates

Julog provides a number of built-in predicates for control-flow and convenience. Some of these are also part of ISO Prolog, but may not share the exact same behavior.

  • cons and cend are reserved for lists. [x, y, z] is equivalent to cons(x, cons(y, cons(z, cend())).
  • true and false operate as one might expect.
  • and(A, B, C, ...) is equivalent to A & B & C & ... in the body of an Julog clause.
  • or(A, B, C, ...) is equivalent to A ; B ; C ; ... in Prolog-syntax.
  • not(X) / !X is true if X cannot be proven (i.e. negation as failure).
  • unifies(X, Y) / X ≐ Y is true if X unifies with Y.
  • exists(Cond, Act) is true if Act is true for at least one binding of Cond.
  • forall(Cond, Act) is true if Act is true for all possible bindings of Cond (beware infinite loops).
  • imply(Cond, Act) / Cond => Act is true if either Cond is false, or both Cond and Act are true.
  • call(pred, A, B, ...), the meta-call predicate, is equivalent to pred(A, B, ...).
  • findall(Template, Cond, List) finds all instances where Cond is true, substitutes any variables into Template, and unifies List with the result.
  • countall(Cond, N) counts the number of proofs of Cond and unifies N with the result.
  • fail causes the current goal to fail (equivalent to false).
  • cut causes the current goal to succeed and suppresses all other goals. However, this does not have the same effects as in Prolog because Julog uses breadth-first search during SLD-resolution, unlike most Prolog implementations, which use depth-first search.

See test/builtins.jl for usage examples.

Conversion Utilities

Julog provides some support for converting and manipulating logical formulae, for example, conversion to negation, conjunctive, or disjunctive normal form:

julia> formula = @julog and(not(and(a, not(b))), c)
julia> to_nnf(formula)
and(or(not(a), b), c)
julia> to_cnf(formula)
and(or(not(a), b), or(c))
julia> to_dnf(formula)
or(and(not(a), c), and(b, c))

This can be useful for downstream applications, such as classical planning. Note however that these conversions do not handle the implicit existential quantification in Prolog semantics, and hence are not guaranteed to preserve equivalence when free variables are involved. In particular, care should be taken with negations of conjunctions of unbound predicates. For example, the following expression states that "All ravens are black.":

@julog not(and(raven(X), not(black(X))))

However, to_dnf doesn't handle the implied existential quantifier over X, and gives the non-equivalent statement "Either there are no ravens, or there exist black things, or both.":

@julog or(and(not(raven(X))), and(black(X)))

Related Packages

There are several other Julia packages related to Prolog and logic programming:

  • HerbSWIPL.jl is a wrapper around SWI-Prolog that uses the Julog parser and interface.
  • Problox.jl is a lightweight Julia wrapper around ProbLog, a probabilistic variant of Prolog.

Acknowledgements

This implementation was made with reference to Chris Meyer's Python interpreter for Prolog, as well as the unification and SLD-resolution algorithms presented in An Introduction to Prolog by Pierre M. Nugues.

julog.jl's People

Contributors

crashburnrepeat avatar fplk avatar mschauer avatar sebdumancic avatar simeonschaub avatar ztangent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

julog.jl's Issues

Error: LoadError: $Expr(:incomplete, "...") & How to extend `builtins`?

Hi, I am working on a Reasoning System, it has rules written in SWI-Prolog: nal.pl.
I want to use it in Julia, but there're some predicates like membernonvar and subtract are not in Julog's builtins.

When I use @prolog to parse nal.pl:

using Julog

rules = @prolog """
     prolog rules in nal.pl
"""

I got an Error:

Expr
  head: Symbol incomplete
  args: Array{Any}((1,))
    1: String "incomplete: premature end of input"
ERROR: LoadError: syntax error in Julog term at $(Expr(:incomplete, "incomplete: premature end of input"))
Stacktrace:
 [1] error(s::String)
   @ Base .\error.jl:33
 [2] parse_term(expr::Expr, esc::typeof(esc))
   @ Julog C:\Users\Axier\.julia\packages\Julog\V6gVn\src\parse.jl:38
 [3] parse_julog(expr::Expr, esc::Function)
   @ Julog C:\Users\Axier\.julia\packages\Julog\V6gVn\src\parse.jl:111
in expression starting at D:\codes\Junars\src\rules\julogrules.jl:3
in expression starting at D:\codes\Junars\src\rules\julogrules.jl:3

How can I make these rules work in Julog?

Engine does not run through all available variants

I tried to implement simple zebra puzzle. After several hours of struggling through I decided to implement simple check test: generate all permutations on 4 elements

clauses = @julog [
     tuples(T) <<= 
        eq(T, [_,_,_,_]) &
        subset([1,2,3,4], T),
        
    eq(A,A)',
    member(X, [X | Y])',
    member(X, [Y | YS]) <<= member(X, YS),
    subset([],_)',
    subset([X | XS], L) <<= member(X,L) & subset(XS,L)
]
goals = @julog [tuples(T)]
resolve(goals,clauses)[2]

However the output was

8-element Array{Any,1}:
 {T => [1, 2, 3, 4]}
 {T => [1, 2, 4, 3]}
 {T => [1, 3, 2, 4]}
 {T => [1, 4, 2, 3]}
 {T => [2, 1, 3, 4]}
 {T => [2, 1, 4, 3]}
 {T => [3, 1, 2, 4]}
 {T => [4, 1, 2, 3]}

Instead of all 24 permutations
I wrote very similar code on Prolog to compare results:

tuples(T) :-
    T = [_,_,_,_],
    subset([1,2,3,4],T).

subset([],_).

subset([X | XS], L) :-
    member(X,L),
    subset(XS,L).

?- tuples(T)

And got right result

T = [1, 2, 3, 4]
T = [1, 2, 4, 3]
T = [1, 3, 2, 4]
T = [1, 4, 2, 3]
T = [1, 3, 4, 2]
T = [1, 4, 3, 2]
T = [2, 1, 3, 4]
T = [2, 1, 4, 3]
T = [3, 1, 2, 4]
T = [4, 1, 2, 3]
T = [3, 1, 4, 2]
T = [4, 1, 3, 2]
T = [2, 3, 1, 4]
T = [2, 4, 1, 3]
T = [3, 2, 1, 4]
T = [4, 2, 1, 3]
T = [3, 4, 1, 2]
T = [4, 3, 1, 2]
T = [2, 3, 4, 1]
T = [2, 4, 3, 1]
T = [3, 2, 4, 1]
T = [4, 2, 3, 1]
T = [3, 4, 2, 1]
T = [4, 3, 2, 1]

This shows that Julog engine does not run through all available variants

Resolve does not check for valid optional arguments

Following up from #9, resolve does not actively check to make sure optional arguments are valid, instead checking for specific options (such as :dfs for search) and otherwise using the default option. This can lead to silent "failures" where the user may not know resolve is using different settings than the user intended.

Term construction via template?

@ztangent I'm not sure if I'm just missing an easier way to do this (or if there are more Julog-ian ways to do it) but I've been trying to construct some sort of "template logic" that I can then populate with more specific terms. As a short description of what I mean, I've prepared some code 😄 (It does use some Julia 1.5 syntactic sugar though... ;funcs instead of funcs=funcs)

funcs = Dict()
funcs[:sin] = sin
funcs[:square] = x -> x * x

op_def(func,input,comp,output) = @julog $(comp)($(func)($input),$output)

sin_def = op_def(
    :sin,
    π/2,
    Symbol("=="),
    1
)

square_def = op_def(
    :square,
    5,
    Symbol("<="),
    25
)

@assert resolve(sin_def, Clause[]; funcs)[1]==true
@assert resolve(square_def, Clause[]; funcs)[1]==true
@assert resolve(@julog(and(:sin_def, :square_def)), Clause[]; funcs)[1]==true

The idea is more programmatic generation of Julog logic and I didn't see examples like this in the documentation. There were examples on how to use custom functions, but without being able to modify a template, it's impossible to create the and expression with just the funcs argument. Does that make sense, or would it help to elaborate?

As a side note, I've been curious on your vision for Julog. Is the idea to keep it as close to the original Prolog as is feasible, or is greater integration into Julia the goal?

Thanks as always!

Too large an expression?

Hi @ztangent,

I was recently trying to put together a demonstration of logical programming using the 4 color theorem to color a map of the US. Although the code is relatively simple, the logical expressions are quite large; they're show below:

color_pairs = @julog [
    n(red, green)<<=true,
    n(green, red)<<=true,
    n(blue, red)<<=true,
    n(yellow, red)<<=true,
    n(red, blue)<<=true,
    n(green, blue)<<=true,
    n(blue, green)<<=true,
    n(yellow, green)<<=true,
    n(red, yellow)<<=true,
    n(green, yellow)<<=true,
    n(blue, yellow)<<=true,
    n(yellow, blue)<<=true
]

map_layout_all = @julog colors(AK, AL, AR, AZ, CA, CO, CT, DC, DE, FL, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VA, VT, WA, WI, WV, WY)<<=
    n(AL, FL) & n(AL, GA) & n(AL, MS) & n(AL, TN) &
    n(AR, LA) & n(AR, MS) & n(AR, MO) & n(AR, OK) & n(AR, TN) & n(AR, TX) &
    n(AZ, CA) & n(AZ, NM) & n(AZ, NV) & n(AZ, UT) &
    n(CA, OR) & n(CA, NV) &
    n(CO, KS) & n(CO, NE) & n(CO, NM) & n(CO, OK) & n(CO, UT) & n(CO, WY) &
    n(CT, MA) & n(CT, NY) & n(CT, RI) &
    n(DE, MD) & n(DE, NJ) & n(DE, PA) &
    n(FL, GA) &
    n(GA, NC) & n(GA, SC) & n(GA, TN) &
    n(ID, MT) & n(ID, NV) & n(ID, OR) & n(ID, UT) & n(ID, WA) & n(ID, WY) &
    n(IL, IA) & n(IL, IN) & n(IL, KY) & n(IL, MO) & n(IL, WI) &
    n(IN, KY) & n(IN, MI) & n(IN, OH) &
    n(IA, MN) & n(IA, MO) & n(IA, NE) & n(IA, SD) & n(IA, WI) &
    n(KS, MO) & n(KS, NE) & n(KS, OK) &
    n(KY, MO) & n(KY, OH) & n(KY, TN) & n(KY, VA) & n(KY, WV) &
    n(LA, MS) & n(LA, TX) &
    n(ME, NH) &
    n(MD, PA) & n(MD, VA) & n(MD, WV) &
    n(MA, NH) & n(MA, NY) & n(MA, RI) & n(MA, VT) &
    n(MI, OH) & n(MI, WI) & n(MI, MN) & #MI and MN share a water border
    n(MN, ND) & n(MN, SD) & n(MN, WI) &
    n(MS, TN) &
    n(MO, NE) & n(MO, OK) & n(MO, TN) &
    n(MT, ND) & n(MT, SD) & n(MT, WY) &
    n(NE, SD) & n(NE, WY) &
    n(NV, OR) & n(NV, UT) &
    n(NH, VT) &
    n(NJ, NY) & n(NJ, PA) &
    n(NM, OK) & n(NM, TX) &
    n(NY, PA) & n(NY, VT) & n(NY, RI) & #NY and RI share a water border 
    n(NC, SC) & n(NC, TN) & n(NC, VA) &
    n(ND, SD) &
    n(OH, PA) & n(OH, WV) &
    n(OK, TX) &
    n(OR, WA) &
    n(PA, WV) &
    n(SD, WY) &
    n(TN, VA) &
    n(UT, WY) &
    n(VA, WV) &
    n(DC, VA) & n(DC, MD)

goal_all = @julog colors(AK, AL, AR, AZ, CA, CO, CT, DC, DE, FL, GA, HI, IA, ID, IL, IN, KS, KY, LA, MA, MD, ME, MI, MN, MO, MS, MT, NC, ND, NE, NH, NJ, NM, NV, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VA, VT, WA, WI, WV, WY)
map_soln_all = resolve(goal_all, vcat(color_pairs, map_layout_all), mode=:any, search=:dfs)

When I first ran this without any options set in resolve, the solver failed to finish after about an hour, and considering the size of the search space (~4^51 I believe) this didn't seem unreasonable. I then hoped that setting mode=:any and search=:dfs would solve in a reasonable amount of time for a single solution, but I also had to halt the solver after a half an hour had passed.

I wanted to see if this second attempt (trying to find any solution via depth-first search) is one you would have expected to finish in a "reasonable" amount of time, or if this is simply too large a problem even for those options.

Also as a side note, it seems like there's no validity check with the resolve options, and any invalid option choice will just "fail" silently by using the default settings. Am I reading the code correctly for these cases?

Thanks as always!

Parsing for equivalence rules?

I'm trying to recreate in Julog Prolog statements like:

sister(X,Y):-
  parent(Z,X),
  parent(Z,Y),
  female(X),
  X\=Y.

The last term is required or else people can be their own sisters. My initial thought was to translate the last term as X!=Y and the expression was parsed without error, but returned incorrect results (saying that an individual did not have a sister when they did).

My solution has been to use not(unifies(X,Y)) but this seems a little verbose and I'm not sure it's truly equivalent to what I'm looking for. Can the != syntax be implemented without breaking the package, or is using unifies the recommended approach? If != is not the intended approach, can the failure be made more apparent (a throw perhaps?)

`member` usage

Hello there,

I was trying member example like this,

resolve(@julog(member(b, [a, b, c])),Clause[])

Is this a bug or feature?

References on breadth-first logic programming

The README states:

cut causes the current goal to succeed and suppresses all other goals. However, this does not have the same effects as in Prolog because Julog uses breadth-first search during SLD-resolution, unlike most Prolog implementations, which use depth-first search.

No reason for this unusual choice is given, however I'm aware that there are good reasons why one might prefer breadth-first semantics. Three doctoral dissertations explore this choice; in the first and last, the researchers have implemented a breadth-first LPL, while the second explores expressions in Haskell using Wadler's 'list of successes' paradigm:

  1. Richard McPhee, 2000. Compositional Logic Programming. DPhil thesis, Programming Research Group, University of Oxford.
  2. Silvijia Seres, 2001. The Algebra of Logic Programming. DPhil thesis, Programming Research Group, University of Oxford. http://silvija.net/0000OxfordPublications/seres_thesis.pdf
  3. Görkem Paçaci, 2017. Representation of Compositional Relational Programs. PhD thesis, Department of Informatics and Media, Uppsala University.

The issue that drives the preference comes from algebraic semantics: if you regard the semantics of a query as a collection of satisfiers, left-to-right depth-first search gives conjunction a bias where (A,B) might not terminate if A gives an unbounded search, even if B has only finitely many satisfiers consistent with A; the requirement that the semantics lacks this kind of biases is called fairness, and breadth-first search makes this easier to achieve.

It might be worth adding a paragraph to the README mentioning the idea of fairness in logic-programming semantics and gesturing at the literature.

Parsing dot character Issue in `convert_prolog_to_julog`

Hey there! Recently I had an issue with Julog trying to parse,

using Julog
s = """state("minnesota","mn","st. paul",4076.0e+3,84.4e+3,32,"minneapolis","st. paul","duluth","Bloomington")."""
Julog.convert_prolog_to_julog(s)

which outputs;

[
"state(\"minnesota\",\"mn\",\"st <<= true", 
"paul\",4076.0e+3,84.4e+3,32,\"minneapolis\",\"st <<= true",
"paul\",\"duluth\",\"bloomington\") <<= true"
]

It seems the issue is caused by the . character in the string. However, using the original ' character for wrapping strings(such as using it as 'st. paul') also causes parsing issue that says;

Base.Meta.ParseError("character literal contains multiple characters")

where, convert_prolog_to_julog seems to parse correctly as follows;

state('alabama','al','montgomery',3894.0e+3,51.7e+3,22,'birmingham','mobile','montgomery','huntsville') <<= true

However, Meta.parse attempting to read ' literal seems to be the cause.

Thanks in advance.

License?

Hi,

thank you for the great Julia package! Unfortunately I could not find any information about its license. Would it be possible to provide a LICENSE.md file?

Thank you,
Falco

Enhancement proposal: use Metatheory.jl

Me and @philzook58 worked on an EGraph implementation in pure Julia: https://github.com/0x0f0f0f/Metatheory.jl
It may be really interesting to write a backend for Julog using Metatheory.EGraphs and Metatheory.EGraphs.AbstractAnalysis to see if it simplifies the Julog codebase and outperforms the original implementation.
You may want to take a read at this paper https://dl.acm.org/doi/pdf/10.1145/3434304
Using Julog the other way, as an analysis for Metatheory.jl (applying rewrite rules only when a goal can be solved) would prove fundamental and useful for a symbolic mathematics/theorem proving framework in pure Julia.
Thanks for your package btw!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.