Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elegant wat of filtering sets in sparql like style #66

Open
CICS-Oleg opened this issue Mar 7, 2025 · 3 comments
Open

Elegant wat of filtering sets in sparql like style #66

CICS-Oleg opened this issue Mar 7, 2025 · 3 comments
Assignees
Labels
question Further information is requested tutorial Tutorial question

Comments

@CICS-Oleg
Copy link
Contributor

CICS-Oleg commented Mar 7, 2025

Consider we have example database and query in sparql:

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .
SELECT  ?title ?price
WHERE   { ?x ns:price ?price .
          FILTER (?price < 30.5)
          ?x dc:title ?title . }

The resul would be:

title	price
"The Semantic Web"	23

Let's try to reproduce this example in metta. Database will look like this:

(book1 title sprql-tutorial)
(book1 price 42)
(book2 title semantic-web)
(book2 price 23)

The question is: do we have more elegant way to gain the same result than using code below?

!(match &self ($x price $y)
            (if (< $y 30.5)
            (match &self ($x title $z) ($z $y))
            Empty))

The result would be just what we need:

[(semantic-web 23)]

@CICS-Oleg CICS-Oleg added question Further information is requested tutorial Tutorial question labels Mar 7, 2025
@CICS-Oleg
Copy link
Contributor Author

I've noticed interesting thing. When we populate atomspace with more atoms:

(book3 title b3)
(book3 price 42)
(book4 title b4)
(book4 price 23)
(book5 title b5)
(book5 price 42)
(book6 title b6)
(book6 price 23)
(book7 title b7)
(book7 price 42)
...

and so on, running previously mentioned !(match ...) code sometimes (every 3-4 attempts) gives Segmentation fault (core dumped) error.

@CICS-Oleg
Copy link
Contributor Author

When it works it works correctly. The result is
[(b8 23), (b16 23), (b4 23), (b14 23), (b12 23), (semantic-web 23), (b10 23), (b6 23)]

@Necr0x0Der
Copy link
Contributor

First of all, I never get segfault in such cases.
As for "more elegant way", it depends...
Your code:

!(match &self ($x price $y)
            (if (< $y 30.5)
            (match &self ($x title $z) ($z $y))
            Empty))

is an efficient way to do such queries, since the interpreter stomspace doesn't have range-based indexing for numeric values. There were ideas to implement custom indexing for grounded types, but they have not been implemented. So, what can be done now with the interpreter atomspace is to query for one pattern, filter out unnecessary results and query for the second pattern. It looks ok. The difference with SPARQL is only that all the parts are packed in one query there, while you need to write match twice in MeTTa. However,

  • You can write something like this:
!(match &self
   (, ($x price $y)
      ($x title $z))
   (if (< $y 30.5) ($z $y) Empty))

It will less efficient (most likely), because it will query the second part of the pattern before filtering. It looks somewhat more elegant, though. So, it might be worthy to measure performance.

  • You can write a bunch of functions to make queries look more concise, e.g.
(= (price $x)
   (unify &self ($x price $y) $y Empty))
(= (title $x)
   (unify &self ($x title $y) $y Empty))
(= (ift True $r) $r)
(= (ift $b $r) Empty)

!(ift (< (price $x) 30.5)
      ((title $x) (price $x)))

(price $x) is executed twice here, but if there is result cashing, it's ok (I'm not sure if it is still there, though). If there is no, it might be rewritten in a more efficient way. The query itself looks quite elegant. One may have price and title as functions from the beginning, but whether it is a good idea or not depends on the usage.

  • There are also other possible ways, how one can try representing queries with filters in MeTTa compactly and process them by a function specially design for it (e.g., get a tuple of patterns including FILTER and unfold them into a sequence of match, if, etc.).
  • Some atomspaces, like MORK, may have an internal capability to filter out numeric components of patterns. If one or another "more elegant" way of representing such queries in MeTTa turn out to be slow, resorting to a specially designed space might be needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested tutorial Tutorial question
Projects
None yet
Development

No branches or pull requests

3 participants