fca :: FormalContext :: formal_concepts
# Derive the set of formal concepts from the objects and attributes
fun formal_concepts: Set[FormalConcept[O, A]] do
# black magic!
var concepts = new HashSet[FormalConcept[O, A]]
var extentsByAttr = new HashMap[Set[A], Set[O]]
for attribute in attributes do
var ka = new HashSet[A].from([attribute])
extentsByAttr[ka] = new HashSet[O]
for object in objects do
if not objects_attributes[object].has(attribute) then continue
extentsByAttr[ka].add(object)
end
end
var nextents = new HashMap[Set[A], Set[O]]
for k1, v1 in extentsByAttr do
for k2, v2 in extentsByAttr do
if k1 == k2 then continue
var n = v1.intersection(v2)
if extentsByAttr.values.has(n) then continue
var ka = k1.union(k2)
nextents[ka] = n
end
end
extentsByAttr.add_all nextents
var contained = true
for k1, v1 in extentsByAttr do
if not contained then break
for k2, v2 in extentsByAttr do
if k1 == k2 then continue
var n = v1.intersection(v2)
if extentsByAttr.values.has(n) then continue
contained = false
break
end
end
if contained then
extentsByAttr[new HashSet[A]] = new HashSet[O].from(objects)
end
var extents = new HashSet[Set[O]]
for objects in extentsByAttr.values do
extents.add objects
end
for extent in extents do
var intents: Set[A] = new HashSet[A]
var count = 0
var cl = new FormalConcept[O, A]
if extent.is_empty then
intents.add_all(attributes)
else
for object in objects do
if not extent.has(object) then continue
var prev = objects_attributes[object]
if count > 0 then
intents = prev.intersection(intents)
else
intents = prev
end
count += 1
cl.objects.add(object)
end
end
cl.attributes.add_all intents
concepts.add cl
end
return concepts
end
lib/fca/fca.nit:106,2--179,4