Re: [Factor-talk] Directed graph queries via closure?

2013-03-24 Thread CW Alston
John, Alex -

Thanks for these very interesting replies. It seems I am looking past a
simple interpretation of what *closure* is aiming to do,
on one hand, yet I've also dog-paddled into the deep end of the graph
development pool. Curiouser & curiouser!
Both insights are helpful; I'll try to squint them into focus, 'cuz I
really want to use this idiom.

Cheers!
~cw

On Sun, Mar 24, 2013 at 9:28 AM, Alex Vondrak  wrote:

> The graphs vocabulary is pretty primitive.  Until recently, it belonged to
> Factor's core vocabulary root, used early-on in the bootstrapping process.
> [1]  It was written awhile ago, using idioms that existed before the
> current sets vocabulary. [2]  But mostly, it's not much of a
> general-purpose graph library.  The only purpose it's built for is its
> limited usage in cross-referencing (e.g., in the classes, tools.crossref,
> and compilers.crossref vocabs).  There was some work on a better vocab, but
> it's unmaintained and incomplete. [3]
>
> The graphs vocab treats directed graphs as a hash table from a vertex to a
> set of vertices representing its in-neighborhood a.k.a. predecessor set.
> [4]  In various parts of the code base (not just the graphs vocab), you
> still see hashtables getting used as sets [5], so hashtables like H{ { 1 1
> } } are used instead of HS{ 1 }.  Thus, we get the following:
>
> IN: scratchpad USE: graphs
> IN: scratchpad H{ } ! this is our graph
> IN: scratchpad 1 { 2 3 } pick add-vertex ! add the edges 1 -> 2 & 1 -> 3
> IN: scratchpad . ! show the graph
> H{ { 2 H{ { 1 1 } } } { 3 H{ { 1 1 } } } }
>
> Alternatively, you could think of `add-vertex` as instead adding the edges
> 1 <- 2 & 1 <- 3.  Then the digraph becomes a hash table from vertices to
> out-neighborhoods, and the `closure` word makes more sense.  But the docs
> [7] insist on the above interpretation!  And it's a more ordinary way to
> read the call---think like in graphviz, where you would write `1 -> { 2 3
> }`.
>
> The `closure` word computes the transitive closure of the graph [6] at a
> given vertex---telling us which vertices are reachable from the input
> vertex.  Instead of taking a graph as its input, it takes a quotation that
> tells you how to get the in/out-neighborhood of any given vertex.  Now, the
> way the graphs vocab is set up, this pretty much means you'll get the
> transitive closure flowing in the *backwards* direction of your edges,
> because your hashtable will only be able to access the vertex's
> in-neighborhood.  Which is confusing!  But again, suitable for the graphs
> vocab's usages.
>
> An example would be clearer.  So, say we set up the following:
>
> IN: scratchpad USE: graphs
> IN: scratchpad H{ } clone ! our graph
> IN: scratchpad 1 { 2 } pick add-vertex ! 1 -> 2
> IN: scratchpad 2 { 3 } pick add-vertex ! 2 -> 3
> IN: scratchpad 3 { 4 } pick add-vertex ! 3 -> 4
> IN: scratchpad dup . ! our graph: 1 -> 2 -> 3 -> 4
> H{ { 4 H{ { 3 3 } } } { 2 H{ { 1 1 } } } { 3 H{ { 2 2 } } } }
> IN: scratchpad '[ _ at ] ! quot to get the in-neighborhood of a vertex
>
> Now we can start querying the `closure`.  But somewhat confusingly, it's a
> "backwards" closure.  Maybe think of it as the closure of the graph "4 -> 3
> -> 2 -> 1" instead of "1 -> 2 -> 3 -> 4".
>
> IN: scratchpad 1 over closure .
> H{ { 1 1 } }
> IN: scratchpad 2 over closure .
>
> H{ { 1 1 } { 2 2 } }
> IN: scratchpad 3 over closure .
> H{ { 1 1 } { 2 2 } { 3 3 } }
> IN: scratchpad 4 over closure .
> H{ { 1 1 } { 2 2 } { 3 3 } { 4 4 } }
>
> Or how about trying this graph on for size?
>
> IN: scratchpad H{ } clone
> IN: scratchpad 1 { 2 3 } pick add-vertex
> IN: scratchpad 2 { 4 5 } pick add-vertex
> IN: scratchpad 3 { 6 } pick add-vertex
> IN: scratchpad '[ _ at ]
> IN: scratchpad 6 over closure .
> H{ { 1 1 } { 6 6 } { 3 3 } }
> IN: scratchpad 5 over closure .
> H{ { 1 1 } { 5 5 } { 2 2 } }
> IN: scratchpad 4 over closure .
> H{ { 4 4 } { 1 1 } { 2 2 } }
> IN: scratchpad 3 over closure .
> H{ { 1 1 } { 3 3 } }
> IN: scratchpad 2 over closure .
>
> H{ { 1 1 } { 2 2 } }
> IN: scratchpad 1 over closure .
> H{ { 1 1 } }
>
> Now, the duplicated code in the classes vocab has a much shorter
> explanation: that was John fucking around with speed improvements a couple
> weeks back. :) [8]  He uses HS{ } instead of H{ } to represent the sets,
> since (as explained) H{ } is kind of vestigial.  Then, sets:members is used
> to turn the HS{ } into a sequence. [9]
>
> Hope that helps,
> --Alex Vondrak
>
> [1] See
> http://factor-language.blogspot.com/2010/01/factors-bootstrap-process-explained.htmlfor
>  more on that.  Pretty much all the links are now broken, but you can
> easily track down the source code at https://github.com/slavapestov/factor
>
> [2]
> https://github.com/slavapestov/factor/commit/0f0571e48ad5e91d5fdf3717204d3812f0e72787
>
> [3]
> https://github.com/slavapestov/factor/tree/master/unmaintained/graph-theory
>
> [4] https://en.wikipedia.org/wiki/Adjacent_%28graph_theory%29#Direction
>
> [5] http://docs.

