galactic.algebras.convex.strategies.core#

galactic.algebras.convex.strategies.core module

Core strategy classes for convex algebras.

This package exposes strategy abstractions and concrete implementations used to generate sub-concepts from a given concept.

The available classes are grouped into three families:

Base abstractions

Structural traversal

Measure-driven traversal


class Strategy(**data)#

Bases: Resource, ABC

Represents strategies.

Notes

  • The __call__ method is designed to be used as a callable strategy. It takes a concept and computes an iterator of sub-concepts by dividing the items into smaller groups.

  • The space property returns the collection of characteristics that define the strategy space.

abstractmethod __call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class BasicStrategy(**data)#

Bases: Strategy, ABC

Represents basic strategies.

Parameters:

space – A tuple of characteristics

Raises:

TypeError – If any of the provided characteristics is not an instance of the Characteristic class

Notes

  • When subclassing this class, ensure to implement the _call method to provide the specific logic for computing strategies based on the values of the characteristics.

__call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class MetaStrategy(**data)#

Bases: Strategy, ABC

Represents a strategy that depends on other strategies.

Parameters:

strategies – An iterable of inner strategies

Raises:
  • RuntimeError – If the number of inner strategies is less than the minimum or greater than the maximum allowed

  • TypeError – If any of the provided inner strategies is not an instance of the Strategy class

abstractmethod __call__(concept)#

Apply the strategy to the concept.

Sub-classes must implement this method by using the inner strategies.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

Raises:

NotImplementedError – If the method is not implemented

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ValuedStrategy(**data)#

Bases: MetaStrategy, ABC

Valued strategy.

A valued strategy is a super-class for designing strategies that depend on a measure.

Parameters:

measure – A measure to evaluate the sub-concepts. The measure should be a callable that takes a sub-concept and the original concept as input and returns a float value representing the measure of the sub-concept with respect to the original concept.

Raises:

TypeError – If the provided measure is not a instance of the Measure

abstractmethod __call__(concept)#

Apply the strategy to the concept.

Sub-classes must implement this method.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

Raises:

NotImplementedError – If the method is not implemented

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class NaiveStrategy(**data)#

Bases: Strategy

Represents naive strategies.

A naive strategy tries to generate direct predecessors of concepts. This is feasible when the description spaces are convex.

Parameters:

descriptions (tuple[Description, ...]) – An iterable of descriptions to define the strategy space

ALIAS#

The alias of the type in the resource registry.

Type:

ClassVar[str] = “core.strategy.Naive”

Examples

>>> from pprint import pprint
>>> 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.strategies.core import NaiveStrategy
>>> 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=descriptions)
>>> context = Context(domain, co_domain)
>>> connection = GaloisConnection(context)
>>> top = Concept(connection)
>>> strategy = NaiveStrategy(descriptions=descriptions)
>>> concepts = list(strategy(top))
>>> pprint([[item.value for item in concept.extent] for concept in concepts])
[[48, 16, 32, 12, 24, 30, 42, 60],
 [36, 48, 16, 12, 24, 18, 30, 42, 60],
 [36, 48, 16, 32, 12, 24, 18, 42],
 [36, 48, 16, 32, 12, 24, 18, 30, 60]]
>>> pprint([[str(attr) for attr in sub.intent] for sub in concepts])
[['D(int(@),3360)', 'M(int(@),2)'],
 ['D(int(@),5040)', 'M(int(@),2)'],
 ['D(int(@),2016)', 'M(int(@),2)'],
 ['D(int(@),1440)', 'M(int(@),2)']]

Configuration

If you want to specify a naive strategy in a TOML file, you can use the following syntax:

[components.my_component]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component"}
]
name = "my_name"

[descriptions.my_description]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic"}
]

[strategies.my_strategy]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description"}
]
Raises:

TypeError – If any of the provided descriptions is not an instance of the Description class

__call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of direct sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ComplementStrategy(**data)#

Bases: MetaStrategy

Represents complement strategies.

A complement strategy yields the concepts produced by the inner strategy and, for each of them, the concept built from the complementary items in the current concept extent.

