Changeset 7474:3b13ea60370c


Ignore:
Timestamp:
12/01/07 16:43:40 (6 years ago)
Author:
William Stein <wstein@…>
Branch:
default
Message:

Trac #787 -- quotients of vector spaces.

Location:
sage/modules
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sage/modules/free_module.py

    r7355 r7474  
    23362336        """ 
    23372337        return FreeModule_submodule_field(self.ambient_vector_space(),[], check=False) 
    2338      
    2339     def quotient(self,sub): 
     2338 
     2339    # This has to wait until we have non-abstract quotients. 
     2340    def __div__(self, sub, check=True): 
     2341        """ 
     2342        Return the quotient of self by the given subspace sub. 
     2343 
     2344        This just calls self.quotient(sub, check) 
     2345 
     2346        EXAMPLES: 
     2347            sage: V = RDF^3; W = V.span([[1,0,-1], [1,-1,0]]) 
     2348            sage: Q = V/W; Q 
     2349            Vector space quotient V/W of dimension 1 over Real Double Field where 
     2350            V: Vector space of dimension 3 over Real Double Field 
     2351            W: Vector space of degree 3 and dimension 2 over Real Double Field 
     2352            Basis matrix: 
     2353            [ 1.0  0.0 -1.0] 
     2354            [ 0.0  1.0 -1.0] 
     2355            sage: type(Q) 
     2356            <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient'> 
     2357            sage: V([1,2,3]) 
     2358            (1.0, 2.0, 3.0) 
     2359            sage: Q == V.quotient(W) 
     2360            True 
     2361            sage: Q(W.0) 
     2362            (0.0) 
     2363        """ 
     2364        return self.quotient(sub, check) 
     2365 
     2366    def quotient(self, sub, check=True): 
     2367        """ 
     2368        Return the quotient of self by the given subspace sub. 
     2369 
     2370        INPUT: 
     2371            sub -- a submodule of self, or something that can be turned into 
     2372                   one via self.submodule(sub). 
     2373            check -- (default: True) whether or not to check that sub is 
     2374                   a submodule. 
     2375 
     2376        EXAMPLES: 
     2377            sage: A = QQ^3; V = A.span([[1,2,3], [4,5,6]]) 
     2378            sage: Q = V.quotient( [V.0 + V.1] ); Q 
     2379            Vector space quotient V/W of dimension 1 over Rational Field where 
     2380            V: Vector space of degree 3 and dimension 2 over Rational Field 
     2381            Basis matrix: 
     2382            [ 1  0 -1] 
     2383            [ 0  1  2] 
     2384            W: Vector space of degree 3 and dimension 1 over Rational Field 
     2385            Basis matrix: 
     2386            [1 1 1] 
     2387            sage: Q(V.0 + V.1) 
     2388            (0) 
     2389        """ 
     2390        # Calling is_subspace may be way too slow and repeat work done below. 
     2391        # It will be very desirable to somehow do this step better.  
     2392        if check and (not is_FreeModule(sub) or not sub.is_subspace(self)): 
     2393            try: 
     2394                sub = self.subspace(sub) 
     2395            except (TypeError, ArithmeticError): 
     2396                raise ArithmeticError, "sub must be a subspace of self" 
     2397        A, L = self.__quotient_matrices(sub) 
     2398        import quotient_module 
     2399        return quotient_module.FreeModule_ambient_field_quotient(self, sub, A, L) 
     2400 
     2401    def __quotient_matrices(self, sub): 
    23402402        r""" 
    2341         Returns the quotient space of self modulo sub, together with a 
    2342         map sub must be a subspace of self. 
    2343  
    2344         EXAMPLES: 
    2345             sage: A=matrix(QQ,4,4,[0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0]) 
    2346             sage: V=(A^3).kernel() 
    2347             sage: W=A.kernel() 
    2348             sage: U,m=V.quotient(W) 
    2349             sage: [m(v) == 0 for v in W.gens()] 
     2403        This internal function is used by \code{self.quotient(...)}. 
     2404         
     2405        EXAMPLES: 
     2406            sage: V = QQ^3; W = V.span([[1,0,-1], [1,-1,0]]) 
     2407            sage: A, L = V._FreeModule_generic_field__quotient_matrices(W) 
     2408            sage: A 
     2409            [1/3] 
     2410            [1/3] 
     2411            [1/3] 
     2412            sage: L 
     2413            [1 1 1] 
     2414 
     2415        The quotient and lift maps are used to compute in the quotient 
     2416        and to lift: 
     2417            sage: Q = V/W 
     2418            sage: Q(W.0) 
     2419            (0) 
     2420            sage: Q.lift_map()(Q.0) 
     2421            (1, 1, 1) 
     2422            sage: Q(Q.lift_map()(Q.0)) 
     2423            (1) 
     2424        """ 
     2425        # 2. Find a basis C for a another submodule of self, so that 
     2426        #    B + C is a basis for self. 
     2427        # 3. Then the quotient map is: 
     2428        #     x |---> 'write in terms of basis for C and take the last m = #C-#B components. 
     2429        # 4. And a section of this map is: 
     2430        #     x |---> corresponding linear combination of entries of last m entries 
     2431        #    of the basis C. 
     2432 
     2433        # Step 1: Find bases for spaces 
     2434        B = sub.basis_matrix() 
     2435        S = self.basis_matrix() 
     2436 
     2437        # Step 2: Extend basis B to a basis for self. 
     2438        # 
     2439        # Compute a subspace of self with the property that each 
     2440        # element of M has dot product 0 with each element of sub. 
     2441        # This M is thus the orthogonal complement (with respect to 
     2442        # dot product) of the submodule sub inside self. 
     2443        # Then let C be a matrix with these rows. 
     2444         
     2445        C = B.transpose().restrict_domain(self).kernel().basis_matrix() 
     2446        C = C * S 
     2447        n = self.dimension() 
     2448        m = C.nrows() 
     2449 
     2450        # Now B and C together form a matrix whose rows are a basis for self. 
     2451        A = B.stack(C) 
     2452 
     2453        # Step 3: Compute quotient map 
     2454        # The quotient map is given by writing in terms of the above basis, 
     2455        # then taking the last #C columns 
     2456 
     2457        # Compute the matrix D "change of basis from S to A" 
     2458        # that writes each element of the basis 
     2459        # for self in terms of the basis of rows of A, i.e.,  
     2460        # want to find D such that 
     2461        #                D * A = S 
     2462        # where D is a square n x n matrix. 
     2463        # Our algorithm is to note that D is determined if we just 
     2464        # replace both A and S by the submatrix got from their pivot 
     2465        # columns. 
     2466        P  = A.pivots() 
     2467        AA = A.matrix_from_columns(P) 
     2468        SS = S.matrix_from_columns(P) 
     2469        D  = SS * AA**(-1) 
     2470 
     2471        # Compute the image of each basis vector for self under the 
     2472        # map "write an element of self in terms of the basis A" then 
     2473        # take the last n-m components. 
     2474        Q = D.matrix_from_columns(range(n - m, n)) 
     2475 
     2476        # Step 4. Section map 
     2477        # The lifting or section map 
     2478        Dinv = D**(-1) 
     2479        L = Dinv.matrix_from_rows(range(n - C.nrows(), n)) 
     2480         
     2481        return Q, L 
     2482         
     2483    def quotient_abstract(self, sub, check=True): 
     2484        r""" 
     2485        Returns an ambient free module isomorphic to the quotient 
     2486        space of self modulo sub, together with maps from self to the 
     2487        quotient, and a lifting map in the other direction. 
     2488 
     2489        Use \code{self.quotient(sub)} to obtain the quotient module 
     2490        as an object equipped with natural maps in both directions, 
     2491        and a canonical coercion. 
     2492 
     2493        INPUT: 
     2494            sub -- a submodule of self, or something that can be turned into 
     2495                   one via self.submodule(sub). 
     2496            check -- (default: True) whether or not to check that sub is 
     2497                   a submodule. 
     2498 
     2499        OUTPUT: 
     2500            U -- the quotient as an abstract *ambient* free module  
     2501            pi -- projection map to the quotient 
     2502            lift -- lifting map back from quotient 
     2503 
     2504        EXAMPLES: 
     2505            sage: V = GF(19)^3 
     2506            sage: W = V.span_of_basis([ [1,2,3], [1,0,1] ]) 
     2507            sage: U,pi,lift = V.quotient_abstract(W) 
     2508            sage: pi(V.2) 
     2509            (6) 
     2510            sage: pi(V.0) 
     2511            (13) 
     2512            sage: pi(V.0 + V.2) 
     2513            (0) 
     2514 
     2515        Another example involving a quotient of one subspace by another. 
     2516            sage: A = matrix(QQ,4,4,[0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0]) 
     2517            sage: V = (A^3).kernel() 
     2518            sage: W = A.kernel() 
     2519            sage: U, pi, lift = V.quotient_abstract(W) 
     2520            sage: [pi(v) == 0 for v in W.gens()] 
    23502521            [True] 
    2351  
    2352         TODO: 
    2353             * produce a convenient section map back from the quotient space 
    2354             * install appropriate coercions 
    2355         """ 
    2356         if not sub.is_subspace(self): 
    2357             raise ArithmeticError, "sub must be a subspace of self" 
    2358         M = sub.basis_matrix().transpose().restrict_domain(self).kernel().basis_matrix().transpose() 
    2359         quomap = self.hom(M) 
    2360         return quomap.codomain(),quomap 
    2361  
     2522            sage: [pi(lift(b)) == b for b in U.basis()] 
     2523            [True, True] 
     2524        """ 
     2525        # Calling is_subspace may be way too slow and repeat work done below. 
     2526        # It will be very desirable to somehow do this step better.  
     2527        if check and (not is_FreeModule(sub) or not sub.is_subspace(self)): 
     2528            try: 
     2529                sub = self.subspace(sub) 
     2530            except (TypeError, ArithmeticError): 
     2531                raise ArithmeticError, "sub must be a subspace of self" 
     2532 
     2533        A, L = self.__quotient_matrices(sub) 
     2534        quomap = self.hom(A) 
     2535        quo = quomap.codomain() 
     2536        liftmap = quo.Hom(self)(L) 
     2537 
     2538        return quomap.codomain(), quomap, liftmap 
     2539     
    23622540############################################################################### 
    23632541# 
     
    28212999 
    28223000 
     3001 
    28233002############################################################################### 
    28243003# 
     
    34453624            (1, 5, 9) 
    34463625        """ 
    3447         return self.basis_matrix().linear_combination_of_rows(v) 
     3626        return self(self.basis_matrix().linear_combination_of_rows(v)) 
    34483627 
    34493628 
     
    34683647        sage: loads(v.dumps()) == v 
    34693648        True             
    3470  
    3471      
    34723649    """ 
    34733650    def __init__(self, ambient, gens, check=True, inner_product_matrix=None, 
  • sage/modules/matrix_morphism.py

    r6572 r7474  
    136136        if C.is_ambient(): 
    137137            return C(v) 
    138         return C.linear_combination_of_basis(v) 
     138        return C(C.linear_combination_of_basis(v), check=False) 
    139139 
    140140    def __invert__(self): 
  • sage/modules/vector_rational_dense.pyx

    r6680 r7474  
    9595        if isinstance(x, (list, tuple)): 
    9696            if len(x) != self._degree: 
    97                 raise ArithmeticError, "entries must be a list of length %s"%self._degree 
     97                raise TypeError, "entries must be a list of length %s"%self._degree 
    9898            for i from 0 <= i < self._degree: 
    9999                z = Rational(x[i]) 
Note: See TracChangeset for help on using the changeset viewer.