AI::Perlog

Ovid on 2002-07-23T16:15:33

My AI::Perlog is coming along nicely. It's not posted anywhere yet, but maybe I'll have something in about a week? I have boolean responses working fairly well. I can do this:

my $pg = AI::Perlog->new;
$pg->add_fact( owns => qw/ Ovid gold / );
$pg->add_fact( owns => qw/ Yoda grep / );
$pg->owns( 'Ovid', 'gold' ); # returns true
$pg->owns( 'Yoda', 'gold' ); # returns false
$pg->owns( '', 'gold' ); # Does *anyone* own gold? Returns true

Actually, while the above facts work, there is a bug that can create false positives with complex facts. I know what's causing it but the data structure that I need to create to get around it is pretty large and for serious AI systems with millions of facts, it will eat up all of the system's memory. However, I've made the classic "space for time" trade-off and, as a result, this seems to run reasonably fast.

Fixing the first bug has the nice side effect of tremendously simplifying the unification problem, but that's still going to be a tricky one. I need to do some more research into exactly how Prolog handles some of these issues.

One thing I've noticed is that while my data structures are large, they're not complicated (well, to a Perl programmer they're not :), so I am thinking that I may eventually be able to move them to Inline::C to save on space and improve performance. That, however, will probably not happen for quite some time. After I work on unification, I need to see how my planned implementation of rules is going to work.

Meanwhile, I have paying work to attend to. Sigh. The warm beauty of intellectualism shattered by the cold reality of life.


undef vs. ''

particle on 2002-07-25T13:47:47

i usually find clarity using undef vs ''. for instance, i'd write

$pg->owns( undef, 'gold' );

instead of

$pg->owns( '', 'gold' );

then again, if i wanted a more 'prologgy' syntax, i think i'd create a constant with an undefined value, like

sub X () {}
## or use constant X => undef;

$pg->owns( X, 'gold' );

in fact, i think i like the Prolog-like syntax in my last example. that's probably what i'll find myself using.

hrmmm... what if X is an lvalue subroutine?

Re:undef vs. ''

Ovid on 2002-07-25T16:46:49

I think you'll be relatively happy with this. In the auto-generated rules, if an argument is encountered with a false value, such as the empty string or undef, it's ignored (sort of). This means that if you prefer undef, you'll be perfectly free to use it.

As for $pg->owns( X, 'gold' );, I like the syntax, but forcing a person to predefine all of those constants means that it will be harder for them to generate queries on the fly.

    use constant Who => '';
    $pg->owns( Who, 'gold' );

Yes, I could have the person actually specify the constant in an import list and then export it into their namespace, but again, it's more work to change queries on the fly. If they want to know who gives books to whom, they have to create another constant.

    $pg->gives( Who, 'book', Whom );

This might not seem like a big deal, but I don't like generating constants for no reason ... though the lvalue subroutine idea sounded mighty sexy :)

Here's my very hated and proposed syntax for unification:

    my $results = $pg->gives( qw/ $who book $whom / ); # remember that qw// doesn't interpolate

If anyone has better suggestions, I'm open to them. I'm not sure about the return value, though. I could make it a hashref, but perhaps the rules should be factories returning objects that manage the data. That seems cleaner. It would also be easier to provide many different ways to access that data, if I use a factory, but it's kind of a moot point until I finish with some other issues.