Example #1
0
    def __init__(self, s):
        """
        TESTS::

            sage: s = Subsets(Set([1]))
            sage: e = s.first()
            sage: isinstance(e, s.element_class)
            True

        In the following "_test_elements" is temporarily disabled
        until :class:`sage.sets.set.Set_object_enumerated` objects
        pass the category tests::

            sage: S = Subsets([1,2,3])
            sage: TestSuite(S).run(skip=["_test_elements"])

            sage: S = sage.sets.set.Set_object_enumerated([1,2])
            sage: TestSuite(S).run()         # todo: not implemented
        """
        Parent.__init__(self, category=EnumeratedSets().Finite())
        if s not in EnumeratedSets():
            from sage.misc.misc import uniq
            from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
            s = list(s)
            us = uniq(s)
            if len(us) == len(s):
                s = FiniteEnumeratedSet(s)
            else:
                s = FiniteEnumeratedSet(us)
        self._s = s
Example #2
0
    def __init__(self, s):
        """
        TESTS::

            sage: s = Subsets(Set([1]))
            sage: e = s.first()
            sage: isinstance(e, s.element_class)
            True

        In the following "_test_elements" is temporarily disabled
        until :class:`sage.sets.set.Set_object_enumerated` objects
        pass the category tests::

            sage: S = Subsets([1,2,3])
            sage: TestSuite(S).run(skip=["_test_elements"])

            sage: S = sage.sets.set.Set_object_enumerated([1,2])
            sage: TestSuite(S).run()         # todo: not implemented
        """
        Parent.__init__(self, category=EnumeratedSets().Finite())
        if s not in EnumeratedSets():
            from sage.misc.misc import uniq
            from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
            s = list(s)
            us = uniq(s)
            if len(us) == len(s):
                s = FiniteEnumeratedSet(s)
            else:
                s = FiniteEnumeratedSet(us)
        self._s  = s
Example #3
0
def _check_polynomials_P3(quadratic1, quadratic2, variables):
    """
    Check that the polynomial is weighted homogeneous in standard variables.

    INPUT:

    - ``quadratic1``, ``quadratic2`` -- two quadratic polynomials in 4
      homogeneous or 3 inhomogeneous variables.

    - ``variables`` -- the variables or ``None`` (default).

    OUTPUT:

    This function returns ``variables``, potentially guessed from the
    polynomial ring. A ``ValueError`` is raised if the polynomial is
    not homogeneous.

    EXAMPLES:

        sage: from sage.schemes.toric.weierstrass_higher import _check_polynomials_P3
        sage: R.<w,x,y,z> = QQ[]
        sage: quadratic = w^2+x^2+y^2+z^2
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,z])
        (w, x, y, z)
        sage: _check_polynomials_P3(w^2, quadratic, None)
        (w, x, y, z)
        sage: _check_polynomials_P3(z^2, quadratic.subs(w=0), None)
        (x, y, z, None)
        sage: R.<w,x,y,z,t> = QQ[]
        sage: quadratic = w^2+x^2+y^2+z^2 + t*(x*y+y*z+z*w+w*x)
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,z])
        (w, x, y, z)
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,t])
        Traceback (most recent call last):
        ...
        ValueError: The polynomial is not homogeneous with weights (1, 1, 1, 1)
    """
    if quadratic1.parent() is not quadratic2.parent():
        raise ValueError(
            'The two quadratics must be in the same polynomial ring.')
    if variables is None:
        from sage.misc.misc import uniq
        variables = uniq(quadratic1.variables() + quadratic2.variables())
        variables.reverse()
    if len(variables) == 4:
        w, x, y, z = variables
        _check_homogeneity(quadratic1, [w, x, y, z], (1, 1, 1, 1), 2)
        _check_homogeneity(quadratic2, [w, x, y, z], (1, 1, 1, 1), 2)
    elif len(variables) == 3:
        w, x, y = variables
        z = None
    else:
        raise ValueError('Need three or four variables, got ' + str(variables))
    return (w, x, y, z)
Example #4
0
def _check_polynomials_P3(quadratic1, quadratic2, variables):
    """
    Check that the polynomial is weighted homogeneous in standard variables.

    INPUT:

    - ``quadratic1``, ``quadratic2`` -- two quadratic polynomials in 4
      homogeneous or 3 inhomogeneous variables.

    - ``variables`` -- the variables or ``None`` (default).

    OUTPUT:

    This function returns ``variables``, potentially guessed from the
    polynomial ring. A ``ValueError`` is raised if the polynomial is
    not homogeneous.

    EXAMPLES:

        sage: from sage.schemes.toric.weierstrass_higher import _check_polynomials_P3
        sage: R.<w,x,y,z> = QQ[]
        sage: quadratic = w^2+x^2+y^2+z^2
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,z])
        (w, x, y, z)
        sage: _check_polynomials_P3(w^2, quadratic, None)
        (w, x, y, z)
        sage: _check_polynomials_P3(z^2, quadratic.subs(w=0), None)
        (x, y, z, None)
        sage: R.<w,x,y,z,t> = QQ[]
        sage: quadratic = w^2+x^2+y^2+z^2 + t*(x*y+y*z+z*w+w*x)
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,z])
        (w, x, y, z)
        sage: _check_polynomials_P3(w^2, quadratic, [w,x,y,t])
        Traceback (most recent call last):
        ...
        ValueError: The polynomial is not homogeneous with weights (1, 1, 1, 1)
    """
    if quadratic1.parent() is not quadratic2.parent():
        raise ValueError('The two quadratics must be in the same polynomial ring.')
    if variables is None:
        from sage.misc.misc import uniq
        variables = uniq(quadratic1.variables() + quadratic2.variables())
        variables.reverse()
    if len(variables) == 4:
        w, x, y, z = variables
        _check_homogeneity(quadratic1, [w, x, y, z], (1, 1, 1, 1), 2)
        _check_homogeneity(quadratic2, [w, x, y, z], (1, 1, 1, 1), 2)
    elif len(variables) == 3:
        w, x, y = variables
        z = None
    else:
        raise ValueError('Need three or four variables, got '+str(variables))
    return (w, x, y, z)
