Skip to content

Commit

Permalink
v0.4.0 (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikulatomas authored Sep 6, 2022
1 parent e43ebc0 commit a3afa72
Show file tree
Hide file tree
Showing 14 changed files with 458 additions and 134 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,9 @@ jobs:
- python-version: 3.7
args: ""
os: ubuntu-latest
- python-version: 3.6
args: ""
os: ubuntu-latest
- python-version: pypy-3.7
args: ""
os: ubuntu-latest
- python-version: pypy-3.6
args: ""
os: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
Expand Down
10 changes: 0 additions & 10 deletions HISTORY.md

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Tomáš Mikula
Copyright (c) 2022 Tomáš Mikula

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ https://doi.org/10.1016/j.ijar.2021.12.001

fcapsy requires:

* Python (>= 3.6)
* Python (>= 3.7)
* [concepts](https://github.com/xflr6/concepts)
* [binsdpy](https://github.com/mikulatomas/binsdpy)
5 changes: 1 addition & 4 deletions fcapsy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
__version__ = "0.3.3"
__author__ = "Tomáš Mikula"
__email__ = "mail@tomasmikula.cz"
__license__ = "MIT license"
from .category import Category
19 changes: 19 additions & 0 deletions fcapsy/category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import typing
import concepts

from .utils import get_vectors


class Category:
"""Category defined as group of exemplars (extent)."""

def __init__(self, context: "concepts.Context", extent) -> None:
self.context = context
self._extent = extent

@property
def extent(self) -> typing.Tuple[str, ...]:
return self._extent.members()

def vectors(self, item: str) -> typing.Dict:
return get_vectors(self, item)
53 changes: 0 additions & 53 deletions fcapsy/centrality.py

This file was deleted.

18 changes: 9 additions & 9 deletions fcapsy/cohesion.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@
import typing

import concepts.lattices
import fcapsy.category

from itertools import combinations, starmap

from .utils import get_vectors

__all__ = ["cohesion_min", "cohesion_avg"]


def cohesion_min(
concept: "concepts.lattices.Concept", similarity: typing.Callable
concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"],
similarity: typing.Callable,
) -> float:
"""Calculate cohesion of given concept as worst case (minimal) similarity of its objects.
Expand All @@ -31,16 +35,14 @@ def cohesion_min(
>>> cohesion_min(lattice.infimum, similarity.jaccard)
0
"""
extent_size = len(concept.extent)
extent_size = concept._extent.count()

if extent_size == 0:
return 0
elif extent_size == 1:
return 1.0

vectors = map(
concept.lattice._context._intents.__getitem__, concept._extent.iter_set()
)
vectors = get_vectors(concept, concept.extent[0]).values()

combs = combinations(vectors, 2)

Expand All @@ -64,16 +66,14 @@ def cohesion_avg(
0
"""
extent_size = len(concept.extent)
extent_size = concept._extent.count()

if extent_size == 0:
return 0
elif extent_size == 1:
return 1.0

vectors = map(
concept.lattice._context._intents.__getitem__, concept._extent.iter_set()
)
vectors = get_vectors(concept, concept.extent[0]).values()

combs = combinations(vectors, 2)

Expand Down
173 changes: 173 additions & 0 deletions fcapsy/item_weights.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import typing

import concepts.lattices
import fcapsy.category

from .utils import get_context


__all__ = ["presence", "absence", "characteristic", "characteristic_r"]


def _get_vectors(item, concept):
context = get_context(concept)

try:
instances_with_item = context.intension([item], raw=True)
Vector = type(concept._intent)
universum = Vector.supremum
concept_core = concept._intent
except KeyError:
instances_with_item = context.extension([item], raw=True)
Vector = type(concept._extent)
universum = Vector.supremum
concept_core = concept._extent

return instances_with_item, concept_core, Vector, universum


def presence(
item, concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"]
):
"""_summary_
Args:
item (str): object or attribute name
concept (typing.Union[concepts.lattices.Concept, fcapsy.category.Category])
Returns:
_type_: _description_
Example:
>>> from concepts import Context
>>> context = Context.fromstring('''
... |2 legs |nests |flies |raptor |
... sparrow | X | X | X | |
... lark | X | X | X | |
... penguin | X | | | |
... chicken | X | X | X | |
... vulture | X | | X | X |
... ''')
>>> birds = context.lattice.supremum
>>> presence("2 legs", birds)
5
>>> presence("nests", birds)
3
>>> flies = birds.lower_neighbors[0]
>>> presence("2 legs", flies)
4
"""
instances_with_item, concept_core, Vector, _ = _get_vectors(item, concept)

occurence_in_concept = Vector.fromint(instances_with_item & concept_core).count()

return occurence_in_concept


def absence(
item, concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"]
):
"""_summary_
Args:
item (str): object or attribute name
concept (typing.Union[concepts.lattices.Concept, fcapsy.category.Category])
Returns:
_type_: _description_
Example:
>>> from concepts import Context
>>> context = Context.fromstring('''
... |2 legs |nests |flies |raptor |
... sparrow | X | X | X | |
... lark | X | X | X | |
... penguin | X | | | |
... chicken | X | X | X | |
... vulture | X | | X | X |
... ''')
>>> birds = context.lattice.supremum
>>> absence("2 legs", birds)
0
>>> absence("nests", birds)
2
>>> flies = birds.lower_neighbors[0]
>>> absence("raptor", flies)
3
"""
instances_with_item, concept_core, Vector, universum = _get_vectors(item, concept)

absence_in_concept = Vector.fromint(
(universum ^ instances_with_item) & concept_core
).count()

return absence_in_concept


def characteristic(
item: str,
concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"],
) -> float:
"""Calculates characteristic of object/attribute in the given concept.
The object/attribute does not has to be from the extent/intent.
Args:
item (str): object or attribute name
concept (typing.Union[concepts.lattices.Concept, fcapsy.category.Category])
Returns:
float: characteristic
Example:
>>> from concepts import Context
>>> context = Context.fromstring('''
... |2 legs |nests |flies |raptor |
... sparrow | X | X | X | |
... lark | X | X | X | |
... penguin | X | | | |
... chicken | X | X | X | |
... vulture | X | | X | X |
... ''')
>>> birds = context.lattice.supremum
>>> birds.extent
('sparrow', 'lark', 'penguin', 'chicken', 'vulture')
>>> characteristic("raptor", birds)
0.2
>>> characteristic("flies", birds)
0.8
>>> characteristic("2 legs", birds)
1.0
"""
instances_with_item, concept_core, Vector, _ = _get_vectors(item, concept)

occurence_in_concept = Vector.fromint(instances_with_item & concept_core).count()

if not instances_with_item.count():
return 0.0

return (occurence_in_concept / instances_with_item.count()) * (
occurence_in_concept / concept_core.count()
)


def characteristic_r(
item: str,
concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"],
) -> float:
instances_with_item, concept_core, Vector, _ = _get_vectors(item, concept)

occurence_in_concept = Vector.fromint(instances_with_item & concept_core).count()

if not instances_with_item.count():
return 0.0

universum = Vector.supremum
universum_minus_core = Vector.fromint(universum & (universum ^ concept_core))
universum_minus_core_minus_instances_with_item = Vector.fromint(
universum_minus_core & (universum ^ instances_with_item)
)

return (occurence_in_concept / concept_core.count()) * (
universum_minus_core_minus_instances_with_item.count()
/ universum_minus_core.count()
)
38 changes: 38 additions & 0 deletions fcapsy/prototype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import typing

import concepts.lattices
import fcapsy.category
import numpy as np

from .utils import get_vectors


def prototype(
concept: typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"],
) -> np.ndarray:
"""Calcualtes prototype of given concept.
Args:
concept (typing.Union["concepts.lattices.Concept", "fcapsy.category.Category"]): concept
Returns:
np.ndarray: prototype
Example:
>>> from concepts import Context
>>> from binsdpy.similarity import jaccard
>>> context = Context.fromstring('''
... |2 legs |nests |flies |raptor |engine |
... sparrow | X | X | X | | |
... lark | X | X | X | | |
... penguin | X | | | | |
... chicken | X | X | X | | |
... vulture | X | | X | X | |
... ''')
>>> birds = context.lattice.supremum
>>> prototype(birds)
array([1. , 0.6, 0.8, 0.2, 0. ])
"""
vectors = get_vectors(concept, concept.extent[0]).values()

return np.array([a.bools() for a in vectors]).astype(int).mean(axis=0)
Loading

0 comments on commit a3afa72

Please sign in to comment.