Looking into it.

On Monday, October 1, 2012, Reinout Stevens wrote:

>
>
> On Saturday, September 29, 2012 11:10:38 PM UTC+2, David Nolen wrote:
>>
>> On Wed, Sep 26, 2012 at 9:20 AM, Reinout Stevens <rest...@vub.ac.be>wrote:
>>
>>> Hi,
>>>
>>>
>>> I'm the author of a DSL that allows reasoning over paths throughout
>>> graphs using core.logic ( 
>>> https://github.com/**ReinoutStevens/damp.qwal<https://github.com/ReinoutStevens/damp.qwal>).
>>>  We noticed that for larger graphs performance became horribly slow, even
>>> though there is no apparent reason why it should be. First investigations
>>> lead me to believe tabling was the issue. We use tabling to prevent
>>> infinite loops due to cycles in the graph. After writing a small testcase
>>> that exhibits the described problems I've noticed that it is a combination
>>> of tabling and looping over a list.
>>>
>>> In the test case we construct a linear graph (so: a graph where each
>>> node has a single successor). We want to asser that there exists a path
>>> from the start to the end node. This is done by using the logical rule trans
>>> [graph current next], which given a graph and the current node binds
>>> next to the possible successors. We write this query in three different
>>> ways. First, we try to succeed the goal trans as many times as needed,
>>> until we end up in the end state. Next, we do the same but tabling our
>>> loop. This prevents looping in case our graph would contain a cycle (in
>>> this case, there is no such cycle). Finally, instead of directly proving
>>> trans, we prove a list of goals. This list contains a single goal (trans).
>>> This last scenario runs much slower than the previous two, even though I
>>> don't see a large difference with the first two scenarios.
>>>
>>> In attachment the code of our test case. There are 3 functions at the
>>> end, each implementing one of the described scenarios. Note the difference
>>> between solve-goal and solve-goals.
>>>
>>> Any pointers how to solve the issue, or work around it are appreciated
>>>
>>
>> I took some time to look into this. The issue is that your terms are
>> quite complex - the entire graph is the first arg to the tabled goal! In
>> order for tabling to work this argument needs to be reified (completely
>> walked and all logic vars replaced with copies) and this is used as the
>> table cache key. As you can imagine this means given the way you've written
>> your program the entries in the table can get quite large and the
>> comparisons to determine whether a reusable cached answer term exists is
>> quite expensive!
>>
>> It's important to table at the right "level". Does this make sense and
>> can you formulate a solution so that you're not passing in the entire graph
>> as the first argument to the tabled goal?
>>
>> David
>>
>>
> Hi,
>
>
> I quickly changed the code so that the graph structure no longer contains
> the list of nodes, and the same behaviour still persists. For the actual
> implementation I have changed it to a function that returns a list of
> nodes, which can be compared in O(1) instead of looping over the data
> structure, and also here we get the same behaviour.
>
> Personally, I don't see the difference between calling solve-goal or
> solve-goals, as both should have an equally large table. The recursive step
> of solve-goals shouldn't do anything, as we are only passing a list
> containing a single item. In attachment the updated code (aka: just removed
> the :node key from the graph).
>
>
> Thanks for taking your time and looking into this,
>
>
> Reinout
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to 
> clojure@googlegroups.com<javascript:_e({}, 'cvml', 
> 'clojure@googlegroups.com');>
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com <javascript:_e({}, 'cvml',
> 'clojure%2bunsubscr...@googlegroups.com');>
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to