Example #5
0
    def automorphism_group(self):
        """
        EXAMPLES::
        
            sage: p = PermutationGroupElement((2,3))
            sage: S = species.SetSpecies()
            sage: F = S * S
            sage: a = F.structures([1,2,3,4]).random_element(); a
            {1}*{2, 3, 4}
            sage: a.automorphism_group()
            Permutation Group with generators [(2,3), (2,3,4)]
        
        ::
        
            sage: [a.transport(g) for g in a.automorphism_group()]
            [{1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4}]
        
        ::
        
            sage: a = F.structures([1,2,3,4]).random_element(); a
            {2, 3}*{1, 4}
            sage: [a.transport(g) for g in a.automorphism_group()]
            [{2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}]
        """
        from sage.groups.all import PermutationGroupElement, PermutationGroup, SymmetricGroup
        from sage.misc.misc import uniq
        from sage.combinat.species.misc import change_support

        left, right = self._list
        n = len(self._labels)

        #Get the supports for each of the sides
        l_support = self._subset._list
        r_support = self._subset.complement()._list

        #Get the automorphism group for the left object and
        #make it have the correct support. Do the same to the
        #right side.
        l_aut = change_support(left.automorphism_group(), l_support)
        r_aut = change_support(right.automorphism_group(), r_support)

        identity = PermutationGroupElement([])

        gens = l_aut.gens() + r_aut.gens()
        gens = [g for g in gens if g != identity]
        gens = uniq(gens) if len(gens) > 0 else [[]]
        return PermutationGroup(gens)
Example #6
0
    def automorphism_group(self):
        """
        EXAMPLES::
        
            sage: p = PermutationGroupElement((2,3))
            sage: S = species.SetSpecies()
            sage: F = S * S
            sage: a = F.structures([1,2,3,4]).random_element(); a
            {1}*{2, 3, 4}
            sage: a.automorphism_group()
            Permutation Group with generators [(2,3), (2,3,4)]
        
        ::
        
            sage: [a.transport(g) for g in a.automorphism_group()]
            [{1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4},
             {1}*{2, 3, 4}]
        
        ::
        
            sage: a = F.structures([1,2,3,4]).random_element(); a
            {2, 3}*{1, 4}
            sage: [a.transport(g) for g in a.automorphism_group()]
            [{2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}]
        """
        from sage.groups.all import PermutationGroupElement, PermutationGroup, SymmetricGroup
        from sage.misc.misc import uniq
        from sage.combinat.species.misc import change_support
        
        left, right = self._list
        n = len(self._labels)
        
        #Get the supports for each of the sides
        l_support = self._subset._list
        r_support = self._subset.complement()._list

        #Get the automorphism group for the left object and
        #make it have the correct support. Do the same to the
        #right side.
        l_aut = change_support(left.automorphism_group(), l_support)
        r_aut = change_support(right.automorphism_group(), r_support)

        identity = PermutationGroupElement([])

        gens = l_aut.gens() + r_aut.gens()
        gens = [g for g in gens if g != identity]
        gens = uniq(gens) if len(gens) > 0 else [[]]
        return PermutationGroup(gens)
