Skip to content

Commit

Permalink
feat(primitives): cfd
Browse files Browse the repository at this point in the history
  • Loading branch information
vladyoslav committed Oct 27, 2024
1 parent dee20b8 commit 84016bd
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions internal/domain/task/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from internal.domain.task.entities import IndTask # noqa: F401
from internal.domain.task.entities import AindTask # noqa: F401
from internal.domain.task.entities import ArTask # noqa: F401
from internal.domain.task.entities import CfdTask # noqa: F401
3 changes: 3 additions & 0 deletions internal/domain/task/entities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from internal.domain.task.entities.ind import IndTask
from internal.domain.task.entities.aind import AindTask
from internal.domain.task.entities.ar import ArTask
from internal.domain.task.entities.cfd import CfdTask
from internal.domain.task.value_objects import PrimitiveName


Expand Down Expand Up @@ -35,4 +36,6 @@ def match_task_by_primitive_name(primitive_name: PrimitiveName):
return AindTask()
case PrimitiveName.ar:
return ArTask()
case PrimitiveName.cfd:
return CfdTask()
assert_never(primitive_name)
1 change: 1 addition & 0 deletions internal/domain/task/entities/cfd/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from internal.domain.task.entities.cfd.cfd_task import CfdTask # noqa: F401
54 changes: 54 additions & 0 deletions internal/domain/task/entities/cfd/cfd_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from desbordante.cfd import CfdAlgorithm
from desbordante.cfd.algorithms import FDFirst
from internal.domain.task.entities.task import Task
from internal.domain.task.value_objects import PrimitiveName, IncorrectAlgorithmName
from internal.domain.task.value_objects.cfd import CfdTaskConfig, CfdTaskResult
from internal.domain.task.value_objects.cfd import (
CfdAlgoName,
CfdModel,
CfdAlgoResult,
)


class CfdTask(Task[CfdAlgorithm, CfdTaskConfig, CfdTaskResult]):
"""
Task class for Conditional Functional Dependencies (CFD) mining.
This class handles the execution of different CFD algorithms and processes
the results into the appropriate format. It implements the abstract methods
defined in the Task base class.
Methods:
- _match_algo_by_name(algo_name: CfdAlgoName) -> CfdAlgorithm:
Match CFD algorithm by its name.
- _collect_result(algo: CfdAlgorithm) -> CfdTaskResult:
Process the output of the CFD algorithm and return the result.
"""

def _collect_result(self, algo: CfdAlgorithm) -> CfdTaskResult:
"""
Collect and process the CFD result.
Args:
algo (CfdAlgorithm): CFD algorithm to process.
Returns:
CfdTaskResult: The processed result containing CFDs.
"""
cfds = algo.get_cfds()
algo_result = CfdAlgoResult(cfds=[CfdModel.from_cfd(cfd) for cfd in cfds])
return CfdTaskResult(primitive_name=PrimitiveName.cfd, result=algo_result)

def _match_algo_by_name(self, algo_name: str) -> CfdAlgorithm:
"""
Match the CFD algorithm by name.
Args:
algo_name (CfdAlgoName): The name of the CFD algorithm.
Returns:
CfdAlgorithm: The corresponding algorithm instance.
"""
match algo_name:
case CfdAlgoName.FDFirst:
return FDFirst()
case _:
raise IncorrectAlgorithmName(algo_name, "CFD")
3 changes: 3 additions & 0 deletions internal/domain/task/value_objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from internal.domain.task.value_objects.ind import IndTaskConfig, IndTaskResult
from internal.domain.task.value_objects.aind import AindTaskConfig, AindTaskResult
from internal.domain.task.value_objects.ar import ArTaskConfig, ArTaskResult
from internal.domain.task.value_objects.cfd import CfdTaskConfig, CfdTaskResult

