Fork me on GitHub

I’m looking to hopefully kick off the merge with main branch in the next week or two which will likely see a bunch of performance optimisations brought across. However there is some work on the underlying libraries I need to catch myself up on and also need to figure out some kind of benchmarking setup. I am looking to carve out some time so that I can do this in the open and start including people in the development effort of Datahike. Are you also familiar with our Discord server @goomba. We are happy to keep answering here. It’s just a little annoying that we lose history of conversation here.

👍 1
Lone Ranger17:10:20

@grounded_sage I sent a message on the discord

👍 1
Jack Park20:10:16

Question (naive?) about nesting datoms. I once saw a youtube on the datomic structure - do not recall the details but it might have been about #datascript - my question lies in the context of Datahike; the speaker dropped a datom into the value slot of another datom; as I recall, the program reacted by replacing that datom with a number - presumably the identity of that datom. But, Datahike's Datom definition does not include an integer. I'd like to be able to do that, to create complex - compound Datoms. Google hasn't been much help. Thanks in advance for thoughts.


I think you might be referring to "lookup refs"? Basically, if you have a :db/unique :db.unique/identity attribute, like :user/email, you can use [:user/email ""] in place of the entity's numeric id. Does that sound like what you're thinking of?

Jack Park21:10:05

I'll confess that it doesn't sound like what I had in mind, but that could be me. I'll also confess that I'm terrible at explaining this. Let me illustrate with this: • A datom: A causes B • A datom which uses that one: C thinks A causes B Notice how I use the term Datom to refer to a tuple which states a "fact". Could be wrong there too. But, this is about nesting structures. Ultimately, does Datalog let me do that? If so, can Datahike do that? I cannot see any mechanism in the code that would allow that, but did not make any experiments to see (yet).

Jack Park21:10:37

I do this in tuples in my Java code, which creates structures like { C, thinks, {A, causes, B}}. To do that, I must put an identifier (id) on each tuple (datom) which Datahike doesn't have. I also put an "objectType" attribute, so my tuples are far longer than any datom in Datahike. There are more field.s


I don't think this is possible exactly the way you want to do it, unfortunately


I think you would have to model the "nested" datom as a separate entity, something like

{:fact/objectType :fact.type/CausalRelation
 :fact/subject A
 :fact.subject/causes B}


In datascript, you can just drop in any old object as a value (like [:db/add C :thinks [A :causes B]]), and this used to be the case in datahike, until schema was added. I think there is a blob type that you could use to do this (as with datomic), but it wouldn't really be queryable the way you'd want (in datascript either). So if you want that information to be queryable, you probably need to model them as entities in their own right.

Jack Park21:10:35

So, that's right - it was Datascript where that happened. That's what I have in mind. Modeling them as entities really does, I suspect, describe what I have in mind, which means: every entity has identity and the entity itself is a compound, as you sketched. It strikes me that you might have offered a solution, one I intend to explore in my project

👍 1
Björn Ebbinghaus09:10:24

@U0288B00494 I think modelling the Cause-Effect structure as a separate entity is the right way.

[; Your agents / events / whatever
 {:db/id "A", :label "A"}, {:db/id "B", :label "B"}, {:db/id "C", :label "C"},

 ; your causality
 {:db/id "causality", :cause "A", :effect "B"},

 [:db/add "A" :knows "causality"]
 [:db/add "C" :thinks "causality"]]

The resulting datoms:
[1 :label "A"]
[2 :label "B"]
[3 :label "C"]
[4 :cause 1]
[4 :effect 2]
[1 :knows 4]
[3 :thinks 4]

Björn Ebbinghaus10:10:17

You can even model:

; [[A :causes B] :causes C]
[{:db/id "causality1", :cause "A", :effect "B"},
 {:cause "causality1", :effect "C"}]

; [A & B :causes C] ; With :cause as a cardinality many attribute
{:cause #{"A" "B"}, :effect "C"}  
Because you mentioned probabilities: You can add probabilities to events and causalities. P(A) {:db/id "A", :probability 0.7} P(B | A) {:db/id "causality", :cause "A", :effect "B", :probability 0.5} To model certainty: "C thinks with 60% certainty that A causes B" :
[{:db/id "A", :label "A"}, {:db/id "B", :label "B"}, {:db/id "C", :label "C"},

 ; your causality
 {:db/id "causality", :cause "A", :effect "B"},
 [:db/add "A" :thinks {:what "causality", :certainty 1.0}]
 [:db/add "C" :thinks {:what "causality", :certainty 0.6}]]

;; OR

 [:db/add "A" :thinks {:cause "A", :effect "B", :probability 1.0}]
 [:db/add "C" :thinks {:cause "A", :effect "B", :probability 0.6}]]
This depends on your domain and needs

Björn Ebbinghaus10:10:12

And you can define datalog rules for your queries: P(A ∧ B):

[[(p-and ?a ?b ?p-a-and-b-happen)
  [?causality :cause ?a]
  [?causality :effect ?b]
  [?causality :probability ?p-a-causes-b]
  [?a :probability ?p-a-happens]
  [(* ?p-a-happens ?p-a-causes-b) ?p-a-and-b-happen]]

 ; so that the order of ?a and ?b doesn't matter.
 [(p-and ?a ?b ?p-a-and-b-happen)
  [?causality :cause ?b]
  [?causality :effect ?a]
  (p-and ?b ?a ?p-a-and-b-happen)]

 ; when ?a and ?b are independent. 
 [(p-and ?a ?b ?p-a-and-b-happen)
  [?a :probability ?p-a-happens]
  [?b :probability ?p-b-happens]
  [(* ?p-a-happens ?p-b-happens) ?p-a-and-b-happen]]]

👍 1
Jack Park18:10:46

@U4VT24ZM3 Great comments. Thank you very much!