Example #7
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: Combinations(['a','a','b'],2).list() # indirect doctest
            [['a', 'a'], ['a', 'b']]
        """
        items = map(self.mset.index, self.mset)
        indices = uniq(sorted(items))
        counts = [0] * len(indices)
        for i in items:
            counts[indices.index(i)] += 1
        for iv in IntegerVectors(self.k, len(indices), outer=counts):
            yield sum([[self.mset[indices[i]]]*iv[i] for i in range(len(indices))],[])
Example #8
0
    def to_chain(self):
        """
        Returns the chain of partitions corresponding to the (semi)standard
        skew tableau.

        EXAMPLES::

            sage: SkewTableau([[None,1],[2],[3]]).to_chain()
            [[1], [2], [2, 1], [2, 1, 1]]
            sage: SkewTableau([[None,1],[1],[2]]).to_chain()
            [[1], [2, 1], [2, 1, 1]]
        """
        weights = [0] + uniq(sorted(self.to_word()))
        return [self.restrict(x).shape()[0] for x in weights]
Example #9
0
    def to_chain(self):
        """
        Returns the chain of partitions corresponding to the (semi)standard
        skew tableau.

        EXAMPLES::

            sage: SkewTableau([[None,1],[2],[3]]).to_chain()
            [[1], [2], [2, 1], [2, 1, 1]]
            sage: SkewTableau([[None,1],[1],[2]]).to_chain()
            [[1], [2, 1], [2, 1, 1]]
        """
        weights = [0] + uniq(sorted(self.to_word()))
        return [ self.restrict(x).shape()[0] for x in weights]
Example #10
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: Combinations(['a','a','b'],2).list() # indirect doctest
            [['a', 'a'], ['a', 'b']]
        """
        items = map(self.mset.index, self.mset)
        indices = uniq(sorted(items))
        counts = [0] * len(indices)
        for i in items:
            counts[indices.index(i)] += 1
        for iv in IntegerVectors(self.k, len(indices), outer=counts):
            yield sum([[self.mset[indices[i]]] * iv[i]
                       for i in range(len(indices))], [])
Example #11
0
    def __contains__(self, x):
        """
        EXAMPLES::

            sage: c = Combinations(range(4))
            sage: all( i in c for i in c )
            True
            sage: [3,4] in c
            False
            sage: [0,0] in c
            False
        """
        try:
            x = list(x)
        except TypeError:
            return False

        return all(i in self.mset for i in x) and len(uniq(x)) == len(x)
Example #12
0
    def __contains__(self, x):
        """
        EXAMPLES::

            sage: c = Combinations(range(4))
            sage: all( i in c for i in c )
            True
            sage: [3,4] in c
            False
            sage: [0,0] in c
            False
        """
        try:
            x = list(x)
        except TypeError:
            return False

        return all(i in self.mset for i in x) and len(uniq(x)) == len(x)
Example #13
0
 def order_filter(self, elements):
     """
     Returns the order filter generated by a list of elements.
     
     `I` is an order filter if, for any `x` in `I` and `y` such that
     `y \ge x`, then `y` is in `I`.
     
     EXAMPLES::
     
         sage: H = Posets.BooleanLattice(4)._hasse_diagram
         sage: H.order_filter([3,8])
         [3, 7, 8, 9, 10, 11, 12, 13, 14, 15]
     """
     of = []
     for i in elements:
         for j in self.breadth_first_search(i):
             of.append(j)
     return uniq(of)
Example #14
0
 def order_filter(self,elements):
     """
     Returns the order filter generated by a list of elements.
     
     `I` is an order filter if, for any `x` in `I` and `y` such that
     `y \ge x`, then `y` is in `I`.
     
     EXAMPLES::
     
         sage: H = Posets.BooleanLattice(4)._hasse_diagram
         sage: H.order_filter([3,8])
         [3, 7, 8, 9, 10, 11, 12, 13, 14, 15]
     """
     of = []
     for i in elements:
         for j in self.breadth_first_search(i):
             of.append(j)
     return uniq(of)
Example #15
0
    def order_ideal(self,elements):
        """
        Returns the order ideal generated by a list of elements.

        `I` is an order ideal if, for any `x` in `I` and `y` such that
        `y \le x`, then `y` is in `I`.

        EXAMPLES::

            sage: H = Posets.BooleanLattice(4)._hasse_diagram
            sage: H.order_ideal([7,10])
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 10]
        """
        H = copy(self).reverse()
        oi = []
        for i in elements:
            for j in H.breadth_first_search(i):
                oi.append(j)
        return uniq(oi)
Example #16
0
    def __contains__(self, x):
        """
        EXAMPLES::

            sage: from sage.combinat.choose_nk import ChooseNK
            sage: c52 = ChooseNK(5,2)
            sage: [0,1] in c52
            True
            sage: [1,1] in c52
            False
            sage: [0,1,3] in c52
            False
        """
        try:
            x = list(x)
        except TypeError:
            return False

        r = range(len(x))
        return all(i in r for i in x) and len(uniq(x)) == self._k
Example #17
0
    def __contains__(self, x):
        """
        EXAMPLES::

            sage: from sage.combinat.choose_nk import ChooseNK
            sage: c52 = ChooseNK(5,2)
            sage: [0,1] in c52
            True
            sage: [1,1] in c52
            False
            sage: [0,1,3] in c52
            False
        """
        try:
            x = list(x)
        except TypeError:
            return False

        r = range(len(x))
        return all(i in r for i in x) and len(uniq(x)) == self._k
Example #18
0
    def __init__(self, alphabet):
        """
        Builds an ordered alphabet from an iterable. The order is that
        given by the order the items appear in the iterable. There must be
        no duplicates.

        NOTE:
            The alphabet is expanded in memory and stored as a list.

        EXAMPLES::

            sage: from sage.combinat.words.alphabet import OrderedAlphabet_Finite
            sage: A = OrderedAlphabet_Finite([0,1,2])
            sage: A == loads(dumps(A))
            True
            sage: A = OrderedAlphabet_Finite("abc")
            sage: A == loads(dumps(A))
            True

        TESTS::

            sage: from sage.combinat.words.alphabet import OrderedAlphabet_Finite
            sage: OrderedAlphabet_Finite('aba')
            Traceback (most recent call last):
            ...
            ValueError: duplicate elements in alphabet
            sage: OrderedAlphabet_Finite(33)
            Traceback (most recent call last):
            ...
            TypeError: cannot build an alphabet from 33
        """
        try:
            self._alphabet = list(alphabet)
        except TypeError:
            raise TypeError, "cannot build an alphabet from %s" % (alphabet)
        if len(uniq(self._alphabet)) != len(self._alphabet):
            raise ValueError, "duplicate elements in alphabet"