Re: [Factor-talk] Directed graph queries via closure?

2013-03-24 Thread Alex Vondrak
The graphs vocabulary is pretty primitive.  Until recently, it belonged to
Factor's core vocabulary root, used early-on in the bootstrapping process.
[1]  It was written awhile ago, using idioms that existed before the
current sets vocabulary. [2]  But mostly, it's not much of a
general-purpose graph library.  The only purpose it's built for is its
limited usage in cross-referencing (e.g., in the classes, tools.crossref,
and compilers.crossref vocabs).  There was some work on a better vocab, but
it's unmaintained and incomplete. [3]

The graphs vocab treats directed graphs as a hash table from a vertex to a
set of vertices representing its in-neighborhood a.k.a. predecessor set.
[4]  In various parts of the code base (not just the graphs vocab), you
still see hashtables getting used as sets [5], so hashtables like H{ { 1 1
} } are used instead of HS{ 1 }.  Thus, we get the following:

IN: scratchpad USE: graphs
IN: scratchpad H{ } ! this is our graph
IN: scratchpad 1 { 2 3 } pick add-vertex ! add the edges 1 -> 2 & 1 -> 3
IN: scratchpad . ! show the graph
H{ { 2 H{ { 1 1 } } } { 3 H{ { 1 1 } } } }

Alternatively, you could think of `add-vertex` as instead adding the edges
1 <- 2 & 1 <- 3.  Then the digraph becomes a hash table from vertices to
out-neighborhoods, and the `closure` word makes more sense.  But the docs
[7] insist on the above interpretation!  And it's a more ordinary way to
read the call---think like in graphviz, where you would write `1 -> { 2 3
}`.

The `closure` word computes the transitive closure of the graph [6] at a
given vertex---telling us which vertices are reachable from the input
vertex.  Instead of taking a graph as its input, it takes a quotation that
tells you how to get the in/out-neighborhood of any given vertex.  Now, the
way the graphs vocab is set up, this pretty much means you'll get the
transitive closure flowing in the *backwards* direction of your edges,
because your hashtable will only be able to access the vertex's
in-neighborhood.  Which is confusing!  But again, suitable for the graphs
vocab's usages.

An example would be clearer.  So, say we set up the following:

