> ...noticed that the attribute names in the datoms are a lot like the port
labels in port graphs. A port label is essentially an attribute key whose
value is the edges incident to it. And when you chain data patterns in
Datalog queries, that's a lot like navigating through a graph.

That's very much in line with what I was thinking you might want to do in
this setting.

You should also take a look at the entity api. It let's you traverse the
graph via these entity objects which behave more or less like a dictionary
of the av pairs associated with a particular entity in the database.
Importantly though, when an attribute points to another entity (a reference
attribute), it is returned as yet another of these entity objects, letting
you traverse the graph using get, in a pretty similar fashion to what
you're describing.

http://docs.datomic.com/entities.html

You may also check out the pull api. It let's you pull facts out of the
graph as regular old maps by specifying what attributes & paths you wish to
pull out of the graph. The result is that you can read from the underlying
graph database as though it was a document store, but where the documents
are dynamically computed/queried from the graph based on the pull
expression you provide. You can also use pull expressions inside the
`:find` clause of either a DataScript of Datomic datalog query, which is
often a convenient way of specifying both a set of entities (via a datalog
query) and statement of facts to pull about them.

http://docs.datomic.com/pull.html

Collectively, these three interfaces give you quite a lot of expressiveness
and flexibility in how you query/traverse your data.



On Tue, Jan 2, 2018 at 12:31 PM, Ben Kovitz <bkov...@gmail.com> wrote:

> Christopher Small,
>
> Your suggestion to look into Datomic definitely turned up a new idea. I
> went through the Datalog tutorial at http://www.learndatalogtoday.org
> (which is excellent, by the way), and noticed that the attribute names in
> the datoms are a lot like the port labels in port graphs. A port label is
> essentially an attribute key whose value is the edges incident to it. And
> when you chain data patterns in Datalog queries, that's a lot like
> navigating through a graph.
>
> The new, hopefully simple, easy-to-use, and not error-prone idea is to use
> the clojure.lang.IPersistentMap  interface to query and update graphs.
> Nodes, edge, attribute names, port labels, and a few "reserved keywords"
> like :adj-nodes and :edge, could navigate the graph as if it were an
> ordinary nested map with get-in, assoc-in, and the like, without ever
> needing to wrap anything inside a record to tell what it is. Here are some
> sample queries and what they could return:
>
> (get-in g [node port-label :adj-nodes])
>   a coll of all the nodes with an edge to [node port-label]
> (get-in g [node port-label :adj-node])
>   one node with an edge to [node port-label], or nil
> (get-in g [node port-label])
>   true or false, according to whether node has a port named port-label
> (get-in g [node k])
>   value of node's attr k
> (get-in g [edge k])
>   value of edge's attr k
> (get g node-or-edge)
>   the entire map of attrs associated with node-or-edge, or nil if it does
> not exist
> (get-in g [node k1 k2 k3])
>   treat node's attrs as a nested map
> (get-in [node port-label :edges])
>   a coll of all the edges that link to [node port-label]
> (get-in [node port-label :edge])
>   a single edge that links to port-label, or nil
> (get-in [node port-label1 port-label2])
>   coll of all nodes that link to [node port-label1] from a port named
> port-label2
>
> And here are some function calls that would return a modified graph:
>
> (assoc-in g [node k] v)
>   sets node attr k to v
> (assoc-in g [edge k] v)
>   sets edge attr k to v  (and similarly for multiple keys)
> (assoc-in g [node1 port-label1 port-label2 node2] :edge)
>   makes an edge between [node1 port-label1] and [node2 port-label2]
> (assoc-in g [node1 port-label1 port-label2 :edge k] v)
>   sets value of edge attr k to v
>
> I haven't yet thought this through completely, and I suspect that some
> parts are still error-prone. For example, notice in the last function call
> that it's not clear whether you should include node2. The approach might be
> "too cute"—that is, brittle because it tries to impose one kind of
> structure (nested maps) onto one that isn't fully isomorphic (graphs).
>
> But I like the basic idea of having a "little language" for designating
> whatever you want, and the little language is nothing but a sequence that
> tells how to navigate through the graph to find (or make) what you're
> interested in.
>
> This would solve the fundamental problem of how to designate an edge
> without imposing type restrictions. For each connection point, you just
> have a sequence that describes a path to that point. If the sequence ends
> on a port label, the connection point is a port. If it ends on :edge, the
> connection point is an edge. So, instead of type restrictions, there are
> just a few reserved words in the tiny DSL for navigating the graph.
>
> This hopefully makes simple editing and querying of port graphs easy, but
> it does not even try to solve the problem of conveniently entering a graph.
> I figure that a "shorthand", i.e. a separate tiny DSL, is the solution for
> that. I found with my current implementation of port graphs that it really
> helped to use a custom shorthand for each specific type of graph. For
> example, there's a obvious and very nice shorthand for specifying graphs
> that represent mathematical expressions, but it's terrible for graphs of
> social networks. Graphs of social networks, though, can be conveniently
> described by their own custom sexprs.
>
> I figure that implementing it will force me to think this idea through the
> rest of the way. Here goes…
>
> --
> Ben Kovitz
> http://pages.iu.edu/~bkovitz/
>
>
> --
> 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 a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/
> topic/clojure/uSwY475pbGA/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/d/optout.

Reply via email to