Example #19
0
    def __init__(self, alphabet):
        """
        Builds an ordered alphabet from an iterable. The order is that
        given by the order the items appear in the iterable. There must be
        no duplicates.

        NOTE:
            The alphabet is expanded in memory and stored as a list.

        EXAMPLES::

            sage: from sage.combinat.words.alphabet import OrderedAlphabet_Finite
            sage: A = OrderedAlphabet_Finite([0,1,2])
            sage: A == loads(dumps(A))
            True
            sage: A = OrderedAlphabet_Finite("abc")
            sage: A == loads(dumps(A))
            True

        TESTS::

            sage: from sage.combinat.words.alphabet import OrderedAlphabet_Finite
            sage: OrderedAlphabet_Finite('aba')
            Traceback (most recent call last):
            ...
            ValueError: duplicate elements in alphabet
            sage: OrderedAlphabet_Finite(33)
            Traceback (most recent call last):
            ...
            TypeError: cannot build an alphabet from 33
        """
        try:
            self._alphabet = list(alphabet)
        except TypeError:
            raise TypeError, "cannot build an alphabet from %s" % (alphabet)
        if len(uniq(self._alphabet)) != len(self._alphabet):
            raise ValueError, "duplicate elements in alphabet"
    def set_value_from_cells(self, obj_class=None, cells={}):
        r"""We have an object value, but we want to change it according to cells
        Yet we want to keep the same class (or warn if that's impossible)

        INPUT:

            -  ``obj_class`` -- an object class (by default: self.value.__class__)
            -  ``cells`` -- a dictionary (i,j)->val
        """
        if not obj_class and self.value:
            obj_class = self.value.__class__
        if not obj_class:
            return
        if hasattr(self.adapter, 'from_cells'):
            try:
                obj = self.adapter.from_cells(cells)
            except:
                raise ValueError(
                    "Could not make an object of class '%s' from given cells" %
                    str(obj_class))
        elif hasattr(obj_class, 'cells') or hasattr(
                obj_class, 'rows'):  # e.g. a tableau / matrix / vector
            positions = sorted(list(cells.keys()))
            for cl in obj_class.__mro__:
                try:
                    obj = cl([[cells[pos] for pos in positions if pos[0] == i]
                              for i in uniq([t[0] for t in positions])])
                except:
                    print("These cells cannot be turned into a %s" % cl)
        else:
            raise TypeError(
                "Unable to cast the given cells into a grid-like object.")
        if not self.validate(obj, None, obj_class):
            raise ValueError(
                "Could not make a compatible ('%s')  object from given cells" %
                str(obj_class))
        self.set_value(obj, False)
Example #21
0
 def draw(self,
          cell_widget_classes=None,
          cell_widget_class_index=None,
          addable_widget_class=None,
          blank_widget_class=None):
     r"""
     Add children to the GridWidget:
     - Sage object/grid editor cells
     - Blank cells for empty cells in a row
     - Addable cells if any
     Used classes can be passed as arguments
     to enable changing shapes, colors ..
     """
     self.initialization = True  # Prevent any interactivity while drawing the widget
     self.reset_links()
     self.compute_height()
     positions = sorted(list(self.cells.keys()))
     rows = [[(pos, self.cells[pos]) for pos in positions if pos[0]==i] \
             for i in range(self.height)]
     vbox_children = []
     addable_positions = self.addable_cells()
     addable_rows = []
     removable_positions = self.removable_cells()
     addable_rows = [(i,[pos for pos in addable_positions if pos[0]==i]) \
                     for i in uniq([t[0] for t in addable_positions])]
     if not cell_widget_classes:
         cell_widget_classes = self.cell_widget_classes
     if not cell_widget_class_index:
         cell_widget_class_index = self.cell_widget_class_index
     if not addable_widget_class:
         addable_widget_class = self.addable_widget_class
     if not blank_widget_class:
         blank_widget_class = self.blank_widget_class
     for i in range(self.height):
         r = rows[i]
         if not r:  # Empty row
             if (i, 0) in addable_positions:
                 vbox_children.append(
                     HBox((addable_widget_class(
                         (i, 0), layout=self.cell_layout), )))
             else:
                 vbox_children.append(
                     HBox((blank_widget_class(layout=self.cell_layout,
                                              disabled=True), )))
             continue
         j = 0
         hbox_children = []
         while j <= max([t[0][1] for t in rows[i]]):
             if (i, j) in positions:
                 cell_content = self.cells[(i, j)]
                 cell_widget_class = cell_widget_classes[
                     cell_widget_class_index((i, j))]
                 cell_display = self.adapter.cell_to_display(
                     cell_content, self.displaytype)
                 cell = cell_widget_class(cell_display, (i, j),
                                          layout=self.cell_layout,
                                          placeholder=cell_display)
                 if (i, j) in removable_positions:
                     if issubclass(cell_widget_class, ToggleButton):
                         cell.description = '-'
                         cell.disabled = False
                     else:
                         cell.add_class('removablecell')
                 hbox_children.append(cell)
             elif (i, j) in addable_positions:
                 # Inside the grid-represented object limits
                 hbox_children.append(
                     addable_widget_class((i, j), layout=self.cell_layout))
             else:
                 hbox_children.append(
                     blank_widget_class(layout=self.cell_layout))
             j += 1
             if j > max([t[0][1]
                         for t in rows[i]]) and (i, j) in addable_positions:
                 # Outside of the grid-represented object limits
                 hbox_children.append(
                     self.addable_widget_class((i, j),
                                               layout=self.cell_layout))
         vbox_children.append(HBox(hbox_children))
     for row in addable_rows:
         if row[0] > i:
             vbox_children.append(
                 HBox([
                     self.addable_widget_class((i, j),
                                               layout=self.cell_layout)
                     for c in row[1]
                 ]))
     if self.display_convention == 'fr':
         vbox_children.reverse()
     self.children = vbox_children
     self.add_links()
     self.initialization = False