from internal.domain.task.value_objects.config import TaskConfig # noqa: F401
from internal.domain.task.value_objects.result import TaskResult # noqa: F401
Expand All @@ -32,6 +33,7 @@
IndTaskConfig,
AindTaskConfig,
ArTaskConfig,
CfdTaskConfig,
],
Field(discriminator="primitive_name"),
]
Expand All @@ -44,6 +46,7 @@
IndTaskResult,
AindTaskResult,
ArTaskResult,
CfdTaskResult,
],
Field(discriminator="primitive_name"),
]
23 changes: 23 additions & 0 deletions internal/domain/task/value_objects/cfd/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import Literal

from pydantic import BaseModel

from internal.domain.task.value_objects.primitive_name import PrimitiveName
from internal.domain.task.value_objects.cfd.algo_config import OneOfCfdAlgoConfig
from internal.domain.task.value_objects.cfd.algo_result import ( # noqa: F401
CfdAlgoResult,
CfdModel,
)
from internal.domain.task.value_objects.cfd.algo_name import CfdAlgoName # noqa: F401


class BaseCfdTaskModel(BaseModel):
primitive_name: Literal[PrimitiveName.cfd]


class CfdTaskConfig(BaseCfdTaskModel):
config: OneOfCfdAlgoConfig


class CfdTaskResult(BaseCfdTaskModel):
result: CfdAlgoResult
38 changes: 38 additions & 0 deletions internal/domain/task/value_objects/cfd/algo_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Literal, Annotated
from pydantic import Field
from internal.domain.common import OptionalModel
from internal.domain.task.value_objects.cfd.algo_name import CfdAlgoName
from internal.domain.task.value_objects.cfd.algo_descriptions import descriptions


class BaseCfdConfig(OptionalModel):
__non_optional_fields__ = {
"algo_name",
}


class FDFirstConfig(BaseCfdConfig):
algo_name: Literal[CfdAlgoName.FDFirst]

columns_number: Annotated[
int, Field(ge=1, description=descriptions["columns_number"])
]
cfd_minsup: Annotated[int, Field(ge=1, description=descriptions["cfd_minsup"])]
cfd_minconf: Annotated[
float, Field(ge=0, le=1, description=descriptions["cfd_minconf"])
]
tuples_number: Annotated[
int, Field(ge=1, description=descriptions["tuples_number"])
]
cfd_max_lhs: Annotated[int, Field(ge=1, description=descriptions["cfd_max_lhs"])]
cfd_substrategy: Annotated[
str,
Literal["dfs", "bfs"],
Field(description=descriptions["cfd_substrategy"]),
]


OneOfCfdAlgoConfig = Annotated[
FDFirstConfig,
Field(discriminator="algo_name"),
]
8 changes: 8 additions & 0 deletions internal/domain/task/value_objects/cfd/algo_descriptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
descriptions = {
"columns_number": "Number of columns in the part of the dataset if you want to use the algorithm on a subset of columns",
"cfd_minsup": "Minimum support value (integer between 1 and the number of tuples in dataset)",
"cfd_minconf": "Minimum confidence value (between 0 and 1)",
"tuples_number": "Number of tuples in the dataset or its part",
"cfd_max_lhs": "Maximum size of the left-hand side of the CFD",
"cfd_substrategy": "Lattice traversal strategy for CFD mining",
}
5 changes: 5 additions & 0 deletions internal/domain/task/value_objects/cfd/algo_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from enum import StrEnum, auto


class CfdAlgoName(StrEnum):
FDFirst = auto()
18 changes: 18 additions & 0 deletions internal/domain/task/value_objects/cfd/algo_result.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pydantic import BaseModel
from desbordante.cfd import CFD


class CfdModel(BaseModel):
lhs_items: list[str | None]
rhs_item: str | None

@classmethod
def from_cfd(cls, cfd: CFD):
return cls(
lhs_items=[item.value for item in cfd.lhs_items],
rhs_item=cfd.rhs_item.value,
)


class CfdAlgoResult(BaseModel):
cfds: list[CfdModel]
1 change: 1 addition & 0 deletions internal/domain/task/value_objects/primitive_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class PrimitiveName(StrEnum):
ac = auto()
ind = auto()
aind = auto()
cfd = auto()
# fd_verification = auto()
# mfd_verification = auto()
# statistics = auto()
Expand Down

0 comments on commit 84016bd

Please sign in to comment.