ztangent / Julog.jl

A Julia package for Prolog-style logic programming.
Apache License 2.0
170 stars 11 forks source link

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

Closed AIxer closed 2 years ago

AIxer commented 2 years ago

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?

ztangent commented 2 years ago

So the parsing provided by @prolog isn't perfect, and without more careful debugging, it's hard to know why the parser isn't working here -- the one thing I can think of is that I don't think Julog.jl supports comments in Prolog right now, so maybe try removing those?

As for adding builtins, I would like to have a more efficient way of doing this, but currently I think your best bet is to add clauses for predicates like member and subtract to the list of clauses you provide to resolve, and to implement nonvar using a custom function. You can see this example for Julog definitions of list-related predicates like member. Hope this helps!

AIxer commented 2 years ago

I‘v done some work, translated all the rules in nal.pl into Julog style. Happily, it partially works and no Error reported, but there are still some problems. well, one of the problem is L1 =.. L2, =.. is SWI-Prolog 's built-in, I wrote a custom function univ, it can translate Term into a Julia Vector of Julog Term, obviously, it's not what I need. So, how to implement it? I hope to get your help. Much appreciated.

AIxer commented 2 years ago

a problem like above, I can't figure out how to implement nonvar with custom functions:

funcs = Dict()
funcs[:nonvar] = x -> !isa(x, Var)
funcs[:ground] = x -> is_ground(x)
julia> goal = @julog ground(atomic(x))
ground(atomic(x))

julia> resolve(goal, Clause[]; funcs)
(false, Any[])

or

funcs = Dict()
funcs[:nonvar] = x -> !isa(@julog(x), Var)
funcs[:ground] = x -> is_ground(@julog(x))
julia> goal = @julog ground(atomic(x))
ground(atomic(x))

julia> resolve(goal, Clause[]; funcs)
(false, Any[])

Both are not working. 😭 Any instructions? 🙏 Thanks a lot! @ztangent

AIxer commented 2 years ago

Well, I think some functions like ground, nonvar and atom may cannot be supported currently. Because of Julog's code here.

ztangent commented 2 years ago

I think you're right! Oof. Maybe you fork Julog and modify the handle_builtins! function so that it knows how to deal with atomic and nonvar? If you make a PR I'd be happy to review it!

AIxer commented 2 years ago

Yes, I've forked just now, but only added ground, nonvar and atom for my project purpose. Then is Univ, but I have no idea now.

ztangent commented 2 years ago

Yeah it seems like Univ might take more work... Julog does have some convenience functions to convert Julia lists into Julog lists, and vice versa, which I think might help! You probably want to handle it is a builtin, and make sure you handle both the case where LHS and RHS are variables.

ztangent commented 2 years ago

This is probably the function you want to use:

https://github.com/ztangent/Julog.jl/blob/01367bc8aa0a84304ff0b7c553223f274cf2ebbd/src/utils.jl#L130-L132

AIxer commented 2 years ago

Thanks! Ordinary Prolog implementation will use functor and arg to achieve Univ, but I think use julia function directly maybe more efficient, make it just act like Univ 😃

AIxer commented 2 years ago

You probably want to handle it is a builtin, and make sure you handle both the case where LHS and RHS are variables.

to_term_list then unifies ? emmm, actually, I haven't fully understood Julog's operational mechanism. 😄