Example #22
0
    def __init__(self, matrices, C, D, check=True):
        """
        Create a morphism from a dictionary of matrices.

        EXAMPLES::

            from sage.matrix.constructor import zero_matrix
            sage: S = simplicial_complexes.Sphere(1)
            sage: S
            Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
            sage: C = S.chain_complex()
            sage: C.differential()
            {0: [], 1: [ 1  1  0]
            [ 0 -1 -1]
            [-1  0  1], 2: []}
            sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
            sage: G = Hom(C,C)
            sage: x = G(f)
            sage: x
            Chain complex morphism from Chain complex with at most 2 nonzero terms
            over Integer Ring to Chain complex with at most 2 nonzero terms over 
            Integer Ring
            sage: x._matrix_dictionary
            {0: [0 0 0]
            [0 0 0]
            [0 0 0], 1: [0 0 0]
            [0 0 0]
            [0 0 0]}

        Check that the bug in :trac:`13220` has been fixed::

            sage: X = simplicial_complexes.Simplex(1)
            sage: Y = simplicial_complexes.Simplex(0)
            sage: g = Hom(X,Y)({0:0, 1:0})
            sage: g.associated_chain_complex_morphism()
            Chain complex morphism from Chain complex with at most 2 nonzero 
            terms over Integer Ring to Chain complex with at most 1 nonzero terms 
            over Integer Ring
        """
        if not C.base_ring() == D.base_ring():
            raise NotImplementedError('morphisms between chain complexes of different'
                                      ' base rings are not implemented')
        d = C.degree_of_differential()
        if d != D.degree_of_differential():
            raise ValueError('degree of differential does not match')
            
        from sage.misc.misc import uniq
        degrees = uniq(C.differential().keys() + D.differential().keys())
        initial_matrices = dict(matrices)
        matrices = dict()
        for i in degrees:
            if i - d not in degrees:
                if not (C.free_module_rank(i) == D.free_module_rank(i) == 0):
                    raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i))
                continue
            try:
                matrices[i] = initial_matrices.pop(i)
            except KeyError:
                matrices[i] = matrix.zero_matrix(C.base_ring(),
                                                 D.differential(i).ncols(),
                                                 C.differential(i).ncols(), sparse=True)
        if check:
            # all remaining matrices given must be 0x0
            if not all(m.ncols() == m.nrows() == 0 for m in initial_matrices.values()):
                raise ValueError('the remaining matrices are not empty')
            # check commutativity
            for i in degrees:
                if i - d not in degrees:
                    if not (C.free_module_rank(i) == D.free_module_rank(i) == 0):
                        raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i))
                    continue
                if i + d not in degrees:
                    if not (C.free_module_rank(i+d) == D.free_module_rank(i+d) == 0):
                        raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i+d))
                    continue
                Dm = D.differential(i) * matrices[i]
                mC = matrices[i+d] * C.differential(i)
                if mC != Dm:
                    raise ValueError('matrices must define a chain complex morphism')
        self._matrix_dictionary = matrices
        self._domain = C
        self._codomain = D
    def __init__(self, matrices, C, D, check=True):
        """
        Create a morphism from a dictionary of matrices.

        EXAMPLES::

            sage: S = simplicial_complexes.Sphere(1)
            sage: S
            Minimal triangulation of the 1-sphere
            sage: C = S.chain_complex()
            sage: C.differential()
            {0: [], 1: [-1 -1  0]
             [ 1  0 -1]
             [ 0  1  1], 2: []}
            sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
            sage: G = Hom(C,C)
            sage: x = G(f)
            sage: x
            Chain complex endomorphism of Chain complex with at most 2 nonzero terms over Integer Ring
            sage: x._matrix_dictionary
            {0: [0 0 0]
            [0 0 0]
            [0 0 0], 1: [0 0 0]
            [0 0 0]
            [0 0 0]}

        Check that the bug in :trac:`13220` has been fixed::

            sage: X = simplicial_complexes.Simplex(1)
            sage: Y = simplicial_complexes.Simplex(0)
            sage: g = Hom(X,Y)({0:0, 1:0})
            sage: g.associated_chain_complex_morphism()
            Chain complex morphism:
              From: Chain complex with at most 2 nonzero terms over Integer Ring
              To: Chain complex with at most 1 nonzero terms over Integer Ring

        Check that an error is raised if the matrices are the wrong size::

            sage: C = ChainComplex({0: zero_matrix(ZZ, 0, 1)})
            sage: D = ChainComplex({0: zero_matrix(ZZ, 0, 2)})
            sage: Hom(C,D)({0: matrix(1, 2, [1, 1])})  # 1x2 is the wrong size.
            Traceback (most recent call last):
            ...
            ValueError: matrix in degree 0 is not the right size
            sage: Hom(C,D)({0: matrix(2, 1, [1, 1])})  # 2x1 is right.
            Chain complex morphism:
              From: Chain complex with at most 1 nonzero terms over Integer Ring
              To: Chain complex with at most 1 nonzero terms over Integer Ring
        """
        if not C.base_ring() == D.base_ring():
            raise NotImplementedError('morphisms between chain complexes of different'
                                      ' base rings are not implemented')
        d = C.degree_of_differential()
        if d != D.degree_of_differential():
            raise ValueError('degree of differential does not match')
            
        from sage.misc.misc import uniq
        degrees = uniq(list(C.differential()) + list(D.differential()))
        initial_matrices = dict(matrices)
        matrices = dict()
        for i in degrees:
            if i - d not in degrees:
                if not (C.free_module_rank(i) == D.free_module_rank(i) == 0):
                    raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i))
                continue
            try:
                matrices[i] = initial_matrices.pop(i)
            except KeyError:
                matrices[i] = zero_matrix(C.base_ring(),
                                          D.differential(i).ncols(),
                                          C.differential(i).ncols(), sparse=True)
        if check:
            # All remaining matrices given must be 0x0.
            if not all(m.ncols() == m.nrows() == 0 for m in initial_matrices.values()):
                raise ValueError('the remaining matrices are not empty')
            # Check sizes of matrices.
            for i in matrices:
                if (matrices[i].nrows() != D.free_module_rank(i) or
                    matrices[i].ncols() != C.free_module_rank(i)):
                    raise ValueError('matrix in degree {} is not the right size'.format(i))
            # Check commutativity.
            for i in degrees:
                if i - d not in degrees:
                    if not (C.free_module_rank(i) == D.free_module_rank(i) == 0):
                        raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i))
                    continue
                if i + d not in degrees:
                    if not (C.free_module_rank(i+d) == D.free_module_rank(i+d) == 0):
                        raise ValueError('{} and {} are not rank 0 in degree {}'.format(C, D, i+d))
                    continue
                Dm = D.differential(i) * matrices[i]
                mC = matrices[i+d] * C.differential(i)
                if mC != Dm:
                    raise ValueError('matrices must define a chain complex morphism')
        self._matrix_dictionary = {}
        for i in matrices:
            m = matrices[i]
            # Use immutable matrices because they're hashable.
            m.set_immutable()
            self._matrix_dictionary[i] = m
        Morphism.__init__(self, Hom(C,D, ChainComplexes(C.base_ring())))