Parameters:

strategies (tuple[Strategy]) – An iterable of one inner strategy

ALIAS#

The alias of the type in the resource registry.

Type:

ClassVar[str] = “core.strategy.Complement”

Examples

>>> from pprint import pprint
>>> 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.strategies.core import NaiveStrategy
>>> 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=descriptions)
>>> context = Context(domain, co_domain)
>>> connection = GaloisConnection(context)
>>> top = Concept(connection)
>>> strategy = ComplementStrategy(
...     strategies=(NaiveStrategy(descriptions=descriptions),),
... )
>>> concepts = list(strategy(top))
>>> pprint([[item.value for item in concept.extent] for concept in concepts])
[[48, 16, 32, 12, 24, 30, 42, 60],
 [36, 18],
 [36, 48, 16, 12, 24, 18, 30, 42, 60],
 [32],
 [36, 48, 16, 32, 12, 24, 18, 42],
 [30, 60],
 [36, 48, 16, 32, 12, 24, 18, 30, 60],
 [42]]

Configuration

If you want to specify a complement strategy in a TOML file, you can use the following syntax:

[components.my_component]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component"}
]
name = "my_name"

[descriptions.my_description]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic"}
]

[strategies.my_strategy]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description"}
]

[strategies.complement]
"$type" = "core.strategy.Complement"
strategies = [
  {"$ref" = "strategies.my_strategy"}
]
__call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class CompositeStrategy(**data)#

Bases: MetaStrategy

Represents composite strategies.

A composite strategy is equivalent to applying the inner strategies step by step.

Parameters:

strategies (tuple[Strategy, ...]) – An iterable of inner strategies

ALIAS#

The alias of the type in the resource registry.

Type:

ClassVar[str] = “core.strategy.Composite”

Configuration

If you want to specify a composite strategy in a TOML file, you can use the following syntax:

[components.my_component1]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic1]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component1"}
]
name = "my_name1"

[components.my_component2]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic2]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component2"}
]
name = "my_name2"

[descriptions.my_description1]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic1"}
]

[descriptions.my_description2]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic2"}
]

[strategies.my_strategy1]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description1"}
]

[strategies.my_strategy2]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description2"}
]

[strategies.composite]
"$type" = "core.strategy.Composite"
strategies = [
  {"$ref" = "strategies.my_strategy1"},
  {"$ref" = "strategies.my_strategy2"}
]
__call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class RecursiveStrategy(**data)#

Bases: MetaStrategy

Represents recursive strategies [1].

Parameters:
  • strategies (tuple[Strategy]) – An iterable of one inner strategy

  • support (int, optional) – An optional support threshold to limit the size of sub-concepts

  • normalised_support (float, optional) – An optional normalised support threshold to limit the size of sub-concepts

ALIAS#

The alias of the type in the resource registry.

Type:

ClassVar[str] = “core.strategy.Recursive”

Examples

>>> from pprint import pprint
>>> 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.strategies.core import (
...     NaiveStrategy,
...     RecursiveStrategy,
... )
>>> characteristic = Integer(components=(Component(),))
>>> descriptions = (
...     DivisorDescription(space=(characteristic,)),
...     MultipleDescription(space=(characteristic,)),
... )
>>> dataset = [36, 48, 16, 32]
>>> domain = ItemUniverse(dataset)
>>> co_domain = PredicateUniverse(descriptions=descriptions)
>>> context = Context(domain, co_domain)
>>> connection = GaloisConnection(context)
>>> top = Concept(connection)
>>> strategy = RecursiveStrategy(
...     strategies=(NaiveStrategy(descriptions=descriptions),),
... )
>>> concepts = list(strategy(top))
>>> [[item.value for item in concept.extent] for concept in concepts]
[[48, 16, 32], [36, 48, 16], [16, 32], [36, 48], [32], [36]]
>>> pprint([[str(attr) for attr in concept.intent] for concept in concepts])
[['D(int(@),96)', 'M(int(@),16)'],
 ['D(int(@),144)', 'M(int(@),4)'],
 ['D(int(@),32)', 'M(int(@),16)'],
 ['D(int(@),144)', 'M(int(@),4)', 'M(int(@),3)'],
 ['D(int(@),32)', 'M(int(@),32)'],
 ['D(int(@),36)', 'M(int(@),4)', 'M(int(@),9)']]