IN: scratchpad USE: graphs
IN: scratchpad H{ } clone ! our graph
IN: scratchpad 1 { 2 } pick add-vertex ! 1 -> 2
IN: scratchpad 2 { 3 } pick add-vertex ! 2 -> 3
IN: scratchpad 3 { 4 } pick add-vertex ! 3 -> 4
IN: scratchpad dup . ! our graph: 1 -> 2 -> 3 -> 4
H{ { 4 H{ { 3 3 } } } { 2 H{ { 1 1 } } } { 3 H{ { 2 2 } } } }
IN: scratchpad '[ _ at ] ! quot to get the in-neighborhood of a vertex

Now we can start querying the `closure`.  But somewhat confusingly, it's a
"backwards" closure.  Maybe think of it as the closure of the graph "4 -> 3
-> 2 -> 1" instead of "1 -> 2 -> 3 -> 4".

IN: scratchpad 1 over closure .
H{ { 1 1 } }
IN: scratchpad 2 over closure .
H{ { 1 1 } { 2 2 } }
IN: scratchpad 3 over closure .
H{ { 1 1 } { 2 2 } { 3 3 } }
IN: scratchpad 4 over closure .
H{ { 1 1 } { 2 2 } { 3 3 } { 4 4 } }

Or how about trying this graph on for size?

IN: scratchpad H{ } clone
IN: scratchpad 1 { 2 3 } pick add-vertex
IN: scratchpad 2 { 4 5 } pick add-vertex
IN: scratchpad 3 { 6 } pick add-vertex
IN: scratchpad '[ _ at ]
IN: scratchpad 6 over closure .
H{ { 1 1 } { 6 6 } { 3 3 } }
IN: scratchpad 5 over closure .
H{ { 1 1 } { 5 5 } { 2 2 } }
IN: scratchpad 4 over closure .
H{ { 4 4 } { 1 1 } { 2 2 } }
IN: scratchpad 3 over closure .
H{ { 1 1 } { 3 3 } }
IN: scratchpad 2 over closure .
H{ { 1 1 } { 2 2 } }
IN: scratchpad 1 over closure .
H{ { 1 1 } }

Now, the duplicated code in the classes vocab has a much shorter
explanation: that was John fucking around with speed improvements a couple
weeks back. :) [8]  He uses HS{ } instead of H{ } to represent the sets,
since (as explained) H{ } is kind of vestigial.  Then, sets:members is used
to turn the HS{ } into a sequence. [9]

Hope that helps,
--Alex Vondrak

[1] See
http://factor-language.blogspot.com/2010/01/factors-bootstrap-process-explained.htmlfor
more on that.  Pretty much all the links are now broken, but you can
easily track down the source code at https://github.com/slavapestov/factor

[2]
https://github.com/slavapestov/factor/commit/0f0571e48ad5e91d5fdf3717204d3812f0e72787

[3]
https://github.com/slavapestov/factor/tree/master/unmaintained/graph-theory

[4] https://en.wikipedia.org/wiki/Adjacent_%28graph_theory%29#Direction

[5] http://docs.factorcode.org/content/article-assocs-sets.html

[6] https://en.wikipedia.org/wiki/Transitive_closure#In_graph_theory

[7] http://docs.factorcode.org/content/word-add-vertex%2Cgraphs.html

[8]
https://github.com/slavapestov/factor/commit/03e6f48943c767d286e402b5c1833e8673339b3dWhich,
incidentally, is also around the time graphs got moved from core to
basis:
https://github.com/slavapestov/factor/commit/3ffacf75d269d58f6f28fe14590f6e472a6fa6cf

[9] http://docs.factorcode.org/content/word-members,sets.html
--
Everyone hates slow websites. So d

Re: [Factor-talk] Directed graph queries via closure?

2013-03-24 Thread John Benediktsson
The change to ``classes.private`` was to simplify the code, since it was a
simplified collection routine, albeit very similar to what is in ``graphs``.

If you try out the graphs code:

CONSTANT: my-graph H{
{ 1 H{ { 1 1 } { 2 2 } } }
{ 2 H{ { 3 3 } { 6 6 } } }
{ 4 H{ { 4 4 } { 5 5 } } }
{ 5 H{ { 5 5 } { 1 1 } } }
{ 6 H{ { 6 6 } { 1 1 } } }
}

IN: scratchpad 2 [ my-graph at ] closure keys natural-sort .
{ 1 2 3 6 }

IN: scratchpad 3 [ my-graph at ] closure keys natural-sort .
{ 3 }

IN: scratchpad 4 [ my-graph at ] closure keys natural-sort .
{ 1 2 3 4 5 6 }

You can see it follows all the edges generated by the quotation (my-graph
at) from a starting vertex.

If it isn't the right abstraction for you, I'm sure it wouldn't be too hard
to write a different routine?




On Sun, Mar 24, 2013 at 12:48 AM, CW Alston  wrote:

> Greetings folks -
>
>
> I'm experimenting with directed graph possibilites over an inverted index
> (of terms in files)
>
> that I've designed. I'm stumbling on the use of the word closure defined
> IN: graphs,
>
> using hashtables:
>
>
> USING: graphs.private kernel ;
>
> IN: graphs
>
> : closure ( obj quot -- assoc )
>
> H{ } clone [ swap (closure) ] keep ; inline
>
>
> The article on 'Directed graph utilities' suggests that:
>
>
> "You can perform queries on the graph:
>
>  closure ( obj quot -- assoc )
>
>
> Directed graphs are used to maintain cross-referencing information for
> Definitions."
>
>
> I want to implement just such cross-referencing & querying with my
> inverted index graph.
>
> It seems there are no example usages of the graphs-vocab closure, but
> there is a dopplegänger
>
> definition of closure IN: classes.private, which appears to do the same
> work using hash-sets:
>
>
> USING: kernel ;
>
> IN: classes.private
>
> : closure ( obj quot -- set )
>
> HS{ } clone [ swap (closure) ] keep ; inline
>
>
> I find the only(?) example use of the classes.private closure is in the
> definition of class-usages,
>
> which is opaque to me. I can't suss out what the construction 
> sets:membersthere is doing.
>
> Although the recursive (closure) in its def has an obvious analogue in
> graph's (closure), both
>
> are a mite hairy.
>
>
> Can anyone soothe my perplexity with an illustration using closure on a
> directed graph?
>
> Much obliged,
>
> ~cw
>
>
>
> --
> Everyone hates slow websites. So do we.
> Make your web apps faster with AppDynamics
> Download AppDynamics Lite for free today:
> http://p.sf.net/sfu/appdyn_d2d_mar
> ___
> Factor-talk mailing list
> Factor-talk@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/factor-talk
>
>
--
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar___
Factor-talk mailing list
Factor-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/factor-talk


[Factor-talk] Directed graph queries via closure?

2013-03-24 Thread CW Alston
Greetings folks -


I'm experimenting with directed graph possibilites over an inverted index
(of terms in files)

that I've designed. I'm stumbling on the use of the word closure defined
IN: graphs,

using hashtables:


USING: graphs.private kernel ;

IN: graphs

: closure ( obj quot -- assoc )

H{ } clone [ swap (closure) ] keep ; inline


The article on 'Directed graph utilities' suggests that:


"You can perform queries on the graph:

 closure ( obj quot -- assoc )


Directed graphs are used to maintain cross-referencing information for
Definitions."


I want to implement just such cross-referencing & querying with my inverted
index graph.

It seems there are no example usages of the graphs-vocab closure, but there
is a dopplegänger

definition of closure IN: classes.private, which appears to do the same
work using hash-sets:


USING: kernel ;

IN: classes.private

: closure ( obj quot -- set )

HS{ } clone [ swap (closure) ] keep ; inline


I find the only(?) example use of the classes.private closure is in the
definition of class-usages,

which is opaque to me. I can't suss out what the construction
sets:membersthere is doing.

Although the recursive (closure) in its def has an obvious analogue in
graph's (closure), both

are a mite hairy.


Can anyone soothe my perplexity with an illustration using closure on a
directed graph?

Much obliged,

~cw
--
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar___
Factor-talk mailing list
Factor-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/factor-talk