Example #24
0
    def __init__(self, matrices, C, D, check=True):
        """
        Create a morphism from a dictionary of matrices.

        EXAMPLES::

            sage: S = simplicial_complexes.Sphere(1)
            sage: S
            Minimal triangulation of the 1-sphere
            sage: C = S.chain_complex()
            sage: C.differential()
            {0: [], 1: [ 1  1  0]
            [ 0 -1 -1]
            [-1  0  1], 2: []}
            sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
            sage: G = Hom(C,C)
            sage: x = G(f)
            sage: x
            Chain complex endomorphism of Chain complex with at most 2 nonzero terms over Integer Ring
            sage: x._matrix_dictionary
            {0: [0 0 0]
            [0 0 0]
            [0 0 0], 1: [0 0 0]
            [0 0 0]
            [0 0 0]}

        Check that the bug in :trac:`13220` has been fixed::

            sage: X = simplicial_complexes.Simplex(1)
            sage: Y = simplicial_complexes.Simplex(0)
            sage: g = Hom(X,Y)({0:0, 1:0})
            sage: g.associated_chain_complex_morphism()
            Chain complex morphism:
              From: Chain complex with at most 2 nonzero terms over Integer Ring
              To: Chain complex with at most 1 nonzero terms over Integer Ring

        Check that an error is raised if the matrices are the wrong size::

            sage: C = ChainComplex({0: zero_matrix(ZZ, 0, 1)})
            sage: D = ChainComplex({0: zero_matrix(ZZ, 0, 2)})
            sage: Hom(C,D)({0: matrix(1, 2, [1, 1])})  # 1x2 is the wrong size.
            Traceback (most recent call last):
            ...
            ValueError: matrix in degree 0 is not the right size
            sage: Hom(C,D)({0: matrix(2, 1, [1, 1])})  # 2x1 is right.
            Chain complex morphism:
              From: Chain complex with at most 1 nonzero terms over Integer Ring
              To: Chain complex with at most 1 nonzero terms over Integer Ring
        """
        if not C.base_ring() == D.base_ring():
            raise NotImplementedError(
                'morphisms between chain complexes of different'
                ' base rings are not implemented')
        d = C.degree_of_differential()
        if d != D.degree_of_differential():
            raise ValueError('degree of differential does not match')

        from sage.misc.misc import uniq
        degrees = uniq(C.differential().keys() + D.differential().keys())
        initial_matrices = dict(matrices)
        matrices = dict()
        for i in degrees:
            if i - d not in degrees:
                if not (C.free_module_rank(i) == D.free_module_rank(i) == 0):
                    raise ValueError(
                        '{} and {} are not rank 0 in degree {}'.format(
                            C, D, i))
                continue
            try:
                matrices[i] = initial_matrices.pop(i)
            except KeyError:
                matrices[i] = zero_matrix(C.base_ring(),
                                          D.differential(i).ncols(),
                                          C.differential(i).ncols(),
                                          sparse=True)
        if check:
            # All remaining matrices given must be 0x0.
            if not all(m.ncols() == m.nrows() == 0
                       for m in initial_matrices.values()):
                raise ValueError('the remaining matrices are not empty')
            # Check sizes of matrices.
            for i in matrices:
                if (matrices[i].nrows() != D.free_module_rank(i)
                        or matrices[i].ncols() != C.free_module_rank(i)):
                    raise ValueError(
                        'matrix in degree {} is not the right size'.format(i))
            # Check commutativity.
            for i in degrees:
                if i - d not in degrees:
                    if not (C.free_module_rank(i) == D.free_module_rank(i) ==
                            0):
                        raise ValueError(
                            '{} and {} are not rank 0 in degree {}'.format(
                                C, D, i))
                    continue
                if i + d not in degrees:
                    if not (C.free_module_rank(i + d) ==
                            D.free_module_rank(i + d) == 0):
                        raise ValueError(
                            '{} and {} are not rank 0 in degree {}'.format(
                                C, D, i + d))
                    continue
                Dm = D.differential(i) * matrices[i]
                mC = matrices[i + d] * C.differential(i)
                if mC != Dm:
                    raise ValueError(
                        'matrices must define a chain complex morphism')
        self._matrix_dictionary = {}
        for i in matrices:
            m = matrices[i]
            # Use immutable matrices because they're hashable.
            m.set_immutable()
            self._matrix_dictionary[i] = m
        Morphism.__init__(self, Hom(C, D, ChainComplexes(C.base_ring())))
