Re: Being Forced to Fork with Nested Regular Expressions
by paulbort (Hermit) on Jan 02, 2004 at 18:00 UTC
|
I know that it really doesn't address your topic, but I think the reason that you're running into the problem is that it's the wrong approach. An impressive (ab)use of regular expressions, though.
What I've seen of predicate systems leads me to a database approach rather than regular expressions. Given the right data structure, you need to write two parsers: one to convert $facts into rows in tables, and one to convert your queries into SQL. With the right data structure, this is straightforward.
Most of this can be done with three tables: One to contain people, things and attributes (Merlyn, Ovid, Kudra, books, gold, valuable), one to contain verbs ( owns, is ), and one to contain tuples of person/thing/attribute, verb, person/thing/attribute. This leads to something like:
SELECT actor
FROM relations
WHERE verb = 'owns'
AND acted_on IN (
SELECT actor
FROM relations
WHERE verb = 'is'
AND acted_on = 'valuable'
);
This query, with proper data, can answer the question of 'who owns something valuable' in a very reasonable amount of time. You still do code generation, but now it's SQL instead of RE.
HTH,
Paul
-- Spring: Forces, Coiled Again!
| [reply] [d/l] |
|
With DBD::SQLite, this might be a viable option if I can figure out how to structure this. I've seen this discussed before and, if it works, I can push the hard part of matching down to the C level and get a huge performance boost. I'll have to see how robust the SQLite SQL implementation is. As I recall, it's pretty good (and here's an instance where I think a typeless database like SQLite is fine).
| [reply] |
|
| [reply] |
|
+----------+
| Facts |
+----------+
| verb |
| subject |
| object |
+----------+
That limits me to simple things such as "owns Ovid gold". However, what if I want to express "gives Ovid books kudra"? In this case, there's an implied prepositional phrase "to kudra" that doesn't fit and this tremendously limits the utility of this approach.
My other option would be to create a recursive tree structure with arbitrary depth. I've done that before and it's not fun, but I can see no other way to approach this.
| [reply] |
|
| [reply] |
Re: Being Forced to Fork with Nested Regular Expressions
by adrianh (Chancellor) on Jan 02, 2004 at 17:31 UTC
|
Any suggestions to get around this, or am I stuck?
With regexes I think you'll remain stuck. You'll also restrict yourself to assertions about simple strings which I imagine you'll quickly find restrictive.
Personally I think using the call stack to implement your backtracking will be a lot easier - but I would say that wouldn't I :-)
| [reply] |
|
| [reply] |
|
Somewhat belated reply ;-)
Even if you don't use the call stack, I think that the regex engine is probably the wrong choice - it's just not made to be used that way easily (as you've found out :-)
Implementing backtracking isn't really that hard. All you really need is a stack. I'd start there if it was me.
| [reply] |
Re: Being Forced to Fork with Nested Regular Expressions
by halley (Prior) on Jan 02, 2004 at 18:12 UTC
|
I also wanted to abuse the regex system with twelve-level-deep s///e recursion to implement my Pentominos Solving Quine, but instead found that perl would crash horribly if it tried to recurse there.
for $pattern (@patterns)
{
while ($data =~ m/(?=$pattern)/g)
{
do_recurse($data, pos($data), $pattern);
# $data is the source
# pos($data) is the found place in the souce
++pos($data);
}
}
The alternative method uses pos() as an lvalue and m/(?=)/g as in the loop above, to allow me to iterate through matches yet not recurse via any regex code-evaluating trick. I do recurse, but not by getting the regex to do the call.
-- [ e d @ h a l l e y . c c ]
| [reply] [d/l] [select] |
Re: Being Forced to Fork with Nested Regular Expressions
by Aristotle (Chancellor) on Jan 02, 2004 at 17:41 UTC
|
| [reply] |
|
I've certainly tried a multi-level hash structure, but I started to get too complicated. When you say "entanglement", though, it makes me think you are implying superpositions. I've never actually tried that route. Very interesting idea, though.
| [reply] |
|
| [reply] |
Re: Being Forced to Fork with Nested Regular Expressions
by diotalevi (Canon) on Jan 04, 2004 at 01:12 UTC
|
I wrote Regexp::Approx - Use fuzzy regular expressions (and forgot to submit it to CPAN) to solve the re-entrant regex problem for my specific problem. I forked during INIT, kept some file handles pointing to and from the child and then would send all the re-entrancy-requiring work to the child. You could pre-fork a number of children and then create more as needed. Alternatively, you could create a backtracking module for us and allow us to stop abusing regexes just to get at an already written engine.
| [reply] |
Re: Being Forced to Fork with Nested Regular Expressions
by mnc (Beadle) on Jan 05, 2004 at 05:18 UTC
|
my $code = <<END_CODE;
owns(merlyn,gold).
owns(ovid,books).
owns(kudra,gold).
valuable(perl).
valuable(gold).
valuable(corinna).
query :-
owns(X,Y), valuable(Y),
writef('["%t", "%t"], ',[X,Y]).
main :-
writef('[ '),
bagof(_,query,_),
writef(']\n').
END_CODE
my $tmpfile = "deleteme.pro";
open(TMP,">$tmpfile"); print TMP $code; close(TMP);
my $result = `pl -q -f deleteme.pro -t main`;
unlink($tmpfile);
print $result;
yields this
[ ["merlyn", "gold"], ["kudra", "gold"], ]
using SWI-Prolog.
Perl is great at generating code, handing it to an industrial-strength backtracking engine, and scraping the result (though there is also Language::Prolog::Yaswi
et.al.).
| [reply] [d/l] [select] |