def __init__(self, crystals, **options): """ TESTS:: sage: from sage.combinat.crystals.tensor_product import FullTensorProductOfCrystals sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: isinstance(T, FullTensorProductOfCrystals) True sage: TestSuite(T).run() """ crystals = list(crystals) category = Category.meet([crystal.category() for crystal in crystals]) Parent.__init__(self, category = category) self.rename("Full tensor product of the crystals %s"%(crystals,)) self.crystals = crystals if options.has_key('cartan_type'): self._cartan_type = CartanType(options['cartan_type']) else: if len(crystals) == 0: raise ValueError, "you need to specify the Cartan type if the tensor product list is empty" else: self._cartan_type = crystals[0].cartan_type() self.cartesian_product = CartesianProduct(*self.crystals) self.module_generators = self
def _children_iter(self, node): """ Iterate over all children nodes. This is a helper iterator to iterate over all children, by generating and/or computing them, of a given Kleber tree node this isn't the root. We perform the dominance iteration by using the condition that that new root must be smaller than the previous root. INPUT: - ``node`` -- The current node in the tree whose children we want to generate TESTS:: sage: KT = KleberTree(['D', 4], [[2,2]]) sage: KT[1] Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] sage: for x in KT: x ... Kleber tree node with weight [0, 2, 0, 0] and upwards edge root [0, 0, 0, 0] Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] sage: for x in KT._children_iter(KT[1]): x ... Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] """ n = self._cartan_type.n cartan_matrix = self._cartan_type.cartan_matrix() RS = self._cartan_type.root_system() WS = RS.weight_space() L = [] for val in node.up_root.to_vector(): L.append(range(val + 1)) root_list = CartesianProduct(*L).list() root_list.pop(0) # First element is the zero element root_basis = RS.root_space().basis() for root in root_list: # Convert the list to an honest root in the root space converted_root = RS.root_space().zero() for i, val in enumerate(root): converted_root += val * root_basis[i + 1] # Add 1 for indexing new_weight = node.weight - WS(converted_root) if new_weight.is_dominant(): yield KleberTreeNode(self, new_weight, converted_root, node)
def _children_iter(self, node): """ Iterate over all children nodes. This is a helper iterator to iterate over all children, by generating and/or computing them, of a given Kleber tree node this isn't the root. We perform the dominance iteration by using the condition that that new root must be smaller than the previous root. INPUT: - ``node`` -- The current node in the tree whose children we want to generate TESTS:: sage: KT = KleberTree(['D', 4], [[2,2]]) sage: KT[1] Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] sage: for x in KT: x ... Kleber tree node with weight [0, 2, 0, 0] and upwards edge root [0, 0, 0, 0] Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] sage: for x in KT._children_iter(KT[1]): x ... Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] """ n = self._cartan_type.n cartan_matrix = self._cartan_type.cartan_matrix() RS = self._cartan_type.root_system() WS = RS.weight_space() L = [] for val in node.up_root.to_vector(): L.append(range(val + 1)) root_list = CartesianProduct(*L).list() root_list.pop(0) # First element is the zero element root_basis = RS.root_space().basis() for root in root_list: # Convert the list to an honest root in the root space converted_root = RS.root_space().zero() for i, val in enumerate(root): converted_root += val * root_basis[i+1] # Add 1 for indexing new_weight = node.weight - WS(converted_root) if new_weight.is_dominant(): yield KleberTreeNode(self, new_weight, converted_root, node)
def _test_euclidean_degree(self, **options): r""" Test that the assumptions on a euclidean degree are met. EXAMPLES:: sage: R.<x> = QQ[] sage: R._test_euclidean_degree() .. SEEALSO:: :meth:`_test_quo_rem` """ tester = self._tester(**options) S = [s for s in tester.some_elements() if not s.is_zero()] min_degree = self.one().euclidean_degree() from sage.rings.all import NN for a in S: tester.assertIn(a.euclidean_degree(), NN) tester.assertGreaterEqual(a.euclidean_degree(), min_degree) tester.assertEqual(a.euclidean_degree() == min_degree, a.is_unit()) from sage.combinat.cartesian_product import CartesianProduct for a,b in tester.some_elements(CartesianProduct(S,S)): p = a * b # For rings which are not exact, we might get something that # acts like a zero divisor. # Therefore we skip the product if it evaluates to zero. # Let the category of Domains handle the test for zero divisors. if p.is_zero(): continue tester.assertLessEqual(a.euclidean_degree(), p.euclidean_degree())
def _test_quo_rem(self, **options): r""" Test that the assumptions on a quotient with remainder of an euclidean domain are met. EXAMPLES:: sage: R.<x> = QQ[] sage: R._test_quo_rem() .. SEEALSO:: :meth:`_test_euclidean_degree` """ tester = self._tester(**options) S = tester.some_elements() from sage.combinat.cartesian_product import CartesianProduct for a,b in tester.some_elements(CartesianProduct(S,S)): if b.is_zero(): tester.assertRaises(ZeroDivisionError, lambda: a.quo_rem(b)) else: q,r = a.quo_rem(b) tester.assertIn(q, self) tester.assertIn(r, self) tester.assertEqual(a,q*b+r) if r != 0: tester.assertLess(r.euclidean_degree(), b.euclidean_degree())
def _test_additive_associativity(self, **options): r""" Test associativity for (not necessarily all) elements of this additive semigroup. INPUT: - ``options`` -- any keyword arguments accepted by :meth:`_tester` EXAMPLES: By default, this method tests only the elements returned by ``self.some_elements()``:: sage: S = CommutativeAdditiveSemigroups().example() sage: S._test_additive_associativity() However, the elements tested can be customized with the ``elements`` keyword argument:: sage: (a,b,c,d) = S.additive_semigroup_generators() sage: S._test_additive_associativity(elements = (a, b+c, d)) See the documentation for :class:`TestSuite` for more information. """ tester = self._tester(**options) S = tester.some_elements() from sage.combinat.cartesian_product import CartesianProduct for x,y,z in tester.some_elements(CartesianProduct(S,S,S)): tester.assert_((x + y) + z == x + (y + z))
def _test_distributivity(self, **options): r""" Test the distributivity of `*` on `+` on (not necessarily all) elements of this set. INPUT:: - ``options`` -- any keyword arguments accepted by :meth:`_tester` EXAMPLES: By default, this method runs the tests only on the elements returned by ``self.some_elements()``:: sage: NN.some_elements() [0, 1, 3, 42] sage: NN._test_distributivity() However, the elements tested can be customized with the ``elements`` keyword argument:: sage: CC._test_distributivity(elements=[CC(0),CC(1),CC(3),CC(I)]) See the documentation for :class:`TestSuite` for more information. """ tester = self._tester(**options) S = tester.some_elements() from sage.combinat.cartesian_product import CartesianProduct for x,y,z in tester.some_elements(CartesianProduct(S,S,S)): # left distributivity tester.assert_(x * (y + z) == (x * y) + (x * z)) # right distributivity tester.assert_((x + y) * z == (x * z) + (y * z))
def _test_div(self, **options): """ Test division of elements of this ring. INPUT: - ``options`` -- any keyword arguments accepted by :meth:`_tester`. EXAMPLES:: sage: Zp(3)._test_div() .. SEEALSO:: :class:`TestSuite` """ tester = self._tester(**options) from sage.combinat.cartesian_product import CartesianProduct elements = CartesianProduct(tester.some_elements(), tester.some_elements()) if len(elements) > tester._max_runs: from random import sample elements = sample(elements, tester._max_runs) for x,y in elements: try: z = x / y except (ZeroDivisionError, PrecisionError, ValueError): if self.is_fixed_mod(): tester.assertFalse(y.is_unit()) else: tester.assertTrue(y.is_zero()) else: tester.assertFalse(y.is_zero()) tester.assertIs(z.parent(), self if self.is_fixed_mod() else self.fraction_field()) tester.assertEqual(z.precision_relative(), min(x.precision_relative(), y.precision_relative())) tester.assertEqual(z.valuation(), x.valuation() - y.valuation())
def __iter__(self): """ A basic generator .. TODO:: could be optimized. TESTS:: sage: OrderedTrees(0).list() [] sage: OrderedTrees(1).list() [[]] sage: OrderedTrees(2).list() [[[]]] sage: OrderedTrees(3).list() [[[], []], [[[]]]] sage: OrderedTrees(4).list() [[[], [], []], [[], [[]]], [[[]], []], [[[], []]], [[[[]]]]] """ if self._size == 0: return else: for c in Compositions(self._size - 1): for lst in CartesianProduct(*(map(self.__class__, c))): yield self._element_constructor_(lst)
def rescalings(self): """ Return the rescalings of homogeneous coordinates. OUTPUT: A tuple containing all points that are equivalent to `[1:1:\dots:1]`, the distinguished point of the big torus orbit. EXAMPLES:: sage: ni = toric_varieties.P2_123(base_ring=GF(5)).point_set()._naive_enumerator() sage: ni.rescalings() ((1, 1, 1), (1, 4, 4), (4, 2, 3), (4, 3, 2)) sage: ni = toric_varieties.dP8(base_ring=GF(3)).point_set()._naive_enumerator() sage: ni.rescalings() ((1, 1, 1, 1), (1, 2, 2, 2), (2, 1, 2, 1), (2, 2, 1, 2)) sage: ni = toric_varieties.P1xP1(base_ring=GF(3)).point_set()._naive_enumerator() sage: ni.rescalings() ((1, 1, 1, 1), (1, 1, 2, 2), (2, 2, 1, 1), (2, 2, 2, 2)) """ free = self._Chow_group_free() tors = self._Chow_group_torsion() if len(tors) == 0: # optimization for smooth fans return free result = set(free) for f, t in CartesianProduct(free, tors): phases = tuple(x * y for x, y in zip(f, t)) result.add(phases) return tuple(sorted(result))
def _Chow_group_free(self): r""" Return the relations coming from the free part of the Chow group OUTPUT: A tuple containing the elements of $Hom(A_{d-1,\text{free}}, F^\times)$, including the identity. EXAMPLES:: sage: fan = NormalFan(ReflexivePolytope(2, 0)) sage: X = ToricVariety(fan, base_field=GF(7)) sage: X.Chow_group().degree(1) C3 x Z sage: enum = X.point_set()._naive_enumerator() sage: enum._Chow_group_free() ((1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6)) """ units = self.units() result = [] rays = self.fan().rays() + self.fan().virtual_rays() ker = rays.matrix().integer_kernel().matrix() for phases in CartesianProduct(*([units] * ker.nrows())): phases = tuple( prod(mu**exponent for mu, exponent in zip(phases, column)) for column in ker.columns()) result.append(phases) return tuple(sorted(result))
def _test_associativity(self, **options): r""" Test associativity for (not necessarily all) elements of this semigroup. INPUT:: - ``options`` -- any keyword arguments accepted by :meth:`_tester`. EXAMPLES: By default, this method tests only the elements returned by ``self.some_elements()``:: sage: L = Semigroups().example(choice='leftzero') sage: L._test_associativity() However, the elements tested can be customized with the ``elements`` keyword argument:: sage: L._test_associativity(elements = (L(1), L(2), L(3))) See the documentation for :class:`TestSuite` for more information. """ tester = self._tester(**options) S = tester.some_elements() from sage.combinat.cartesian_product import CartesianProduct for x, y, z in tester.some_elements(CartesianProduct(S, S, S)): tester.assert_((x * y) * z == x * (y * z))
def _test_mul(self, **options): """ Test multiplication of elements of this ring. INPUT: - ``options`` -- any keyword arguments accepted by :meth:`_tester`. EXAMPLES:: sage: Zp(3)._test_mul() .. SEEALSO:: :class:`TestSuite` """ tester = self._tester(**options) from sage.combinat.cartesian_product import CartesianProduct elements = CartesianProduct(tester.some_elements(), tester.some_elements()) if len(elements) > tester._max_runs: from random import sample elements = sample(elements, tester._max_runs) for x,y in elements: z = x * y tester.assertIs(z.parent(), self) tester.assertLessEqual(z.precision_relative(), min(x.precision_relative(), y.precision_relative())) if not z.is_zero(): tester.assertEqual(z.valuation(), x.valuation() + y.valuation())
def _structures(self, structure_class, labels): """ EXAMPLES:: sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) sage: L.structures(['a','b','c']).list() [F-structure: {{'a', 'b', 'c'}}; G-structures: [('a', 'b', 'c')], F-structure: {{'a', 'b', 'c'}}; G-structures: [('a', 'c', 'b')], F-structure: {{'a', 'c'}, {'b'}}; G-structures: [('a', 'c'), ('b')], F-structure: {{'a', 'b'}, {'c'}}; G-structures: [('a', 'b'), ('c')], F-structure: {{'b', 'c'}, {'a'}}; G-structures: [('b', 'c'), ('a')], F-structure: {{'a'}, {'b'}, {'c'}}; G-structures: [('a'), ('b'), ('c')]] TESTS:: sage: a = _[2] sage: f, gs = a._list sage: f {{'a', 'c'}, {'b'}} sage: f.parent() Set species sage: f._list [1, 2] sage: f._labels [{'a', 'c'}, {'b'}] sage: [g.parent() for g in gs] [Cyclic permutation species, Cyclic permutation species] sage: [g._labels for g in gs] [['a', 'c'], ['b']] sage: [g._list for g in gs] [[1, 2], [1]] """ from sage.combinat.cartesian_product import CartesianProduct P = PartitionSpecies() for pi in P.structures(labels): #The labels of the G-structures will be just be the things #in labels gs = CartesianProduct( *[self._G.structures(part.labels()) for part in pi]) #The labels of the F-structure will be set objects fs = self._F.structures(list(pi)) for f, gg in CartesianProduct(fs, gs): yield structure_class(self, labels, pi, f, gg)
class FullTensorProductOfCrystals(CrystalOfWords): def __init__(self, crystals, **options): """ TESTS:: sage: from sage.combinat.crystals.tensor_product import FullTensorProductOfCrystals sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: isinstance(T, FullTensorProductOfCrystals) True sage: TestSuite(T).run() """ crystals = list(crystals) category = Category.meet([crystal.category() for crystal in crystals]) Parent.__init__(self, category=category) self.rename("Full tensor product of the crystals %s" % (crystals, )) self.crystals = crystals if options.has_key('cartan_type'): self._cartan_type = CartanType(options['cartan_type']) else: if len(crystals) == 0: raise ValueError, "you need to specify the Cartan type if the tensor product list is empty" else: self._cartan_type = crystals[0].cartan_type() self.cartesian_product = CartesianProduct(*self.crystals) self.module_generators = self # TODO: __iter__ and cardinality should be inherited from EnumeratedSets().CartesianProducts() def __iter__(self): """ EXAMPLES:: sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: list(T) [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]] sage: _[0].parent() Full tensor product of the crystals [The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]] """ for x in self.cartesian_product: yield self(*x) # list = CombinatorialClass._CombinatorialClass__list_from_iterator def cardinality(self): """ EXAMPLES:: sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: T.cardinality() 9 """ return self.cartesian_product.cardinality()
class FullTensorProductOfCrystals(CrystalOfWords): def __init__(self, crystals, **options): """ TESTS:: sage: from sage.combinat.crystals.tensor_product import FullTensorProductOfCrystals sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: isinstance(T, FullTensorProductOfCrystals) True sage: TestSuite(T).run() """ crystals = list(crystals) category = Category.meet([crystal.category() for crystal in crystals]) Parent.__init__(self, category = category) self.rename("Full tensor product of the crystals %s"%(crystals,)) self.crystals = crystals if options.has_key('cartan_type'): self._cartan_type = CartanType(options['cartan_type']) else: if len(crystals) == 0: raise ValueError, "you need to specify the Cartan type if the tensor product list is empty" else: self._cartan_type = crystals[0].cartan_type() self.cartesian_product = CartesianProduct(*self.crystals) self.module_generators = self # TODO: __iter__ and cardinality should be inherited from EnumeratedSets().CartesianProducts() def __iter__(self): """ EXAMPLES:: sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: list(T) [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]] sage: _[0].parent() Full tensor product of the crystals [The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]] """ for x in self.cartesian_product: yield self(*x) # list = CombinatorialClass._CombinatorialClass__list_from_iterator def cardinality(self): """ EXAMPLES:: sage: C = CrystalOfLetters(['A',2]) sage: T = TensorProductOfCrystals(C,C) sage: T.cardinality() 9 """ return self.cartesian_product.cardinality()
def matrix_combinatorial_adjoint(mat): r""" Return Combinatorial Adjoint. """ dim = mat.nrows() M = list() mat_space = MatrixSpace(CombinatorialScalarRing(), dim) prnt = mat_space.base_ring() #create list L of lists of sets, dimension is increased by one to mitigate index confusion L = list() for i in range(dim + 1): L.append(list()) for j in range(dim + 1): L[i].append(set()) P = Permutations(dim) for p in P: p_comb = CombinatorialScalarWrapper( [CombinatorialObject(p, p.signature())]) l = list() for i in range(1, dim + 1): l.append(mat[p(i) - 1, i - 1]) #This list will have empty sets, which will yield to an empty cartesian product #especially when the matrix input is triangular (except for the identity permutation). #We will now iterate through the selected entries in each column #and create a set of a singleton of an empty string that corresponds #to the "missing" element of the tuple described in definition 39. for i in range(1, dim + 1): copy_l = copy(l) copy_l[i - 1] = CombinatorialScalarWrapper( [CombinatorialObject('_', 1)]) cp = CartesianProduct(p_comb, *copy_l) for tupel in cp: tupel = tuple(tupel) tupel_weight = 1 tupel_sign = 1 for elm in tupel: tupel_sign = tupel_sign * elm.get_sign() tupel_weight = tupel_weight * elm.get_weight() L[i][p(i)].add( CombinatorialObject(tupel, tupel_sign, tupel_weight)) #turn these sets into CombinatorialScalars for i in range(1, dim + 1): l = list() for j in range(1, dim + 1): l.append(CombinatorialScalarWrapper(L[i][j])) M.append(l) return mat_space(M)
def _monomial_product(self, xi, v): """ Result of acting by the basis element ``xi`` of the corresponding Schur algebra on the basis element ``v`` of ``self``. EXAMPLES:: sage: T = SchurTensorModule(QQ, 2, 3) sage: xi = T._schur.basis().keys()[4]; xi ((1, 1, 2), (1, 1, 1)) sage: T._monomial_product(xi, (1, 1, 1)) B[1] # B[1] # B[2] + B[1] # B[2] # B[1] + B[2] # B[1] # B[1] """ ret = [] for i in CartesianProduct(*[range(1, self._n + 1)] * self._r): if schur_representative_from_index(i, v) == xi: ret.append(tuple(i)) return self.sum_of_monomials(ret)
def coordinate_iter(self): """ Iterate over all distinct homogeneous coordinates. This method does NOT identify homogeneous coordinates that are equivalent by a homogeneous rescaling. OUTPUT: An iterator over the points. EXAMPLES:: sage: F2 = GF(2) sage: ni = toric_varieties.P2(base_ring=F2).point_set()._naive_enumerator() sage: list(ni.coordinate_iter()) [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0), (1, 1, 1)] sage: ni = toric_varieties.P1xP1(base_ring=F2).point_set()._naive_enumerator() sage: list(ni.coordinate_iter()) [(0, 1, 0, 1), (1, 0, 0, 1), (1, 0, 1, 0), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)] TESTS:: sage: V = ToricVariety(Fan([Cone([(1,1)])]), base_ring=GF(3)) sage: ni = V.point_set()._naive_enumerator() sage: list(ni.coordinate_iter()) [(0, 1), (0, 2), (1, 1), (1, 2), (2, 1), (2, 2)] """ units = [x for x in self.ring if x != 0] zero = self.ring.zero() rays = self.fan.rays() + self.fan.virtual_rays() big_torus = [units] * len(rays) for cone in self.cone_iter(): patch = copy(big_torus) for i in cone.ambient_ray_indices(): patch[i] = [zero] for p in CartesianProduct(*patch): yield tuple(p)
def _test_zero_divisors(self, **options): """ Check to see that there are no zero divisors. .. NOTE:: In rings whose elements can not be represented exactly, there may be zero divisors in practice, even though these rings do not have them in theory. For such inexact rings, these tests are not performed: sage: R = ZpFM(5); R 5-adic Ring of fixed modulus 5^20 sage: R.is_exact() False sage: a = R(5^19) sage: a.is_zero() False sage: (a*a).is_zero() True sage: R._test_zero_divisors() EXAMPLES:: sage: ZZ._test_zero_divisors() sage: ZpFM(5)._test_zero_divisors() """ if not self.is_exact(): return # Can't check on inexact rings tester = self._tester(**options) # Filter out zero S = [s for s in tester.some_elements() if not s.is_zero()] from sage.combinat.cartesian_product import CartesianProduct for a, b in tester.some_elements(CartesianProduct(S, S)): p = a * b tester.assertFalse(p.is_zero())
def _test_sub(self, **options): """ Test subtraction on elements of this ring. INPUT: - ``options`` -- any keyword arguments accepted by :meth:`_tester`. EXAMPLES:: sage: Zp(3)._test_sub() .. SEEALSO:: :class:`TestSuite` """ tester = self._tester(**options) elements = tester.some_elements() for x in elements: y = x - self.zero() tester.assertEqual(y, x) tester.assertEqual(y.precision_absolute(), x.precision_absolute()) tester.assertEqual(y.precision_relative(), x.precision_relative()) from sage.combinat.cartesian_product import CartesianProduct elements = CartesianProduct(elements, elements) if len(elements) > tester._max_runs: from random import sample elements = sample(elements, tester._max_runs) for x,y in elements: z = x - y tester.assertIs(z.parent(), self) tester.assertEqual(z.precision_absolute(), min(x.precision_absolute(), y.precision_absolute())) tester.assertGreaterEqual(z.valuation(), min(x.valuation(),y.valuation())) if x.valuation() != y.valuation(): tester.assertEqual(z.valuation(), min(x.valuation(),y.valuation())) tester.assertEqual(z - x, -y) tester.assertEqual(z + y, x)
def add_inequality(self, a): """ Return a new double description pair with the inequality `a` added. INPUT: - ``a`` -- vector. An inequality. OUTPUT: A new :class:`StandardDoubleDescriptionPair` instance. EXAMPLES:: sage: A = matrix([(-1, 1, 0), (-1, 2, 1), (1/2, -1/2, -1)]) sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm sage: DD, _ = StandardAlgorithm(A).initial_pair() sage: newDD = DD.add_inequality(vector([1,0,0])); newDD Double description pair (A, R) defined by [ -1 1 0] [ 1 1 0 0] A = [ -1 2 1], R = [ 1 1 1 1] [ 1/2 -1/2 -1] [ 0 -1 -1/2 -2] [ 1 0 0] """ from sage.combinat.cartesian_product import CartesianProduct R_pos, R_nul, R_neg = self.R_by_sign(a) if len(R_neg) == 0: return self R_new = [] for rp, rn in CartesianProduct(R_pos, R_neg): if not self.are_adjacent(rp, rn): continue r = a.inner_product(rp) * rn - a.inner_product(rn) * rp r.set_immutable() R_new.append(r) R_new = tuple(R_pos + R_nul + R_new) A_new = self.A + (a, ) return self._make_new(A_new, R_new)
def _iterator_part(self, part): """ Return an iterator for the set partitions with block sizes corresponding to the partition part. INPUT: - ``part`` -- a :class:`Partition` object EXAMPLES:: sage: S = SetPartitions(3) sage: it = S._iterator_part(Partition([1,1,1])) sage: list(sorted(map(list, it.next()))) [[1], [2], [3]] sage: S21 = SetPartitions(3,Partition([2,1])) sage: len(list(S._iterator_part(Partition([2,1])))) == S21.cardinality() True """ nonzero = [] expo = [0] + part.to_exp() for i in range(len(expo)): if expo[i] != 0: nonzero.append([i, expo[i]]) taillesblocs = map(lambda x: (x[0]) * (x[1]), nonzero) blocs = OrderedSetPartitions(self._set, taillesblocs) for b in blocs: lb = [ IterableFunctionCall(_listbloc, nonzero[i][0], nonzero[i][1], b[i]) for i in range(len(nonzero)) ] for x in itertools.imap(lambda x: _union(x), CartesianProduct(*lb)): yield x
def __iter__(self): """ EXAMPLES:: sage: M = FiniteSetMaps(2,2) sage: M.list() [[0, 0], [0, 1], [1, 0], [1, 1]] TESTS:: sage: FiniteSetMaps(0,0).list() [[]] sage: FiniteSetMaps(0,1).list() [[]] sage: FiniteSetMaps(0,10).list() [[]] sage: FiniteSetMaps(1,0).list() [] sage: FiniteSetMaps(1,1).list() [[0]] """ for v in CartesianProduct(*([range(self._n)] * self._m)): yield self._from_list_(v)
def matrix_determinant(mat): r""" Return determinant scalar, the form of which is: (\sigma,a_1,...,a_n) where sign \sigma is sgn(\sigma) and weight \sigma is 1. """ dim = mat.nrows() P = Permutations(dim) S = set() for p in P: l = list() p_comb = CombinatorialScalarWrapper( [CombinatorialObject(p, p.signature())]) for i in range(1, dim + 1): l.append(mat[i - 1, p(i) - 1]) cp = CartesianProduct(p_comb, *l) for i in cp: weight = 1 sign = 1 for elm in i: sign = sign * elm.get_sign() weight = weight * elm.get_weight() S.add(CombinatorialObject(tuple(i), sign, weight)) return CombinatorialScalarWrapper(S)
def assert_strict_weak_order(a,b,c, cmp_func): r""" Checks that ``cmp_func`` is a strict weak order. A strict weak order is a binary relation ``<`` such that * For all `x`, it is not the case that `x < x` (irreflexivity). * For all `x\not=y`, if `x < y` then it is not the case that `y < x` (asymmetric). * For all `x`, `y`, and `z`, if `x < y` and `y < z` then `x < z` (transitivity). * For all `x`, `y`, and `z`, if x is incomparable with `y`, and `y` is incomparable with `z`, then `x` is incomparable with `z` (transitivity of equivalence). INPUT: - ``a``, ``b``, ``c`` -- anything that can be compared by ``cmp_func``. - ``cmp_func`` -- function of two arguments that returns their comparison (i.e. either ``True`` or ``False``). OUTPUT: Does not return anything. Raises a ``ValueError`` if ``cmp_func`` is not a strict weak order on the three given elements. REFERENCES: http://en.wikipedia.org/wiki/Strict_weak_ordering EXAMPLES: The usual ordering of integers is a strict weak order:: sage: from sage.symbolic.random_tests import assert_strict_weak_order sage: a, b, c = [ randint(-10,10) for i in range(0,3) ] sage: assert_strict_weak_order(a,b,c, lambda x,y: x<y) sage: x = [SR(unsigned_infinity), SR(oo), -SR(oo)] sage: cmp = matrix(3,3) sage: indices = list(CartesianProduct(range(0,3),range(0,3))) sage: for i,j in CartesianProduct(range(0,3),range(0,3)): ... cmp[i,j] = x[i].__cmp__(x[j]) sage: cmp [ 0 -1 -1] [ 1 0 -1] [ 1 1 0] """ from sage.matrix.constructor import matrix from sage.combinat.cartesian_product import CartesianProduct from sage.combinat.permutation import Permutations x = (a,b,c) cmp = matrix(3,3) indices = list(CartesianProduct(range(0,3),range(0,3))) for i,j in indices: cmp[i,j] = (cmp_func(x[i], x[j]) == 1) # or -1, doesn't matter msg = 'The binary relation failed to be a strict weak order on the elements\n' msg += ' a = '+str(a)+'\n' msg += ' b = '+str(b)+'\n' msg += ' c = '+str(c)+'\n' msg += str(cmp) for i in range(0,3): # irreflexivity if cmp[i,i]: raise ValueError(msg) for i,j in indices: # asymmetric if i==j: continue #if x[i] == x[j]: continue if cmp[i,j] and cmp[j,i]: raise ValueError(msg) for i,j,k in Permutations([0,1,2]): # transitivity if cmp[i,j] and cmp[j,k] and not cmp[i,k]: raise ValueError(msg) def incomparable(i,j): return (not cmp[i,j]) and (not cmp[j,i]) for i,j,k in Permutations([0,1,2]): # transitivity of equivalence if incomparable(i,j) and incomparable(j,k) and not incomparable(i,k): raise ValueError(msg)
def _coeffs_from_height(self, height_tuple): """ Returns a list of tuples of a-invariants of all curves described by height_tuple. INPUT: - ``height_tuple`` -- A tuple of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. OUTPUT: - A list of 2-tuples, each consisting of the given height, followed by a tuple of a-invariants of a curve of that height. EXAMPLES: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: B = C.next_height(4); B (4, [1, 2], [1]) sage: L = C._coeffs_from_height(B) sage: for ell in L: print ell ...: (4, [0, 0, 0, -1, -2]) (4, [0, 0, 0, -1, 2]) (4, [0, 0, 0, 0, -2]) (4, [0, 0, 0, 0, 2]) (4, [0, 0, 0, 1, -2]) (4, [0, 0, 0, 1, 2]) """ height = height_tuple[0] coeffs = height_tuple[1] index = height_tuple[2] # Produce list of all coefficient tuples with given height L = [] for S in list(powerset(index))[1:]: B = [] for j in range(len(coeffs)): if j in S: B.append([-coeffs[j], coeffs[j]]) elif j in index: B.append(srange(-coeffs[j] + 1, coeffs[j])) else: B.append(srange(-coeffs[j], coeffs[j] + 1)) C = CartesianProduct(*B).list() for c in C: L.append(c) # Convert coefficient tuples to a-invariants L2 = [] for c in L: C = self._coeffs_to_a_invariants(c) if not self._is_singular(C): L2.append((height, C)) return L2
def _highest_weight_iter(self): r""" Iterate over the highest weight rigged configurations by moving through the :class:`KleberTree` and then setting appropriate values of the partitions. EXAMPLES:: sage: RC = RiggedConfigurations(['A', 2, 1], [[1, 1]]) # indirect doctest sage: len([x for x in RC]) 3 """ n = self._cartan_type.n for tree_node in self.kleber_tree: shapes = [] cur = tree_node path_lambda = [cur.up_root.to_vector()] # Build the lambda values # Note that these are not same lambda as in the paper, # but a less computational version. while cur.parent_node is not None: path_lambda.insert(0, (cur.parent_node.up_root - cur.up_root).to_vector()) cur = cur.parent_node for a in range(n): shapes.append([]) for i, cur_lambda in enumerate(path_lambda): for j in range(cur_lambda[a]): shapes[-1].insert(0, i) # Start with a base to calculate the vacancy numbers # Make a copy just to be safe base = self(partition_list=shapes[:]) # Build out the blocks for the partition values vac_nums = [] blocks = [] L = [] for partition in base: vac_nums.append(partition.vacancy_numbers) blocks.append([[]]) # If the partition is empty, there's nothing to do if len(partition) <= 0: L.append([[]]) continue # Setup the first block blockLen = partition[0] for i, rowLen in enumerate(partition): # If we've gone to a different sized block, then update the # values which change when moving to a new block size if blockLen != rowLen: blocks[-1].append([]) blockLen = rowLen blocks[-1][-1].append(partition.vacancy_numbers[i]) L2 = [] for block in blocks[-1]: L2.append(IterableFunctionCall(self._block_iterator, block)) L.append(CartesianProduct(*L2)) # TODO Find a more efficient method without appealing to the CartesianProduct C = CartesianProduct(*L) for curBlocks in C: yield self(KT_constructor=[ shapes[:], self._blocks_to_values(curBlocks[:]), vac_nums[:] ])
def __init__( self, space, projection=True, bounding_box=3, color=CartanType.color, labels=True, level=None, affine=None, ): r""" TESTS:: sage: L = RootSystem(['B',2,1]).weight_space() sage: options = L.plot_parse_options() sage: options.dimension 2 sage: options._projections [Weight space over the Rational Field of the Root system of type ['B', 2], <bound method WeightSpace_with_category._plot_projection of Weight space over the Rational Field of the Root system of type ['B', 2]>] sage: L = RootSystem(['B',2,1]).ambient_space() sage: options = L.plot_parse_options() sage: options.dimension 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], <bound method AmbientSpace_with_category._plot_projection of Ambient space of the Root system of type ['B', 2]>] sage: options = L.plot_parse_options(affine=True) sage: options.dimension 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], <bound method AmbientSpace_with_category._plot_projection of Ambient space of the Root system of type ['B', 2]>] sage: options = L.plot_parse_options(affine=False) sage: options._projections [<bound method AmbientSpace_with_category._plot_projection of Ambient space of the Root system of type ['B', 2, 1]>] sage: options.dimension 3 sage: options = L.plot_parse_options(affine=False, projection='barycentric') sage: options._projections [<bound method AmbientSpace_with_category._plot_projection_barycentric of Ambient space of the Root system of type ['B', 2, 1]>] sage: options.dimension 3 """ self.space = space self._color = color self.labels = labels # self.level = l != None: whether to intersect the alcove picture at level l # self.affine: whether to project at level l and then onto the classical space if affine is None: affine = space.cartan_type().is_affine() if affine: if level is None: level = 1 if not space.cartan_type().is_affine(): raise ValueError("affine option only valid for affine types") projections = [space.classical()] projection_space = space.classical() else: projections = [] projection_space = space self.affine = affine self.level = level if projection is True: projections.append(projection_space._plot_projection) elif projection == "barycentric": projections.append(projection_space._plot_projection_barycentric) elif projection is not False: # assert projection is a callable projections.append(projection) self._projections = projections self.origin_projected = self.projection(space.zero()) self.dimension = len(self.origin_projected) # Bounding box from sage.rings.real_mpfr import RR from sage.geometry.polyhedron.all import Polyhedron from sage.combinat.cartesian_product import CartesianProduct if bounding_box in RR: bounding_box = [[-bounding_box, bounding_box]] * self.dimension else: if not len(bounding_box) == self.dimension: raise TypeError( "bounding_box argument doesn't match with the plot dimension" ) elif not all(len(b) == 2 for b in bounding_box): raise TypeError("Invalid bounding box %s" % bounding_box) self.bounding_box = Polyhedron(vertices=CartesianProduct( *bounding_box))
def _subpoly_parallel_facets(self): """ Generator for all lattice sub-polyhedra with parallel facets. In a sub-polyhedron `Y\subset X` not all edges of `Y` need to be parallel to `X`. This method iterates over all sub-polyhedra where they are parallel, up to an overall translation of the sub-polyhedron. Degenerate sub-polyhedra of dimension strictly smaller are included. OUTPUT: A generator yielding `\ZZ`-polyhedra. By construction, each facet of the returned polyhedron is parallel to one of the facets of ``self``. EXAMPLES:: sage: X = Polyhedron(vertices=[(0,0), (0,1), (1,0), (1,1)]) sage: X._subpoly_parallel_facets() <generator object _subpoly_parallel_facets at 0x...> sage: for p in X._subpoly_parallel_facets(): ... print p.Vrepresentation() (A vertex at (0, 0),) (A vertex at (0, -1), A vertex at (0, 0)) (A vertex at (-1, 0), A vertex at (0, 0)) (A vertex at (-1, -1), A vertex at (-1, 0), A vertex at (0, -1), A vertex at (0, 0)) TESTS:: sage: X = Polyhedron(vertices=[(0,), (3,)]) sage: [ p.vertices() for p in X._subpoly_parallel_facets() ] [(A vertex at (0),), (A vertex at (-1), A vertex at (0)), (A vertex at (-2), A vertex at (0)), (A vertex at (-3), A vertex at (0))] sage: list( Polyhedron(vertices=[[0,0]])._subpoly_parallel_facets() ) [A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex] sage: list( Polyhedron()._subpoly_parallel_facets() ) [The empty polyhedron in ZZ^0] """ if self.dim()>2 or not self.is_compact(): raise NotImplementedError('only implemented for bounded polygons') from sage.geometry.polyhedron.plot import cyclic_sort_vertices_2d vertices = cyclic_sort_vertices_2d(self.vertices()) n = len(vertices) if n==1: # single point yield self return edge_vectors = [] for i in range(0,n): v = vertices[(i+1) % n].vector() - vertices[i].vector() d = gcd(list(v)) v_prim = (v/d).change_ring(ZZ) edge_vectors.append([ v_prim*i for i in range(d+1) ]) origin = self.ambient_space().zero() parent = self.parent() from sage.combinat.cartesian_product import CartesianProduct for edges in CartesianProduct(*edge_vectors): v = [] point = origin for e in edges: point += e v.append(point) if point!=origin: # does not close up, not a subpolygon continue yield parent([v, [], []], None)