Example #25
0
    def __add__(self, Nelt):
        r"""
        Concatenate two ascii art object.

        By default, when two object are concatenated, the new one will be
        splittable between both.

        If the baseline is defined, the concatenation is computed such that the
        new baseline coincidate with the olders.

        For example, let `T` be a tree with it's baseline ascii art
        representation in the middle::

            o
             \
              o
             / \
            o   o

        and let `M` be a matrix with it's baseline ascii art representation at
        the middle two::

            [1 2 3]
            [4 5 6]
            [7 8 9]

        then the concatenation of both will give::

            o
             \   [1 2 3]
              o  [4 5 6]
             / \ [7 8 9]
            o   o

        If one of the objects has not baseline, the concatenation is realized
        from the top::

            o    [1 2 3]
             \   [4 5 6]
              o  [7 8 9]
             / \
            o   o

        TESTS::

            sage: from sage.typeset.ascii_art import AsciiArt
            sage: l5 = AsciiArt(lines=['|' for _ in range(5)], baseline=2); l5
            |
            |
            |
            |
            |
            sage: l3 = AsciiArt(lines=['|' for _ in range(3)], baseline=1); l3
            |
            |
            |
            sage: l3 + l5
             |
            ||
            ||
            ||
             |
            sage: l5 + l3
            |
            ||
            ||
            ||
            |
            sage: l5._baseline = 0
            sage: l5 + l3
            |
            |
            |
            ||
            ||
             |
            sage: l5._baseline = 4
            sage: l5 + l3
             |
            ||
            ||
            |
            |
            |
            sage: l3._baseline = 0
            sage: l3 + l5
            |
            |
            ||
             |
             |
             |
             |
        """
        new_matrix = []
        new_h = self.__class__._compute_new_h(self, Nelt)
        new_baseline = self.__class__._compute_new_baseline(self, Nelt)

        if self._baseline is not None and Nelt._baseline is not None:
            # left treatement
            for line in self._matrix:
                new_matrix.append(line + " " * (self._l - len(line)))

            if new_h > self._h:
                # |                 new_h > self._h
                # |                 new_baseline > self._baseline
                # ||<-- baseline    number of white lines at the bottom
                #  | }               :: Nelt._baseline - self._baseline
                #  | }
                if new_baseline > self._baseline:
                    for k in range(new_baseline - self._baseline):
                        new_matrix.append(" " * self._l)
                #  | }              new_h > self._h
                #  | }              new_h - new_baseline > self._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - self._h + self._baseline
                # ||
                #  |
                #  |
                if new_h - new_baseline > self._h - self._baseline:
                    for _ in range((new_h - new_baseline) - (self._h - self._baseline)):
                        new_matrix.insert(0, " " * self._l)

            # right treatement
            i = 0
            if new_h > Nelt._h:
                # |  }              new_h > Nelt._h
                # |  }              new_h - new_baseline > Nelt._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - Nelt._h + Nelt._baseline
                # ||
                # ||
                # |
                i = max(new_h - new_baseline - Nelt._h + Nelt._baseline, 0)
            for j in range(Nelt._h):
                new_matrix[i + j] += Nelt._matrix[j]
        else:
            for line in self._matrix:
                new_matrix.append(line + " " * (self._l - len(line)))
            for i, line_i in enumerate(Nelt._matrix):
                if i == len(new_matrix):
                    new_matrix.append(" " * self._l + line_i)
                else:
                    new_matrix[i] += line_i

        # breakpoint
        new_breakpoints = list(self._breakpoints)
        new_breakpoints.append(self._l)
        for bp in Nelt._breakpoints:
            new_breakpoints.append(bp + self._l)
        from sage.misc.misc import uniq

        return self.__class__(lines=new_matrix, breakpoints=uniq(new_breakpoints), baseline=new_baseline)
