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

Allow arbitrary additional keys in a graph? #53

Open
yuhan0 opened this issue Oct 2, 2019 · 4 comments
Open

Allow arbitrary additional keys in a graph? #53

yuhan0 opened this issue Oct 2, 2019 · 4 comments

Comments

@yuhan0
Copy link

yuhan0 commented Oct 2, 2019

An Ubergraph exposes the hash map interface, however the implementation of clojure.core map functions only allows for a closed set of keys and turns everything else into a no-op:

(get [this key default-value]

This seems to go against the Clojure design philosophy of having open data structures – I should be able to assoc extra information to the graph and have it be "ignored" by any function that doesn't request for it.

(-> (uber/digraph)
  (uber/add-edges [1 2])
  (assoc
    :extra/info "foo"
    :date-created "2019-10-02")
  (keys))
;; => (:node-map :allow-parallel? :undirected? :attrs :cached-hash)

What's the rationale for this behavior? Loom graphs for instance allow for it by default since they are plain records.
Is there some other API for adding attributes to the graph as a whole?

@Engelberg
Copy link
Owner

Engelberg commented Oct 2, 2019 via email

@yuhan0
Copy link
Author

yuhan0 commented Oct 4, 2019

Thanks for the reply! I got what I needed by directly adding a namespaced key to the attrs map of the ubergraph - not sure what the practical difference is versus using metadata, and equality semantics stays the same.

(defn add-graph-attr
  [g k v]
  (assoc-in g [:attrs ::uber/graph-attrs k] v))

(defn graph-attr
  [g attr]
  (get-in g [:attrs ::uber/graph-attrs attr]))

(let [g (uber/graph)
      h (add-graph-attr g :date-created "2019-10-02")]

  (:attrs h)
  ;; => #:ubergraph.core{:graph-attrs {:date-created "2019-10-02"}}

  (graph-attr h :date-created)
  ;; => "2019-10-02"

  (= g h)
  ;; => true
  )

My use case is doing graph rewriting and transformation, where I have to add certain flags to the entire graph to store additional information like "deleted nodes"

Would something like this be useful in Ubergraph core? I could open a PR.

@Engelberg
Copy link
Owner

I think you've correctly identified that Ubergraph would benefit from graph attributes, and I'm glad you were able to find a reasonable workaround for your specific use case.

I would like to incorporate support for graph attributes, but am interested in making sure it is done with care. In my mind, here's the kind of solution I'm looking for:

There are two types of graph attributes: those that affect graph equality and those that don't. The graph attributes that don't affect equality would be stored in the metadata and set and accessed using Clojure's standard metadata facilities. Coding this would require adding a metadata map to the deftype and implementing the corresponding interfaces (which currently are stubbed out to do nothing).

Then, I'd want full implementation of graph attributes which do affect hashing and equality. I would be inclined to store this info in the existing attrs part of the data structure under a custom key like :ubergraph/graph-attrs, or another viable option would be to have a separate map in the data structure just devoted to graph attributes. In either case, the hashing and equality would need to know to look there.

Then, a protocol would need to be defined and implemented to access, add, and remove graph attributes.

If you are motivated to do all that, I'd be enthused for the contribution. Now that we've discussed it, this is something I will likely add in the future, but realistically I only am able to devote significant development time to ubergraph once a year or so, and I just did a fairly big series of improvements, so it will be a while before I can get back to it and make those changes.

@dcj
Copy link

dcj commented Feb 18, 2020

Just chiming in here: I agree that "Ubergraph would benefit from graph attributes". I am currently working on a project that builds graphs from aircraft flight procedure datasets, the graph itself represents the procedure, and there is a need to place attributes on the procedure/graph, in addition to the nodes and edges. Currently I am using Loom, and putting the graph attibutes into the metadata. I'm planning to experiment with Ubergraph instead of Loom as this work progresses. If I ever get that far, I will take a look at the proposed design above...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants