<commit_before>#
# This file is part of CONCUSS, https://github.com/theoryinpractice/concuss/,
# and is Copyright (C) North Carolina State University, 2015. It is licensed
# under the three-clause BSD license; see LICENSE.
#


from collections import defaultdict, Counter
from itertools import product

from dptable import DPTable


class ColorDPTable(DPTable):
    """
    Dynamic programming table for computing graph isomorphisms.
    See http://arxiv.org/pdf/1406.2587v4.pdf for the algorithm
    and explanations of the table and pattern operations

    This DPTable subclass counts how many times the pattern was seen in each
    set of colors in the TDD.  This allows us to count patterns in fewer sub-
    graphs as we can get all the information we need about smaller sets of
    colors by looking at only the top level.

    Because this table keeps track of more information than the standard
    DPTable, it is not directly compatible.  The dynamic programming can
    be run the same way (and is - PatternCounter doesn't care which DPTable
    class is being used).  However, the table entries can not be used by
    InclusionExclusion, so ColorCounts must be used.  Since the CountCom-
    biner decides which DPTable it uses, there isn't a problem.
    """
    __counters = defaultdict(list)

    def __init__(self, G, reuse=True):
        """
        Arguments
                G: TDDecomposition object

        Optional arguments
                reuse: True to enable clearing/storing of dicts
                    used in table entries.
        """
        self.table = defaultdict(lambda: defaultdict(Counter))
        self.G = G
        self.reuse = reuse
        # If we got reuse=True, store unused Counters for reuse.
        if reuse:
            self.getCounter = ColorDPTable.__getCounter
            self.freeCounter = ColorDPTable.__freeCounter
        # Else, just make new counters and never get rid of old ones.
        else:
            #self.getCounter = Counter
            self.getCounter = ColorDPTable.__getCounter
            self.freeCounter = lambda _, mem_motif: None

    @classmethod
    def __getCounter(cls, mem_motif, reuse=True):
        """Return an empty counter, either from the list or newly created"""
        # if cls.__counters:
        #     return cls.__counters.pop()
        # else:
        #     return Counter()
        if reuse and mem_motif in cls.__counters and cls.__counters[mem_motif]:
            return cls.__counters[mem_motif].pop()

        return Counter()

    @classmethod
    def __freeCounter(cls, counter, mem_motif):
        """Clear a counter and store it in a list for later reuse"""
        if counter:
            counter.clear()

        cls.__counters[mem_motif].append(counter)

    def computeLeaf(self, v, pattern1, mem_motif=None):
        """
        Compute table entry for a given leaf and k-pattern

        Arguments:
                v:  leaf Vertex
                pattern1:  kPattern
        """
        patternSum = self.getCounter(mem_motif, self.reuse)
        # Localize functions to speed up the loop
        self_isIsomorphism = self.isIsomorphism
        patternSum_update = patternSum.update
        # Iterate through all patterns that become pattern1 when they forget<commit_msg>Fixed ColorCount?<commit_after>#
# This file is part of CONCUSS, https://github.com/theoryinpractice/concuss/,
# and is Copyright (C) North Carolina State University, 2015. It is licensed
# under the three-clause BSD license; see LICENSE.
#


from collections import defaultdict, Counter
from itertools import product

from dptable import DPTable


class ColorDPTable(DPTable):
    """
    Dynamic programming table for computing graph isomorphisms.
    See http://arxiv.org/pdf/1406.2587v4.pdf for the algorithm
    and explanations of the table and pattern operations

    This DPTable subclass counts how many times the pattern was seen in each
    set of colors in the TDD.  This allows us to count patterns in fewer sub-
    graphs as we can get all the information we need about smaller sets of
    colors by looking at only the top level.

    Because this table keeps track of more information than the standard
    DPTable, it is not directly compatible.  The dynamic programming can
    be run the same way (and is - PatternCounter doesn't care which DPTable
    class is being used).  However, the table entries can not be used by
    InclusionExclusion, so ColorCounts must be used.  Since the CountCom-
    biner decides which DPTable it uses, there isn't a problem.
    """
    __counters = defaultdict(list)

    def __init__(self, G, reuse=True):
        """
        Arguments
                G: TDDecomposition object

        Optional arguments
                reuse: True to enable clearing/storing of dicts
                    used in table entries.
        """
        self.table = defaultdict(lambda: defaultdict(Counter))
        self.G = G
        self.reuse = reuse
        # If we got reuse=True, store unused Counters for reuse.
        if reuse:
            self.getCounter = ColorDPTable.__getCounter
            self.freeCounter = ColorDPTable.__freeCounter
        # Else, just make new counters and never get rid of old ones.
        else:
            #self.getCounter = Counter
            self.getCounter = ColorDPTable.__getCounter
            self.freeCounter = lambda _, mem_motif: None

    @classmethod
    def __getCounter(cls, mem_motif, reuse=True):
        """Return an empty counter, either from the list or newly created"""
        # if cls.__counters:
        #     return cls.__counters.pop()
        # else:
        #     return Counter()
        if reuse and mem_motif in cls.__counters and cls.__counters[mem_motif]:
            return cls.__counters[mem_motif].pop()

        return Counter()

    @classmethod
    def __freeCounter(cls, counter, mem_motif):
        """Clear a counter and store it in a list for later reuse"""
        if counter:
            counter.clear()
            cls.__counters[mem_motif].append(counter)

    def computeLeaf(self, v, pattern1, mem_motif=None):
        """
        Compute table entry for a given leaf and k-pattern

        Arguments:
                v:  leaf Vertex
                pattern1:  kPattern
        """
        patternSum = self.getCounter(mem_motif, self.reuse)
        # Localize functions to speed up the loop
        self_isIsomorphism = self.isIsomorphism
        patternSum_update = patternSum.update
        # Iterate through all patterns that become pattern1 when they forget
{'fraction_non_alphanumeric': 0.06285192512555167, 'fraction_numerical': 0.004869882818444681, 'mean_word_length': 2.4318537859007834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5818194', 'n_tokens_mistral': 1791, 'n_tokens_neox': 1685, 'n_words': 686}