Configuration

If you want to specify a recursive strategy in a TOML file, you can use the following syntax:

[components.my_component]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component"}
]
name = "my_name"

[descriptions.my_description]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic"}
]

[strategies.my_strategy]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description"}
]

[strategies.recursive]
"$type" = "core.strategy.Recursive"
strategies = [
  {"$ref" = "strategies.my_strategy"}
]
support = 0
normalised_support = 0.0
relative_support = 0.0

References

__call__(concept)#

Apply the strategy to the concept.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class SelectiveStrategy(**data)#

Bases: ValuedStrategy

Selective strategy.

A selective strategy applies the inner strategy and keeps only sub-concepts whose measure is at least ratio * best_measure and greater or equal to the threshold.

Parameters:
  • strategies (tuple[Strategy]) – An iterable of one inner strategy

  • measure (Callable[[Concept, Concept], float]) – A measure function to evaluate the sub-concepts relatively to the current concept.

  • ratio (float, default=0.0) – Ratio in [0, 1] used to filter sub-concepts relatively to the best measured sub-concept.

  • threshold (float, default=0.0) – A threshold to filter the sub-concepts. Only sub-concepts with a measure value greater than or equal to this threshold will be yielded.

ALIAS#

The alias of the type in the resource registry.

Type:

ClassVar[str] = “core.strategy.Selective”

Examples

>>> 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
>>> from galactic.algebras.convex.strategies.core import (
...     NaiveStrategy,
...     SelectiveStrategy,
... )
>>> 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=descriptions)
>>> context = Context(domain, co_domain)
>>> connection = GaloisConnection(context)
>>> top = Concept(connection)
>>> naive = NaiveStrategy(descriptions=descriptions)
>>> support = Support()
>>> selective = SelectiveStrategy(strategies=(naive,), measure=support, ratio=1)
>>> selected = list(selective(top))
>>> [support(sub, top) for sub in selected]
[9.0, 9.0]
>>> strategy2 = SelectiveStrategy(strategies=(naive,), measure=support, ratio=0.5)
>>> selected = list(strategy2(top))
>>> [support(sub, top) for sub in selected]
[9.0, 9.0, 8.0, 8.0]
>>> filtering = SelectiveStrategy(strategies=(naive,), measure=support, threshold=9)
>>> filtered = list(filtering(top))
>>> [len(sub.extent) for sub in filtered]
[9, 9]
>>> [[str(attr) for attr in sub.intent] for sub in filtered]
[['D(int(@),5040)', 'M(int(@),2)'], ['D(int(@),1440)', 'M(int(@),2)']]

Configuration

If you want to specify a selective strategy in a TOML file, you can use the following syntax:

[components.my_component]
"$type" = "core.Component"
expr = "value"

[characteristics.my_characteristic]
"$type" = "core.characteristic.Boolean"
components = [
  {"$ref" = "components.my_component"}
]
name = "my_name"

[descriptions.my_description]
"$type" = "core.description.Boolean"
space = [
  {"$ref" = "characteristics.my_characteristic"}
]

[strategies.my_strategy]
"$type" = "core.strategy.Naive"
descriptions = [
  {"$ref" = "descriptions.my_description"}
]

[strategies.selective]
"$type" = "core.strategy.Selective"
strategies = [
  {"$ref" = "strategies.my_strategy"}
]
ratio = 0.0
threshold = 0.0
__call__(concept)#

Apply the strategy to the concept.

The SelectiveStrategy applies the inner strategy to the concept and keeps only sub-concepts whose measure is at least ratio * best_measure.

Parameters:

concept (Concept) – A concept

Returns:

An iterator over a collection of sub-concepts

Return type:

Iterator[Concept]

model_config: ClassVar[ConfigDict] = {'validate_assignment': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].