Thought I'd mention a really nice Graph visualization library that I like. 
It would be great to include this into any new Graph library project.

https://github.com/pallix/lacij

>From the readme:

"Lacij is a graph visualization library written in Clojure. It allows the 
*display 
and the dynamic modification of graphs as SVG documents* that can be viewed 
with a *Web browser* or with a *Swing component*. Undo/redo is supported 
for the dynamic modification. Automatic layout is provided for the 
visualization."

I like graphviz too, but this might be a better fit.

Cheers,
Avram


On Wednesday, June 19, 2013 5:57:02 AM UTC-7, Aysylu Biktimirova wrote:
>
> If you'd like to take a stab at integrating your proposed protocol into 
> Loom, I'd be happy to merge the changes. Thanks!
>
> On Tuesday, June 18, 2013 1:12:04 PM UTC-4, Stephen Kockentiedt wrote:
>>
>> That sounds great! I'll mail you my complete code in case you want to 
>> take a look at it or want to use parts of it. And in case I can help in any 
>> other way, feel free to ask.
>>
>> Am Dienstag, 18. Juni 2013 18:44:33 UTC+2 schrieb Aysylu Biktimirova:
>>>
>>> Stephen, thanks for reaching out to me! I really like your ideas and 
>>> agree with the issues you pointed out in Loom's API. I'd like to 
>>> incorporate your ideas into Loom to improve its API and have 1 graph 
>>> library in Clojure. I'm actively working on it and would be happy to 
>>> combine our efforts.
>>>
>>> There's one implementation of the API, as far as I know, 
>>> https://github.com/aysylu/loom/blob/titanium/src/loom/titanium.clj, which 
>>> integrates Loom with Titanium. I'm planning to refactor it out of Loom and 
>>> release as a separate project. Since I'm the author and the only maintainer 
>>> of Titanium+Loom, I'd be happy to handle the transition.
>>>
>>> On Tuesday, June 18, 2013 3:10:23 AM UTC-4, Stephen Kockentiedt wrote:
>>>>
>>>> My bad. I did only find the original repository of loom and thought it 
>>>> was abandoned. I should have taken more care while looking at it. My 
>>>> approach was apparently the same in abstracting multiple graph 
>>>> implementations under one API. However, I see some problems with Loom's 
>>>> API, namely:
>>>>
>>>> 1. The specifications of the protocol functions are very sparse. E.g., 
>>>> which nodes shall a directed graph return from neighbors? Successors, 
>>>> predecessors or both?
>>>> 2. How do I know if the graph implementation works by mutating the 
>>>> given object or returning a new one?
>>>> 3. Loom assumes that every graph is editable. That is definitely not 
>>>> the case.
>>>> 4. I think a protocol should be as easy to implement as possible. The 
>>>> additional functionality can be given by functions relying on the protocol 
>>>> functions. E.g., in the user API of my code, there is a function 
>>>> direct-predecessors which provides this functionality (albeit slow) 
>>>> for graph implementations which did not implement the corresponding 
>>>> protocol function:
>>>>
>>>> (defn direct-predecessors
>>>>   "Returns a set or sequence of all nodes n2 for which
>>>>    (has-edge? g n2 n) returns true. May not contain
>>>>    duplicates."
>>>>   [g n]
>>>>   (if (satisfies? p/PPredecessorGraph g)
>>>>     (p/direct-predecessors g n)
>>>>     (filter #(p/has-edge? g % n) (p/nodes g))))
>>>>
>>>> E.g., implementations of Loom's API need to provide two implementations 
>>>> of neighbors and need to implement add-nodes* instead of only add-node*. 
>>>> This may not be much more work to do. However, the easier the API, the 
>>>> more 
>>>> implementations there will be.
>>>>
>>>> Please, don't get me wrong. I think that Loom is a great project, has 
>>>> the same goals and, in terms of functionality, is way ahead of my efforts.
>>>>
>>>> Said all that, I definitely don't want there to be two competing graph 
>>>> APIs. That would be counterproductive. I see the following possible 
>>>> solutions:
>>>>
>>>> 1. I keep the code to myself and let loom be the sole graph API.
>>>> 2. We transfer the advantages of my proposal to Loom and change its 
>>>> API. Do you know of any implementations of the API outside Loom itself? If 
>>>> there are none, this should be possible without much trouble. Also, the 
>>>> README states that the API is alpha-stage.
>>>> 3. I publish my code and each API can be implemented in terms of the 
>>>> other one. I'm not sure that this is possible in a simple way. Maybe each 
>>>> protocol could be extended to java.lang.Object, which calls the 
>>>> protocols of the other API, but I don't know if that is feasible.
>>>>
>>>> Please tell me what you think. I will also send Aysylu an email so 
>>>> that she can chime in on the conversation.
>>>>
>>>>
>>>> Am Dienstag, 18. Juni 2013 07:02:52 UTC+2 schrieb Rob Lachlan:
>>>>>
>>>>> Loom was indeed working on this, and it's a very nice library.  One 
>>>>> thing that I particularly liked about Justin's design, was the ability to 
>>>>> run a graph algorithm without worrying about conforming to a particular 
>>>>> graph representation.  See for example the bread first search function, 
>>>>> here:
>>>>>
>>>>> https://github.com/jkk/loom/blob/master/src/loom/alg_generic.clj#L110
>>>>>
>>>>> All the bfs function requires is a neighbors function and and a start 
>>>>> vertex.  Simple and easy to use.
>>>>>
>>>>> Justin had said that he won't be actively developing loom for the 
>>>>> forseeable future; I was hoping to develop it further, but I only got as 
>>>>> far as implementing a max flow algorithm before the rest of my life got 
>>>>> in the way of my plans.  I know that Aysylu was doing a fair amount of 
>>>>> work 
>>>>> on loom, so I'd guess that her repo is the most advanced one.
>>>>>
>>>>> Stephen:
>>>>> I think the set of protocols above is good, better than Loom's in 
>>>>> fact; notably, the decision to make direct-predecessors optional is the 
>>>>> correct one, and a lot of graph libraries get that wrong.  
>>>>>
>>>>> If you want to compare how loom did it:
>>>>> https://github.com/jkk/loom/blob/master/src/loom/graph.clj
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Monday, June 17, 2013 1:14:34 PM UTC-7, dgrnbrg wrote:
>>>>>>
>>>>>> I think that there's already a project working on this called Loom. 
>>>>>> The furthest-developed fork is here: https://github.com/aysylu/loomwhich 
>>>>>> appears to have protocols for graphs, bindings to Titanium (the 
>>>>>> Clojurewerkz graph DB library), visualization support, and 
>>>>>> implementations 
>>>>>> of several algorithms.
>>>>>>
>>>>>> Maybe there's a way to incorporate these projects?
>>>>>>
>>>>>> On Monday, June 17, 2013 3:38:45 PM UTC-4, Stephen Kockentiedt wrote:
>>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> I want to create a graph API similar to what core.matrix is for 
>>>>>>> matrices. I have created some protocols which every graph 
>>>>>>> implementation 
>>>>>>> has to satisfy and a prototype implementation. Now I want your feedback 
>>>>>>> on 
>>>>>>> these protocols. Which functions do you want to see which aren't there? 
>>>>>>> Which functions should be changed? Are there problems with the general 
>>>>>>> design? Have you any other feedback?
>>>>>>>
>>>>>>> Here are the protocol definitions:
>>>>>>>
>>>>>>> (defprotocol PGraph
>>>>>>>   "Minimal functionality of a graph."
>>>>>>>   (directed? [g]
>>>>>>>     "Returns true if the graph is directed and false if the
>>>>>>>      graph is undirected. If it is undirected, all functions
>>>>>>>      taking two nodes must be commutative with regard to
>>>>>>>      these nodes.")
>>>>>>>   (nodes [g]
>>>>>>>     "Returns a set or sequence of all nodes of the graph. May
>>>>>>>      not contain duplicates.")
>>>>>>>   (has-edge? [g n1 n2]
>>>>>>>     "Returns true if the graph g has an edge from node n1
>>>>>>>      to node n2.")
>>>>>>>   (direct-successors [g n]
>>>>>>>     "Returns a set or sequence of all nodes n2 for which
>>>>>>>      (has-edge? g n n2) returns true. May not contain
>>>>>>>      duplicates."))
>>>>>>>
>>>>>>> (defprotocol PPredecessorGraph
>>>>>>>   "Optional functionality of a graph which can give a
>>>>>>>    list of all direct predecessors of a node."
>>>>>>>   (direct-predecessors [g n]
>>>>>>>     "Returns a set or sequence of all nodes n2 for which
>>>>>>>      (has-edge? g n2 n) returns true. May not contain
>>>>>>>      duplicates."))
>>>>>>>
>>>>>>> (defprotocol PEditableGraph
>>>>>>>   "Minimal functionality of an editable graph."
>>>>>>>   (mutable? [g]
>>>>>>>     "Returns true if the graph is mutated in place.
>>>>>>>      If true is returned, the other functions change
>>>>>>>      the graph passed as the first argument and return
>>>>>>>      the same graph object. If false is returned, the
>>>>>>>      functions return a new graph and the old graph is
>>>>>>>      unchaged.")
>>>>>>>   (add-node [g n]
>>>>>>>     "Adds the node n to the graph g. If it already
>>>>>>>      contained n, the graph will not be changed.")
>>>>>>>   (remove-node [g n]
>>>>>>>     "Removes the node n from the graph g. If it did
>>>>>>>      not contain n, the graph will not be changed.")
>>>>>>>   (add-edge [g n1 n2]
>>>>>>>     "Adds an edge from node n1 to node n2 to the graph g.
>>>>>>>      If one or both of the nodes is not present it will
>>>>>>>      be added to the graph. If the edge was already present,
>>>>>>>      the graph will not be changed.")
>>>>>>>   (remove-edge [g n1 n2]
>>>>>>>     "Removes the edge from node n1 to the node n2 from
>>>>>>>      the graph g. If it did not contain the edge, the graph
>>>>>>>      will not be changed."))
>>>>>>>
>>>>>>> (defprotocol PWeightedGraph
>>>>>>>   "Functionality of a graph whose edges can be weighted."
>>>>>>>   (edge-weight [g n1 n2]
>>>>>>>     "Returns the weight of the edge from node n1 to
>>>>>>>      node n2."))
>>>>>>>
>>>>>>> (defprotocol PEditableWeightedGraph
>>>>>>>   "Functionality of a weighted graph whose weights can be
>>>>>>>    changed."
>>>>>>>   (update-edge-weight [g n1 n2 f]
>>>>>>>     "Updates the weight of the edge from node n1 to node n2,
>>>>>>>      where f is a function taking the old value and returning
>>>>>>>      the new one. If the graph did not contain the edge, it
>>>>>>>      will be created."))
>>>>>>>
>>>>>>> (defprotocol PNodeDataGraph
>>>>>>>   "Functionality of a graph which stores data with its
>>>>>>>    nodes."
>>>>>>>   (node-data [g n]
>>>>>>>     "Returns the data of the node n."))
>>>>>>>
>>>>>>> (defprotocol PEditableNodeDataGraph
>>>>>>>   "Functionality of a graph which stores editable data
>>>>>>>    with its nodes."
>>>>>>>   (update-node-data [g n f]
>>>>>>>     "Updates the data of the node n, where f is a function
>>>>>>>      taking the old value and returning the new one. If the
>>>>>>>      graph did not contain the node, it will be added."))
>>>>>>>
>>>>>>> (defprotocol PEdgeDataGraph
>>>>>>>   "Functionality of a graph which stores data with its edges."
>>>>>>>   (edge-data [g n1 n2]
>>>>>>>     "Returns the data of the edge from node n1 to node n2."))
>>>>>>>
>>>>>>> (defprotocol PEditableEdgeDataGraph
>>>>>>>   "Functionality of a graph which stores editable data
>>>>>>>    with its edges."
>>>>>>>   (update-edge-data [g n1 n2 f]
>>>>>>>     "Changes the data of the edge from node n1 to n2, where
>>>>>>>      f is a function taking the old value and returning the
>>>>>>>      new one. If the graph did not contain the edge, it will
>>>>>>>      be added."))
>>>>>>>
>>>>>>

-- 
-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to