Module garoupa.algebra.product.product
Classes
class Product (*groups, seed=None)-
Expand source code
class Product(Group): def __init__(self, *groups, seed=None): self.groups = groups identity = Tuple(*(g.identity for g in self.groups)) sorted = lambda: (Tuple(*es) for es in product(*(g.sorted() for g in self.groups))) super().__init__(identity, sorted, seed) @property def comm_degree(self): comms = [g.comm_degree for g in self.groups] if any(comm is None for comm in comms): return return reduce(operator.mul, comms) def __iter__(self): its = [cycle(iter(g)) for g in self.groups] while True: yield Tuple(*(next(it) for it in its)) def __repr__(self): return "×".join([str(g) for g in self.groups]) def __mul__(self, other): if isinstance(other, Product): return Product(*self.groups, *other.groups) return Product(*self.groups, other) def replace(self, *args, **kwargs): dic = {"seed": self.seed} dic.update(kwargs) groups = args or self.groups return self.__class__(*groups, **dic) @classmethod def order_hist_mul(cls, hista, histb): """Histogram of element orders for a product of 2 groups. Usage: >>> from garoupa.algebra.dihedral import D >>> Product.order_hist_mul(D(5).order_hist, D(7).order_hist) {1: 1, 2: 47, 5: 4, 7: 6, 10: 28, 14: 30, 35: 24} Based on Gabriel Dalforno code.""" hist = {} for k1 in hista.keys(): for k2 in histb.keys(): key = cls.lcm(k1, k2) if key not in hist.keys(): hist[key] = hista[k1] * histb[k2] else: hist[key] += hista[k1] * histb[k2] return dict(sorted(hist.items())) @property def order_hist(self): """Sorted histogram of element orders. Usage: >>> from garoupa.algebra.dihedral import D >>> (D(3) * D(5) * D(7)).order_hist {1: 1, 2: 191, 3: 2, 5: 4, 6: 94, 7: 6, 10: 124, 14: 138, 15: 8, 21: 12, 30: 56, 35: 24, 42: 60, 70: 72, 105: 48} """ if self._order_hist is None: self._order_hist = dict(sorted(reduce(self.order_hist_mul, (G.order_hist for G in self.groups)).items())) return self._order_hist def compact_order_hist_lowmem(self, max_histsize, preserve_upto, initial_binsize=1, show_timestamp=True): """Memory-friendly histogram of element orders in a direct product Compact largest intermediate histograms during calculation to avoid memory exhaustion. Nested products will also be processed through this method. Final and temporary hist may exceed max_histsize by a factor of 2 at most. Usage: >>> from garoupa.algebra.dihedral import D >>> Product.order_hist_mul(D(7).order_hist, D(19).order_hist) {1: 1, 2: 159, 7: 6, 14: 114, 19: 18, 38: 126, 133: 108} >>> G = D(3) * D(5) * D(7) * D(9) >>> G.compact_order_hist(binsize=20) {9: 7936, 29: 1064, 42: 1176, 69: 1044, 90: 1080, 105: 192, 126: 1188, 210: 576, 315: 432, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=0, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.1997278911564626 Hist size: 10 False D3*D5*D7 [2] [1] Pi: 0.09817901234567901 Hist size: 12 False D3*D5*D7*D9 [4] [1] {3: 1134, 6: 3402, 9: 2268, 10: 2020, 30: 1076, 35: 84, 70: 1476, 90: 1548, 105: 312, 210: 576, 315: 792, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=10, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.17061791383219957 Hist size: 15 False D3*D5*D7 [2] [1] Pi: 0.11385896951373144 Hist size: 24 False D3*D5*D7*D9 [4] [1] {1: 1, 2: 1919, 3: 8, 5: 4, 6: 1600, 9: 18, 10: 36, 12: 3240, 15: 8, 18: 1746, 21: 36, 30: 672, 35: 24, 36: 1620, 42: 828, 45: 24, 63: 72, 70: 936, 90: 336, 105: 192, 126: 360, 210: 576, 315: 432, 630: 432} """ # if max_histsize <= preserve_upto: errado # raise Exception(f"Cannot preserve up to order {preserve_upto} limited by {max_histsize} at the same time.") def hists(): for g in self.groups: if isinstance(g, Product): yield str(g), g.compact_order_hist_lowmem(max_histsize, preserve_upto, initial_binsize) else: yield str(g), g.order_hist def compact(hist, binsize): while True: hist = self.compact_order_hist( binsize=binsize[0], preserve_upto=preserve_upto, max_histsize=max_histsize, hist=hist ) if 0 in hist: del hist[0] binsize[0] = max(1, int(binsize[0] ** 1 / 2)) break if len(hist) <= max_histsize or binsize[0] > len(hist) // 2: binsize[0] = max(1, int(binsize[0] ** 1 / 2)) break binsize[0] *= 2 return hist binsizea = [initial_binsize] binsizeb = [initial_binsize] def mul(tupa, tupb): ga, hista = tupa gb, histb = tupb hista = compact(hista, binsizea) histb = compact(histb, binsizeb) hist = self.order_hist_mul(hista, histb) prod = f"{ga}*{gb}" print( "Pi:", self._pi_core(hist), f"\tHist size: {len(hist)}\t", show_timestamp and datetime.now().strftime("%d/%m/%Y %H:%M:%S"), f"\t{prod}", binsizea, binsizeb, flush=True, ) return prod, hist return dict(sorted(reduce(mul, hists())[1].items()))Ancestors
Static methods
def order_hist_mul(hista, histb)-
Histogram of element orders for a product of 2 groups.
Usage:
>>> from garoupa.algebra.dihedral import D >>> Product.order_hist_mul(D(5).order_hist, D(7).order_hist) {1: 1, 2: 47, 5: 4, 7: 6, 10: 28, 14: 30, 35: 24}Based on Gabriel Dalforno code.
Instance variables
prop comm_degree-
Expand source code
@property def comm_degree(self): comms = [g.comm_degree for g in self.groups] if any(comm is None for comm in comms): return return reduce(operator.mul, comms) prop order_hist-
Expand source code
@property def order_hist(self): """Sorted histogram of element orders. Usage: >>> from garoupa.algebra.dihedral import D >>> (D(3) * D(5) * D(7)).order_hist {1: 1, 2: 191, 3: 2, 5: 4, 6: 94, 7: 6, 10: 124, 14: 138, 15: 8, 21: 12, 30: 56, 35: 24, 42: 60, 70: 72, 105: 48} """ if self._order_hist is None: self._order_hist = dict(sorted(reduce(self.order_hist_mul, (G.order_hist for G in self.groups)).items())) return self._order_histSorted histogram of element orders.
Usage:
>>> from garoupa.algebra.dihedral import D >>> (D(3) * D(5) * D(7)).order_hist {1: 1, 2: 191, 3: 2, 5: 4, 6: 94, 7: 6, 10: 124, 14: 138, 15: 8, 21: 12, 30: 56, 35: 24, 42: 60, 70: 72, 105: 48}
Methods
def compact_order_hist_lowmem(self, max_histsize, preserve_upto, initial_binsize=1, show_timestamp=True)-
Expand source code
def compact_order_hist_lowmem(self, max_histsize, preserve_upto, initial_binsize=1, show_timestamp=True): """Memory-friendly histogram of element orders in a direct product Compact largest intermediate histograms during calculation to avoid memory exhaustion. Nested products will also be processed through this method. Final and temporary hist may exceed max_histsize by a factor of 2 at most. Usage: >>> from garoupa.algebra.dihedral import D >>> Product.order_hist_mul(D(7).order_hist, D(19).order_hist) {1: 1, 2: 159, 7: 6, 14: 114, 19: 18, 38: 126, 133: 108} >>> G = D(3) * D(5) * D(7) * D(9) >>> G.compact_order_hist(binsize=20) {9: 7936, 29: 1064, 42: 1176, 69: 1044, 90: 1080, 105: 192, 126: 1188, 210: 576, 315: 432, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=0, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.1997278911564626 Hist size: 10 False D3*D5*D7 [2] [1] Pi: 0.09817901234567901 Hist size: 12 False D3*D5*D7*D9 [4] [1] {3: 1134, 6: 3402, 9: 2268, 10: 2020, 30: 1076, 35: 84, 70: 1476, 90: 1548, 105: 312, 210: 576, 315: 792, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=10, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.17061791383219957 Hist size: 15 False D3*D5*D7 [2] [1] Pi: 0.11385896951373144 Hist size: 24 False D3*D5*D7*D9 [4] [1] {1: 1, 2: 1919, 3: 8, 5: 4, 6: 1600, 9: 18, 10: 36, 12: 3240, 15: 8, 18: 1746, 21: 36, 30: 672, 35: 24, 36: 1620, 42: 828, 45: 24, 63: 72, 70: 936, 90: 336, 105: 192, 126: 360, 210: 576, 315: 432, 630: 432} """ # if max_histsize <= preserve_upto: errado # raise Exception(f"Cannot preserve up to order {preserve_upto} limited by {max_histsize} at the same time.") def hists(): for g in self.groups: if isinstance(g, Product): yield str(g), g.compact_order_hist_lowmem(max_histsize, preserve_upto, initial_binsize) else: yield str(g), g.order_hist def compact(hist, binsize): while True: hist = self.compact_order_hist( binsize=binsize[0], preserve_upto=preserve_upto, max_histsize=max_histsize, hist=hist ) if 0 in hist: del hist[0] binsize[0] = max(1, int(binsize[0] ** 1 / 2)) break if len(hist) <= max_histsize or binsize[0] > len(hist) // 2: binsize[0] = max(1, int(binsize[0] ** 1 / 2)) break binsize[0] *= 2 return hist binsizea = [initial_binsize] binsizeb = [initial_binsize] def mul(tupa, tupb): ga, hista = tupa gb, histb = tupb hista = compact(hista, binsizea) histb = compact(histb, binsizeb) hist = self.order_hist_mul(hista, histb) prod = f"{ga}*{gb}" print( "Pi:", self._pi_core(hist), f"\tHist size: {len(hist)}\t", show_timestamp and datetime.now().strftime("%d/%m/%Y %H:%M:%S"), f"\t{prod}", binsizea, binsizeb, flush=True, ) return prod, hist return dict(sorted(reduce(mul, hists())[1].items()))Memory-friendly histogram of element orders in a direct product
Compact largest intermediate histograms during calculation to avoid memory exhaustion. Nested products will also be processed through this method. Final and temporary hist may exceed max_histsize by a factor of 2 at most.
Usage:
>>> from garoupa.algebra.dihedral import D >>> Product.order_hist_mul(D(7).order_hist, D(19).order_hist) {1: 1, 2: 159, 7: 6, 14: 114, 19: 18, 38: 126, 133: 108} >>> G = D(3) * D(5) * D(7) * D(9) >>> G.compact_order_hist(binsize=20) {9: 7936, 29: 1064, 42: 1176, 69: 1044, 90: 1080, 105: 192, 126: 1188, 210: 576, 315: 432, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=0, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.1997278911564626 Hist size: 10 False D3*D5*D7 [2] [1] Pi: 0.09817901234567901 Hist size: 12 False D3*D5*D7*D9 [4] [1] {3: 1134, 6: 3402, 9: 2268, 10: 2020, 30: 1076, 35: 84, 70: 1476, 90: 1548, 105: 312, 210: 576, 315: 792, 630: 432} >>> G.compact_order_hist_lowmem(max_histsize=5, preserve_upto=10, show_timestamp=False) # doctest: +NORMALIZE_WHITESPACE Pi: 0.28944444444444445 Hist size: 7 False D3*D5 [1] [1] Pi: 0.17061791383219957 Hist size: 15 False D3*D5*D7 [2] [1] Pi: 0.11385896951373144 Hist size: 24 False D3*D5*D7*D9 [4] [1] {1: 1, 2: 1919, 3: 8, 5: 4, 6: 1600, 9: 18, 10: 36, 12: 3240, 15: 8, 18: 1746, 21: 36, 30: 672, 35: 24, 36: 1620, 42: 828, 45: 24, 63: 72, 70: 936, 90: 336, 105: 192, 126: 360, 210: 576, 315: 432, 630: 432} def replace(self, *args, **kwargs)-
Expand source code
def replace(self, *args, **kwargs): dic = {"seed": self.seed} dic.update(kwargs) groups = args or self.groups return self.__class__(*groups, **dic)
Inherited members