Example #26
0
    def __add__(self, Nelt):
        r"""
        Concatenate two ascii art object.

        By default, when two object are concatenated, the new one will be
        splittable between both.

        If the baseline is defined, the concatenation is computed such that the
        new baseline coincidate with the olders.

        For example, let `T` be a tree with it's baseline ascii art
        representation in the middle::

            o
             \
              o
             / \
            o   o

        and let `M` be a matrix with it's baseline ascii art representation at
        the middle two::

            [1 2 3]
            [4 5 6]
            [7 8 9]

        then the concatenation of both will give::

            o
             \   [1 2 3]
              o  [4 5 6]
             / \ [7 8 9]
            o   o

        If one of the objects has not baseline, the concatenation is realized
        from the top::

            o    [1 2 3]
             \   [4 5 6]
              o  [7 8 9]
             / \
            o   o

        TESTS::

            sage: from sage.misc.ascii_art import AsciiArt
            sage: l5 = AsciiArt(lines=['|' for _ in range(5)], baseline=2); l5
            |
            |
            |
            |
            |
            sage: l3 = AsciiArt(lines=['|' for _ in range(3)], baseline=1); l3
            |
            |
            |
            sage: l3 + l5
             |
            ||
            ||
            ||
             |
            sage: l5 + l3
            |
            ||
            ||
            ||
            |
            sage: l5._baseline = 0
            sage: l5 + l3
            |
            |
            |
            ||
            ||
             |
            sage: l5._baseline = 4
            sage: l5 + l3
             |
            ||
            ||
            |
            |
            |
            sage: l3._baseline = 0
            sage: l3 + l5
            |
            |
            ||
             |
             |
             |
             |
        """
        new_matrix = []
        new_h = AsciiArt._compute_new_h(self, Nelt)
        new_baseline = AsciiArt._compute_new_baseline(self, Nelt)

        if self._baseline != None and Nelt._baseline != None:
            # left traitement
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))

            if new_h > self._h:
                # |                 new_h > self._h
                # |                 new_baseline > self._baseline
                # ||<-- baseline    number of white lines at the bottom
                #  | }               :: Nelt._baseline - self._baseline
                #  | }
                if new_baseline > self._baseline:
                    for k in range(new_baseline - self._baseline):
                        new_matrix.append(" "**Integer(self._l))
                #  | }              new_h > self._h
                #  | }              new_h - new_baseline > self._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - self._h + self._baseline
                # ||
                #  |
                #  |
                if new_h - new_baseline > self._h - self._baseline:
                    for _ in range((new_h - new_baseline) -
                                   (self._h - self._baseline)):
                        new_matrix.insert(0, " "**Integer(self._l))

            # right traitement
            i = 0
            if new_h > Nelt._h:
                # |  }              new_h > Nelt._h
                # |  }              new_h - new_baseline > Nelt._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - Nelt._h + Nelt._baseline
                # ||
                # ||
                # |

                i = max(new_h - new_baseline - Nelt._h + Nelt._baseline, 0)

            for j in range(Nelt._h):
                new_matrix[i + j] += Nelt._matrix[j]
        else:
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))
            for i, line_i in enumerate(Nelt._matrix):
                if i == len(new_matrix):
                    new_matrix.append(" "**Integer(self._l) + line_i)
                else:
                    new_matrix[i] += line_i

        # breakpoint
        new_breakpoints = list(self._breakpoints)
        new_breakpoints.append(self._l)
        for bp in Nelt._breakpoints:
            new_breakpoints.append(bp + self._l)
        from sage.misc.misc import uniq
        return AsciiArt(lines=new_matrix,
                        breakpoints=uniq(new_breakpoints),
                        baseline=new_baseline,
                        atomic=False)