Skip to content

Commit

Permalink
Add reference couting
Browse files Browse the repository at this point in the history
  • Loading branch information
iddan authored and dennwc committed Dec 15, 2019
1 parent 28a8a2b commit 0bf3edf
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 8 deletions.
50 changes: 44 additions & 6 deletions inference/inference.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Class struct {
sub map[*Class]struct{}
ownProperties map[*Property]struct{}
inProperties map[*Property]struct{}
store *Store
}

// Name returns the class's name
Expand All @@ -34,6 +35,13 @@ func (class *Class) IsSubClassOf(superClass *Class) bool {
return false
}

func (class *Class) removeReference() {
class.references--
if class.references == 0 {
delete(class.store.classes, class.name)
}
}

// Property represents a RDF Property with the links to classes and other properties
type Property struct {
name quad.Value
Expand All @@ -42,6 +50,7 @@ type Property struct {
_range *Class
super map[*Property]struct{}
sub map[*Property]struct{}
store *Store
}

// Name returns the property's name
Expand Down Expand Up @@ -72,6 +81,13 @@ func (property *Property) IsSubPropertyOf(superProperty *Property) bool {
return false
}

func (property *Property) removeReference() {
property.references--
if property.references == 0 {
delete(property.store.properties, property.name)
}
}

// Store is a struct holding the inference data
type Store struct {
classes map[quad.Value]*Class
Expand All @@ -98,27 +114,33 @@ func (store *Store) GetProperty(name quad.Value) *Property {

func (store *Store) addClass(class quad.Value) *Class {
if c, ok := store.classes[class]; ok {
c.references++
return c
}
c := &Class{
name: class,
references: 1,
super: map[*Class]struct{}{},
sub: map[*Class]struct{}{},
ownProperties: map[*Property]struct{}{},
inProperties: map[*Property]struct{}{},
store: store,
}
store.classes[class] = c
return c
}

func (store *Store) addProperty(property quad.Value) *Property {
if p, ok := store.properties[property]; ok {
p.references++
return p
}
p := &Property{
name: property,
super: map[*Property]struct{}{},
sub: map[*Property]struct{}{},
name: property,
references: 1,
super: map[*Property]struct{}{},
sub: map[*Property]struct{}{},
store: store,
}
store.properties[property] = p
return p
Expand Down Expand Up @@ -200,21 +222,29 @@ func (store *Store) ProcessQuads(quads []quad.Quad) {
}

func (store *Store) deleteClass(class quad.Value) {
if _, ok := store.classes[class]; ok {
// TODO delete refrences
if c, ok := store.classes[class]; ok {
for sub := range c.sub {
c.removeReference()
delete(sub.super, c)
}
for super := range c.super {
c.removeReference()
delete(super.sub, c)
}
delete(store.classes, class)
}
}

func (store *Store) deleteProperty(property quad.Value) {
if p, ok := store.properties[property]; ok {
for super := range p.super {
p.removeReference()
delete(super.sub, p)
}
for sub := range p.sub {
p.removeReference()
delete(sub.super, p)
}
// TODO delete refrences
delete(store.properties, property)
}
}
Expand All @@ -223,7 +253,9 @@ func (store *Store) deleteClassRelationship(child quad.Value, parent quad.Value)
parentClass := store.GetClass(parent)
childClass := store.GetClass(child)
if _, ok := parentClass.sub[childClass]; ok {
parentClass.removeReference()
delete(parentClass.sub, childClass)
childClass.removeReference()
delete(childClass.super, parentClass)
}
}
Expand All @@ -232,7 +264,9 @@ func (store *Store) deletePropertyRelationship(child quad.Value, parent quad.Val
parentProperty := store.GetProperty(parent)
childProperty := store.GetProperty(child)
if _, ok := parentProperty.sub[childProperty]; ok {
parentProperty.removeReference()
delete(parentProperty.sub, childProperty)
childProperty.removeReference()
delete(childProperty.super, parentProperty)
}
}
Expand All @@ -243,6 +277,8 @@ func (store *Store) unsetPropertyDomain(property quad.Value, domain quad.Value)
// FIXME(iddan): Currently doesn't support multiple domains as they are very rare
p.domain = nil
delete(class.ownProperties, p)
p.removeReference()
class.removeReference()
}

func (store *Store) unsetPropertyRange(property quad.Value, _range quad.Value) {
Expand All @@ -251,6 +287,8 @@ func (store *Store) unsetPropertyRange(property quad.Value, _range quad.Value) {
p._range = nil
// FIXME(iddan): Currently doesn't support multiple ranges as they are very rare
delete(class.inProperties, p)
p.removeReference()
class.removeReference()
}

// UnprocessQuad is used to delete a quad from the store
Expand Down
38 changes: 36 additions & 2 deletions inference/inference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ func TestDeleteNewProperty(t *testing.T) {

func TestDeleteSubClass(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
quad.Quad{Subject: quad.IRI("Person"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdfs.SubClassOf), Object: quad.IRI("Person"), Label: nil}
store.ProcessQuad(q)
store.UnprocessQuad(q)
Expand All @@ -221,6 +225,10 @@ func TestDeleteSubClass(t *testing.T) {

func TestDeleteSubProperty(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI("personal"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.SubPropertyOf), Object: quad.IRI("personal"), Label: nil}
store.ProcessQuad(q)
store.UnprocessQuad(q)
Expand All @@ -237,6 +245,10 @@ func TestDeleteSubProperty(t *testing.T) {

func TestDeletePropertyDomain(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI("Person"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.Domain), Object: quad.IRI("Person"), Label: nil}
store.ProcessQuad(q)
store.UnprocessQuad(q)
Expand All @@ -253,11 +265,15 @@ func TestDeletePropertyDomain(t *testing.T) {

func TestDeletePropertyRange(t *testing.T) {
store := NewStore()
q := quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.Range), Object: quad.IRI("Person"), Label: nil}
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI(rdfs.Literal), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.Range), Object: quad.IRI(rdfs.Literal), Label: nil}
store.ProcessQuad(q)
store.UnprocessQuad(q)
createdProperty := store.GetProperty(quad.IRI("name"))
createdClass := store.GetClass(quad.IRI("Person"))
createdClass := store.GetClass(quad.IRI(rdfs.Literal))
// TODO(iddan): what about garbage collection?
if createdProperty.Range() == createdClass {
t.Error("Range class was not unregistered for property")
Expand All @@ -269,6 +285,10 @@ func TestDeletePropertyRange(t *testing.T) {

func TestDeleteIsSubClassOf(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
quad.Quad{Subject: quad.IRI("Person"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdfs.SubClassOf), Object: quad.IRI("Person")}
store.ProcessQuad(q)
store.UnprocessQuad(q)
Expand All @@ -279,6 +299,11 @@ func TestDeleteIsSubClassOf(t *testing.T) {

func TestDeleteIsSubClassOfRecursive(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
quad.Quad{Subject: quad.IRI("Person"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
quad.Quad{Subject: quad.IRI("SoftwareEngineer"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdfs.Class), Label: nil},
})
quads := []quad.Quad{
quad.Quad{Subject: quad.IRI("Engineer"), Predicate: quad.IRI(rdfs.SubClassOf), Object: quad.IRI("Person")},
quad.Quad{Subject: quad.IRI("SoftwareEngineer"), Predicate: quad.IRI(rdfs.SubClassOf), Object: quad.IRI("Engineer")},
Expand All @@ -292,6 +317,10 @@ func TestDeleteIsSubClassOfRecursive(t *testing.T) {

func TestDeleteIsSubPropertyOf(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI("personal"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
})
q := quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.SubPropertyOf), Object: quad.IRI("personal"), Label: nil}
store.ProcessQuad(q)
store.UnprocessQuad(q)
Expand All @@ -302,6 +331,11 @@ func TestDeleteIsSubPropertyOf(t *testing.T) {

func TestDeleteIsSubPropertyOfRecursive(t *testing.T) {
store := NewStore()
store.ProcessQuads([]quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI("personal"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
quad.Quad{Subject: quad.IRI("information"), Predicate: quad.IRI(rdf.Type), Object: quad.IRI(rdf.Property), Label: nil},
})
quads := []quad.Quad{
quad.Quad{Subject: quad.IRI("name"), Predicate: quad.IRI(rdfs.SubPropertyOf), Object: quad.IRI("personal"), Label: nil},
quad.Quad{Subject: quad.IRI("personal"), Predicate: quad.IRI(rdfs.SubPropertyOf), Object: quad.IRI("information"), Label: nil},
Expand Down

0 comments on commit 0bf3edf

Please sign in to comment.