# -*- python -*- # encoding: utf-8 """ cluster.py Created by Michael Brickenstein on 2011-08-05. Copyright 2011 The PolyBoRi Team. See LICENSE file. """ import sys import os from polybori.statistics import used_vars, used_vars_set from polybori.PyPolyBoRi import Variable def main(): pass class ClusterAlgorithmFailed(Exception): pass class ClusterAlgorithm(object): def __init__(self, ideal, determination_modifier=1): if len(ideal) == 0: raise ValueError, 'ideal generators list should be non empty' self.ideal = ideal self.determination_modifier = determination_modifier self.used_variables_ideal = used_vars_set(ideal) self.number_of_used_variables_in_ideal = len(self.used_variables_ideal) self.used_variables_of_polynomial = dict( [(p, set(p.vars_as_monomial().variables())) for p in ideal]) self.variables_introduction_mapping = dict() self.cluster = set() self.used_variables_cluster = set() self.build_variables_usage() self.initialize_variables_introduction_mapping() def build_variables_usage(self): self.variables_usage = dict() for (p, variables) in self.used_variables_of_polynomial.iteritems(): for v in variables: self.variables_usage.setdefault(v, []).append(p) def initialize_variables_introduction_mapping(self): self._build_variables_introduction_mapping() def _build_variables_introduction_mapping(self): def var_set_to_tuple(s): return tuple(sorted(s, key=Variable.index)) self.variables_introduction_mapping.clear() for (p, var_set) in self.used_variables_of_polynomial.iteritems(): if p in self.cluster: continue as_tuple = var_set_to_tuple(var_set.difference(self. used_variables_cluster)) self.variables_introduction_mapping.setdefault( as_tuple, []).append(p) def adjust_variables_introduction_mapping(self, introduced_variables): self._build_variables_introduction_mapping() def determined_enough(self): return (self.number_of_used_variables_in_cluster + self. determination_modifier <= len(self.cluster)) def find_cluster(self): p = self.initial_choice() self.cluster = set() self.add_polynomial_to_cluster(p) while not self.determined_enough(): self.increase_cluster() return list(self.cluster) def add_polynomial_to_cluster(self, p): self.cluster.add(p) self.used_variables_cluster = set(used_vars_set(self.cluster). variables()) self.number_of_used_variables_in_cluster = len(self. used_variables_cluster) self.adjust_variables_introduction_mapping(self. used_variables_of_polynomial[p]) def initial_choice(self): def max_key(entry): (entry_variable, entry_polynomials) = entry return len(entry_polynomials) (variable, polynomials) = max(self.variables_usage.iteritems(), key=max_key) def min_key(p): return len(self.used_variables_of_polynomial[p]) return min(polynomials, key=min_key) def increase_cluster(self): introduced_variables_possibilities = (self. variables_introduction_mapping.keys()) introduced_variables = min(introduced_variables_possibilities, key=len) polynomials = self.variables_introduction_mapping[introduced_variables] assert len(polynomials) > 0 for p in polynomials: self.add_polynomial_to_cluster(p) if len(self.cluster) == len(self.ideal): raise ClusterAlgorithmFailed self.adjust_variables_introduction_mapping(introduced_variables) def find_cluster(ideal): algorithm = ClusterAlgorithm(ideal) return algorithm.find_cluster() if __name__ == '__main__': main()