π Measures#
The galactic.algebras.convex.measures.core module provides abstractions for
measuring the quality of formal concepts. Measures are used to
evaluate sub-concepts relative to their parent concepts.
A Measure is a callable that takes
a sub-concept and a super-concept and returns a non-negative float value representing
the measure of quality. This is particularly useful for filtering or ranking concepts
during lattice traversal.
Available Measures#
The module provides several built-in measure implementations:
Support: Returns the cardinality of the conceptβs extent (count of items)NormalisedSupport: Returns the support normalised by the domain size (a value in[0, 1])
Creating and Using Measures#
Measures can be instantiated and applied directly to concepts:
from galactic.algebras.concept.core import ItemUniverse
from galactic.algebras.convex.characteristics.core import Component, Integer
from galactic.algebras.convex.descriptions.core import (
Concept,
Context,
GaloisConnection,
PredicateUniverse,
)
from galactic.algebras.convex.descriptions.examples.arithmetic.core import (
DivisorDescription,
MultipleDescription,
)
from galactic.algebras.convex.measures.core import Support, NormalisedSupport
from galactic.algebras.convex.strategies.core import NaiveStrategy
# Set up the context
characteristic = Integer(components=(Component(),))
descriptions = [
DivisorDescription(space=(characteristic,)),
MultipleDescription(space=(characteristic,)),
]
dataset = [36, 48, 16, 32, 12, 24, 18, 30, 42, 60]
domain = ItemUniverse(dataset)
co_domain = PredicateUniverse(*descriptions)
context = Context(domain, co_domain)
connection = GaloisConnection(context)
# Create the top concept
top = Concept(connection)
print(f"Top concept extent size: {len(top.extent)}")
# Apply the naive strategy to get sub-concepts
strategy = NaiveStrategy(descriptions=descriptions)
sub_concepts = list(strategy(top))
print(f"Number of sub-concepts: {len(sub_concepts)}")
Top concept extent size: 10
Number of sub-concepts: 4
Now letβs measure these concepts using different measures:
# Create measure instances
support = Support()
norm_support = NormalisedSupport()
# Measure each sub-concept
print("Support measurements:")
supports = [support(sub, top) for sub in sub_concepts]
display(supports)
print("\nNormalised Support measurements:")
norm_supports = [norm_support(sub, top) for sub in sub_concepts]
display(norm_supports)
Support measurements:
[8.0, 9.0, 8.0, 9.0]
Normalised Support measurements:
[0.8, 0.9, 0.8, 0.9]
Filtering Concepts with Measures#
Measures become particularly powerful when combined with filtering strategies.
The FilteringStrategy allows
you to keep only concepts that meet a threshold:
from galactic.algebras.convex.strategies.core import FilteringStrategy
# Create a filtering strategy that keeps concepts with support >= 8
filtering = FilteringStrategy(
strategies=(strategy,),
measure=support,
threshold=8,
)
# Get filtered concepts
filtered_concepts = list(filtering(top))
print(f"Filtered concepts (support >= 8): {len(filtered_concepts)}")
# Show their support values
filtered_supports = [support(sub, top) for sub in filtered_concepts]
display(filtered_supports)
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
Cell In[3], line 1
----> 1 from galactic.algebras.convex.strategies.core import FilteringStrategy
2
3 # Create a filtering strategy that keeps concepts with support >= 8
4 filtering = FilteringStrategy(
ImportError: cannot import name 'FilteringStrategy' from 'galactic.algebras.convex.strategies.core' (/builds/galactic/public/src/algebras/galactic-algebra-convex/src/galactic/algebras/convex/strategies/core/__init__.py)
Selective Filtering with Relative Measures#
The SelectiveStrategy provides
a more flexible filtering mechanism by keeping concepts whose measure is at least
ratio * best_measure:
from galactic.algebras.convex.strategies.core import SelectiveStrategy
# Keep only concepts with support >= 0.5 * best_support
selective_half = SelectiveStrategy(
strategies=(strategy,),
measure=support,
ratio=0.5,
)
# Get selectively filtered concepts
selected_concepts = list(selective_half(top))
print(f"Selectively filtered concepts (ratio=0.5): {len(selected_concepts)}")
# Show their support values
selected_supports = [support(sub, top) for sub in selected_concepts]
display(selected_supports)
# Compare with ratio=1 (keep only the best)
selective_best = SelectiveStrategy(
strategies=(strategy,),
measure=support,
ratio=1,
)
selected_best_concepts = list(selective_best(top))
print(f"\nSelectively filtered concepts (ratio=1): {len(selected_best_concepts)}")
best_supports = [support(sub, top) for sub in selected_best_concepts]
display(best_supports)
Creating Custom Measures#
You can create your own measure by subclassing the
Measure
abstract class and implementing the
__call__() method:
from galactic.algebras.convex.measures.core import Measure
class RelativeSize(Measure):
"""Measure the relative size of a concept compared to its parent."""
def __call__(self, pred, succ):
"""
Return the ratio of extents: len(pred.extent) / len(succ.extent).
"""
if len(succ.extent) == 0:
return 0.0
return len(pred.extent) / len(succ.extent)
# Use the custom measure
relative_size = RelativeSize()
rel_sizes = [relative_size(sub, top) for sub in sub_concepts]
print("Relative Size measurements:")
display(rel_sizes)
# Create a filtering strategy with the custom measure
filtering_relative = FilteringStrategy(
strategies=(strategy,),
measure=relative_size,
threshold=0.8, # Keep concepts with at least 80% of parent's size
)
filtered_by_relative = list(filtering_relative(top))
print(f"\nFiltered concepts (relative size >= 0.8): {len(filtered_by_relative)}")
rel_sizes_filtered = [relative_size(sub, top) for sub in filtered_by_relative]
display(rel_sizes_filtered)