Source code for fca.algorithms.fast_close_by_one

import numpy as np
from fca import Concept, utils


[docs]class FastCloseByOne: """Implements algorithm FastCloseByOne from Jan Outrata, Vilem Vychodil FCbO lists all formal concepts by a systematic search in the space of all formal concepts, avoiding to list the same concept multiple times by performing a canonicity test. The algorithm uses set of already computed intents which fails canonicity test. (cite: https://www.sciencedirect.com/science/article/pii/S0020025511004804) More information about the algorithm can be found here: https://www.sciencedirect.com/science/article/pii/S0020025511004804 """
[docs] @staticmethod def fast_generate_from(context, concept, y, n, Yj, Nj, intent, output): """ Recursively descends through the space of formal concepts, beginning with :math:`<A,B>`. Parameters ---------- context : :py:class:`fca.Context` Context where the concepts should be find. concept : :py:class:`fca.Concept` Initial formal concept. y : Index of first attribute to be processed. n : Number of columns in context. Yj: Preallocated :py:class:`numpy.array` for better performance. Nj: Already computed intents which failed the canonical test. intent : Preallocated intent for better performance. output : list Output list for formal concepts. """ output.append(concept) if np.logical_and.reduce(concept.intent) or y > n: return queue = [] Mj = [np.full((n), False, dtype=bool)] * n for j in range(y, n): Mj[j] = Nj[j] # Reset value from previous call Yj[:] = True Yj[j:] = False # Help variables for subset test (intersections) i0 = np.logical_and(Nj[j], Yj) i1 = np.logical_and(concept.intent, Yj) if not concept.intent[j] and utils.fast_subset_equal(i0, i1): # Reset value from previous call intent[:] = False intent[j] = True # New concept C = np.logical_and( concept.extent, context.down(intent)) D = context.up(C) # Intersection i2 = np.logical_and(D, Yj) if np.array_equal(i1, i2): queue.append((Concept(C, D), j + 1)) else: Mj[j] = D while queue: concept, y = queue.pop() FastCloseByOne.fast_generate_from(context, concept, y, n, Yj, Mj, intent, output)
[docs] @staticmethod def generate_concepts(context): """ Lists all formal concepts by a systematic search in the space of all formal concepts, avoiding to list the same concept multiple times by performing a canonicity test. Parameters ---------- context : :py:class:`fca.Context` Context where the concepts should be found. Returns ------- output : list List of concepts. """ n = len(context.data[0]) init_extent = context.down(np.full(n, False)) init_intent = context.up(init_extent) concept = Concept(init_extent, init_intent) # Preallocating Yj = np.empty(n, dtype=bool) intent = np.empty(n, dtype=bool) Nj = [np.full(n, False)] * n output = [] FastCloseByOne.fast_generate_from(context, concept, 0, n, Yj, Nj, intent, output) return output