Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: AI::Perlog -- Simple implementation

by mattr (Curate)
on Aug 02, 2002 at 13:12 UTC ( [id://187076]=note: print w/replies, xml ) Need Help??


in reply to AI::Perlog -- Simple implementation

Silly me, trying to build and test this on cygwin. Machine is fine, but insane - can't find perl, Test::More, etc.

Anyway tried it, seems to answer "does somebody own gold" and "does x own gold". How to find out everyone who owns gold, or who does not.. or is that what _check_path does?

FWIW I'd like to specify "*" as an alias to "_". Or would that mess up inside a qw()? Also I feel scared by the underscore since it seems like the mysterious used $_ without the $ and always wonder if something will get evaled when I wasn't watching. Though maybe intentional? Does look like a "fill in the blank" which is kinda neat.

I see use of "exists" and a note about autovivification in the code. Is this too fragile for me to touch the knowledgebase hash?

What else needed to solve the thief problem? How about intersections?

What has been your experience using a graph?

  • Comment on Re: AI::Perlog -- Simple implementation

Replies are listed 'Best First'.
AI::Perlog -- Q&A
by Ovid (Cardinal) on Aug 02, 2002 at 16:31 UTC

    Test::More is only required for the tests. If you trust the code, you could go ahead and install it and hope it works.

    How to find out everyone who owns gold, or who does not.. or is that what _check_path does?

    That feature isn't implemented yet. It's what is called "unification", where data gets associated with a variable in a query. To find out who owns gold, a query like the following would probably be made:

    $pg->owns( qw/ $Who gold / );

    Because Perlog would know that arguments beginning with a dollar sign are variables, it would know to grab the appropriate data and return it. I've been very busy this week or I would have put that in -- which is really the first thing that needs to go in to actually make this useful.

    As a side note: I hate the proposed syntax above, so I am open for suggestions.

    _check_path() is called from the following:

    my $a = shift @important; while( my $z = shift @important ) { return if !$self->_check_path($predicate_id,$a,$z,@args[$a,$z] +); $a = $z; } return 1;

    That loops over the arguments supplied in a query and says foreach argument, return false if I don't find a path to the next argument. The actual method call had a bunch of comments that I hadn't bothered to clean out since I wasn't planning on releasing this yet. You can ignore them. There was also a leftover line of debugging code that I forgot to clean out :) Here's the cleaned up method:

    sub _check_path { my ( $self, $predicate, $lvl1, $lvl2, $arg1, $arg2 ) = @_; return 1 if exists $self->{_arg_levels}{$predicate}[$lvl1]{$arg1}[$lvl +2]{$arg2}; return; # nope, didn't find it }

    If you want to try and figure out that hideous data structure, you can read this brief explanation.

    If you really, really are foolish enough to work on this, thank you :) Other than that, here's what you need to know about the object keys.

    _next_vertex
    Every unique argument and predicate is given this value, and then the value is incremented. This ensures that everything has a unique id.
    _object_vertex
    This is a mapping of object names (keys) to their vertex ids (values).
    _predicates
    Poorly named. I should have named it _predicate_vertex. I'll probably change it. It's a mapping of predicate names to their unique ids.
    _arg_levels
    Too complicated to explain here. See the link above.

    If it's not clear, a predicate can be thought of as the name of a rule.

    $pg->add_fact( owns => qw/ Ovid socks / ); $pg->add_fact( gives => qw/ grep grief Ovid / );

    In the above expample, "owns" and "gives" are the predicates.

    FWIW I'd like to specify "*" as an alias to "_". Or would that mess up inside a qw()? Also I feel scared by the underscore since it seems like the mysterious used $_ without the $ and always wonder if something will get evaled when I wasn't watching. Though maybe intentional?

    As for your comments about the underscore: that's borrowed from Prolog. If someone wants to make the query gives( qw/ grep grief _ / ); (which translates to "does grep give grief to anyone?"), then you cannot use the qw// syntax if only the empty string and undef are skipped. As for the asterisk suggestion, I like it, but for practical reasons, I can only use one character for that and I may as well use the standard one.

    What else needed to solve the thief problem?

    Unification.

    What has been your experience using a graph?

    I was using a graph at first, but I realized that it was lacking some of the things that I needed so I rolled my own data structure. Right now, even though Graph.pm is listed as a prerequisite, I actually pulled it out of the module completely. I was mostly using it for tests. Pulling it out also had the nice side effect of doubling the speed of my code.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Just one thing I'd like to say now, What about Who? :) Or, how to differentiate between declarations and queries.. Maybe you want to say that the user specified in the string $Who does in fact own gold.

      So to answer your question about $Who syntax I started thinking about dbi-like placeholders, (e.g. :who) but Who can be multivalued, right? So a Set object or even a simple list might be good.

      Somehow I got this funny idea of letting the underscore ("anyone"/"anything") symbol contribute dimensions to the answer of who gives what to Kudra, so $pg->gives(qw( _ _ kudra )) could give you a two-dimensional array, which works out to a hash %_ that says $_{who} = what. Is this useful? One problem I see besides speed is that of autovivification. If your structure didn't present autoviv. problems to the casual user you could even return an array of references to points in the knowledge base so they could easily modify it. I think I need to know a lot more about how Prolog is used to be intelligent about this.

      I went back to the Haskell page when thinking about your question re embedded facts. I was interested to see that they mention SQL in the context of functional languages. And from their languages page I found an example of syntax in the Curry language which might be applicable.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://187076]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-04-24 18:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found