Пример #1
0
 def twisted_cochain_complex(self):
     """
     Returns chain complex of the presentation CW complex of the
     given group with coefficients twisted by self.
     """
     gens, rels, rho = self.generators, self.relators, self
     d1 = [[fox_derivative(R, rho, g) for g in gens] for R in rels]
     d1 = block_matrix(d1, nrows=len(rels), ncols=len(gens))
     d0 = [rho(g) - 1 for g in gens]
     d0 = block_matrix(d0, nrow=len(gens), ncols=1)
     C = ChainComplex({0: d0, 1: d1}, check=True)
     return C
Пример #2
0
def twisted_alexander_polynomial(alpha, reduced=False):
    """
    In HKL, alpha is epsilon x rho; in nsagetools, it would be called
    phialpha with phi being epsilon.  If reduced is True, the answer is
    divided by (t - 1).

    Here, we duplicate the calculation of Section 10.2 of [HKL].

       sage: M = Manifold('K12a169')
       sage: G = M.fundamental_group()
       sage: A = matrix(GF(5), [[0, 4], [1, 4]])
       sage: rho = cyclic_rep(G, A)
       sage: chi = lambda v:3*v[0]
       sage: alpha = induced_rep_from_twisted_cocycle(3, rho, chi, (0, 0, 1, 0))
       sage: -twisted_alexander_polynomial(alpha, reduced=True)
       4*t^2 + (z^3 + z^2 + 5)*t + 4
    """
    F = alpha('a').base_ring().base_ring()
    epsilon = alpha.epsilon
    gens, rels = alpha.generators, alpha.relators
    k = len(gens)

    # Make sure this special algorithm applies.
    assert len(rels) == len(gens) - 1 and epsilon.range().rank() == 1

    # Want the first variable to be homologically nontrivial
    i0 = [i for i, g in enumerate(gens) if epsilon(g) != 0][0]
    gens = gens[i0:] + gens[:i0]

    # Boundary maps for chain complex

    d2 = [[fox_derivative_with_involution(R, alpha, g) for R in rels]
          for g in gens]
    d2 = block_matrix(d2, nrows=k, ncols=k - 1)
    d1 = [alpha(g.swapcase()) - 1 for g in gens]
    d1 = block_matrix(d1, nrows=1, ncols=k)
    assert d1 * d2 == 0

    T = last_square_submatrix(d2)
    B = first_square_submatrix(d1)

    T = normalize_polynomial(fast_determinant_of_laurent_poly_matrix(T))
    B = normalize_polynomial(fast_determinant_of_laurent_poly_matrix(B))

    q, r = T.quo_rem(B)
    assert r == 0
    ans = normalize_polynomial(q)
    if reduced:
        t = ans.parent().gen()
        ans, r = ans.quo_rem(t - 1)
        assert r == 0
    return ans
Пример #3
0
 def twisted_chain_complex(self):
     """
     Returns chain complex of the presentation CW complex of the
     given group with coefficients twisted by self.
     """
     gens, rels, rho = self.generators, self.relators, self
     d2 = [[fox_derivative_with_involution(R, rho, g) for R in rels]
           for g in gens]
     d2 = block_matrix(d2, nrows=len(gens), ncols=len(rels))
     d1 = [rho(g.swapcase()) - 1 for g in gens]
     d1 = block_matrix(d1, nrows=1, ncols=len(gens))
     C = ChainComplex({1: d1, 2: d2}, degree_of_differential=-1, check=True)
     return C
 def generic_prod_mat(dim_tuple):
     if dim_tuple in gen_prod_mat:
         return gen_prod_mat[dim_tuple]
     k = len(dim_tuple)
     first_column = zero_matrix(ZZ, k, 1)
     last_column = matrix(ZZ, k, 1, [d for d in dim_tuple])
     # If dim_list is all zeros, then return a single matrix of zeros.
     if first_column == last_column:
         return [first_column]
     current_batch = [first_column]
     next_batch = []
     gpms = []
     while len(current_batch) != 0:
         for m in current_batch:
             l = m.ncols()
             next_column_options = [range(m[r, l - 1], min(m[r, l - 1] + 2, dim_tuple[r] + 1)) for r in range(k)]
             new_column_iterator = itertools.product(*next_column_options)
             # we don't want the same column again.
             drop = next(new_column_iterator)
             for next_column_tuple in new_column_iterator:
                 next_column = matrix(ZZ, k, 1, next_column_tuple)
                 mm = block_matrix([[m, matrix(ZZ, k, 1, next_column)]], subdivide=False)
                 if next_column == last_column:
                     gpms += [mm]
                 else:
                     next_batch += [mm]
         current_batch = next_batch
         next_batch = []
     gen_prod_mat[dim_tuple] = gpms
     return gpms
Пример #5
0
def gen_tau_RNE( do_varify, rbt, usemotordyn=True, varify_trig = True ):
    
    Si = _gen_rbt_Si(rbt)
    
    IIi = range(0,rbt.dof+1)
    ### Linear dynamic parameters:
    for i in range(1,rbt.dof+1): IIi[i] = block_matrix( [ rbt.Ifi[i] , skew(rbt.mli[i]) , -skew(rbt.mli[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    ### Not linear dynamic parameters:
    #for i in range(1,dof+1): IIi[i] = block_matrix( [ rbt.Ifi_from_Ici[i] , skew(rbt.mli_e[i]) , -skew(rbt.mli_e[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    
    if do_varify:
        auxvars = []
        def custom_simplify( expression ):
        #    return trig_reduce(expression.expand()).simplify_rational()
            return expression.simplify_rational()
        
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp,auxvars,condition_func=is_compound)
            #return v6R_varify(exp,auxvars,varrepr)
        
    else:
        def varify_func(exp,varrepr):
            return exp
    
    Vi, dVi = _forward_RNE( rbt, Si, varify_func )
    tau = _backward_RNE( rbt, IIi, Si, Vi, dVi, usemotordyn, None, varify_func = varify_func )
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars,tau
    else:
        return tau
Пример #6
0
def adjdual(g, h):
    from sage.all import block_matrix, zero_matrix
    wg = g[0:3, 0]
    vg = g[3:6, 0]
    return block_matrix(
        [[skew(wg), zero_matrix(3, 3)], [skew(vg), skew(wg)]],
        subdivide=False).transpose() * h
Пример #7
0
    def semidirect_rep_from_twisted_cocycle(self, cocycle):
        """
        Given a representation rho to GL(R, n) and a rho-twisted
        1-cocycle, construct the representation to GL(R, n + 1)
        corresponding to the semidirect product.

        Note: Since we prefer to stick to left-actions only, unlike [HLK]
        this is the semidirect produce associated to the left action of
        GL(R, n) on V = R^n.  That is, pairs (v, A) with v in V and A in
        GL(R, n) where (v, A) * (w, B) = (v + A*w, A*B)::

           sage: G = Manifold('K12a169').fundamental_group()
           sage: A = matrix(GF(5), [[0, 4], [1, 4]])
           sage: rho = cyclic_rep(G, A)
           sage: cocycle = vector(GF(5), (0, 0, 1, 0))
           sage: rho_til = rho.semidirect_rep_from_twisted_cocycle(cocycle)
           sage: rho_til('abAB')
           [1 0 4]
           [0 1 1]
           [0 0 1]
        """
        gens, rels, rho = self.generators, self.relators, self
        n = rho.dim
        assert len(cocycle) == len(gens) * n
        new_mats = []
        for i, g in enumerate(gens):
            v = matrix([cocycle[i * n:(i + 1) * n]]).transpose()
            zeros = matrix(n * [0])
            one = matrix([[1]])
            A = block_matrix([[rho(g), v], [zeros, one]])
            new_mats.append(A)

        target = MatrixSpace(rho.base_ring, n + 1)
        return MatrixRepresentation(gens, rels, target, new_mats)
Пример #8
0
def StrictlyPositiveOrthant(d):
    if d == 0:
        return Polyhedron(ambient_dim=0, vertices=[()], base_ring=QQ)
    else:
        return Polyhedron(ieqs=block_matrix([[
            matrix(QQ, d, 1, [-1 for i in range(d)]),
            identity_matrix(QQ, d)
        ]]))
Пример #9
0
def gen_regressor_RNE( do_varify, rbt, usemotordyn = True, usefricdyn = True, varify_trig = True ):
  
    from copy import copy
    
    Si = _gen_rbt_Si(rbt)

    if usefricdyn:
      fric = gen_Dyn_fricterm(rbt)
    
    def custom_simplify( expression ):
        #return trig_reduce(expression.expand()).simplify_rational()
        return expression.simplify_rational()
    
    varify_func = None
    
    if do_varify:
        auxvars = []
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp, auxvars, poolrepr='auxY', condition_func=is_compound)
    
    
    Vi, dVi = _forward_RNE( rbt, Si, varify_func )
    
    P = rbt.Parms(usemotordyn,usefricdyn)
    
    Y = matrix(SR,rbt.dof,P.nrows())
    
    for p in range(P.nrows()) :
        
        select =  subsm( P, zero_matrix(P.nrows(),1) )
        select.update( {P[p,0]:Integer(1)} )
        
        IIi = range(0,rbt.dof+1)
        for i in range(1,rbt.dof+1):
            IIi[i] = block_matrix( [ rbt.Ifi[i].subs(select) , skew(rbt.mli[i].subs(select)) , -skew(rbt.mli[i].subs(select)) , rbt.mi[i].subs(select)*identity_matrix(3) ] ,subdivide=False)
        
        if usemotordyn:
          Imzi = deepcopy(rbt.Imzi)
          for i,Im in enumerate(Imzi):
            Imzi[i] = Im.subs(select)
        else:
          Imzi = None
      
        Y[:,p] = _backward_RNE( rbt, IIi, Si, Vi, dVi, usemotordyn, Imzi, varify_func )
        
        if usefricdyn:
          Y[:,p] += fric.subs(select)
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars , Y
    else:
        return Y
Пример #10
0
def preserves_hermitian_form(SL2C_matrices):
    """
    >>> CC = ComplexField(100)
    >>> A = matrix(CC, [[1, 1], [1, 2]]);
    >>> B = matrix(CC, [[0, 1], [-1, 0]])
    >>> C = matrix(CC, [[CC('I'),0], [0, -CC('I')]])
    >>> ans, sig, form = preserves_hermitian_form([A, B])
    >>> ans
    True
    >>> sig
    'indefinite'
    >>> form.change_ring(ComplexField(10))
    [  0.00 -1.0*I]
    [ 1.0*I   0.00]
    >>> preserves_hermitian_form([A, B, C])
    (False, None, None)
    >>> ans, sig, form = preserves_hermitian_form([B, C])
    >>> sig
    'definite'
    """
    M = block_matrix(len(SL2C_matrices), 1, [
        left_mult_by_adjoint(A) - right_mult_by_inverse(A)
        for A in SL2C_matrices
    ])

    CC = M.base_ring()
    mp.prec = CC.prec()
    RR = RealField(CC.prec())
    epsilon = RR(2)**(-int(0.8 * mp.prec))
    U, S, V = mp.svd(sage_matrix_to_mpmath(M))
    S = list(mp.chop(S, epsilon))
    if mp.zero not in S:
        return False, None, None
    elif S.count(mp.zero) > 1:
        for i, A in enumerate(SL2C_matrices):
            for B in SL2C_matrices[i + 1:]:
                assert (A * B - B * A).norm() < epsilon

        sig = 'indefinite' if any(abs(A.trace()) > 2
                                  for A in SL2C_matrices) else 'both'
        return True, sig, None
    else:
        in_kernel = list(mp.chop(V.H.column(S.index(mp.zero))))
        J = mp.matrix([in_kernel[:2], in_kernel[2:]])
        iJ = mp.mpc(imag=1) * J
        J1, J2 = J + J.H, iJ + iJ.H
        J = J1 if mp.norm(J1) >= mp.norm(J2) else J2
        J = (1 / mp.sqrt(abs(mp.det(J)))) * J
        J = mpmath_matrix_to_sage(J)
        assert all((A.conjugate_transpose() * J * A - J).norm() < epsilon
                   for A in SL2C_matrices)
        sig = 'definite' if J.det() > 0 else 'indefinite'
        return True, sig, J
Пример #11
0
def gen_massmatrix_RNE( do_varify, rbt, usemotordyn = True, varify_trig = True ):
  
    from copy import deepcopy
    
    Si = _gen_rbt_Si(rbt)
    
    IIi = range(0,rbt.dof+1)
    ### Linear dynamic parameters:
    for i in range(1,rbt.dof+1): IIi[i] = block_matrix( [ rbt.Ifi[i] , skew(rbt.mli[i]) , -skew(rbt.mli[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    ### Not linear dynamic parameters:
    #for i in range(1,dof+1): IIi[i] = block_matrix( [ rbt.Ifi_from_Ici[i] , skew(rbt.mli_e[i]) , -skew(rbt.mli_e[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    
    def custom_simplify( expression ):
        #return trig_reduce(expression.expand()).simplify_rational()
        return expression.simplify_rational()
    
    varify_func = None
    
    if do_varify:
        auxvars = []
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp, auxvars, poolrepr='auxM', condition_func=is_compound)
    
    M = matrix(SR,rbt.dof,rbt.dof)
    
    rbttmp = deepcopy(rbt)
    rbttmp.grav = zero_matrix(3,1)
    rbttmp.dq = zero_matrix(rbttmp.dof,1)
    
    for i in range(M.nrows()):
        rbttmp.ddq = zero_matrix(rbttmp.dof,1)
        rbttmp.ddq[i,0] = 1.0
        rbttmp.gen_geom()
        
        Vi, dVi = _forward_RNE( rbttmp, Si, varify_func )
        Mcoli = _backward_RNE( rbttmp, IIi, Si, Vi, dVi, usemotordyn, None, varify_func = varify_func )
        
        # Do like this since M is symmetric:
        M[:,i] = matrix(SR,i,1,M[i,:i].list()).stack( Mcoli[i:,:] )
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars , M
    else:
        return M
def prep_cmb_row((i, n, pmt, nn_to_pm, prod_mats, pm_to_nn)):
    row = zero_matrix(ZZ, 1, pmt)
    p_cols = nn_to_pm[i].columns()
    for j in range(i + 1, pmt):
        q = nn_to_pm[j]
        both_cols = list(set(p_cols + q.columns()))
        both_cols.sort()
        combined = block_matrix([[matrix(ZZ, n, 1, list(v)) for v in both_cols]], subdivide=False)
        combined.set_immutable()
        if combined in prod_mats:
            row[0, j] = pm_to_nn[combined]
        else:
            row[0, j] = -1
    if verbose:
        if i % 100 == 0:
            print 'Finished row ' + str(i)
    return [row]
def r_n_m_iter(A1, A2):
    '''
    A1: n by n half-integral, symmetric matrix.
    A2: m by m half-integral, symmetric matrix.
    Return a generator of the tuple of n by m matrice R and
    mat = block_matrix([[A1, R/2], [R^t/2, A2]]) such that
    mat is half-integral, semi positive definite.
    '''
    n = A1.ncols()
    m = A2.ncols()
    r_iters = [_r_iter(a1, a2) for a1, a2 in itertools.product(
        [A1[i, i] for i in range(n)], [A2[i, i] for i in range(m)])]
    for rs in itertools.product(*r_iters):
        R = matrix(n, [ZZ(r) for r in rs])
        mat = block_matrix([[A1, R / ZZ(2)],
                            [R.transpose() / ZZ(2), A2]])
        if is_semi_positive_definite(mat):
            yield (R, mat)
Пример #14
0
def _adaptive_newton_step(hyperbolicStructure,
                          errors_with_norm,
                          verbose=False):

    errors, errors_norm = errors_with_norm

    num_edges = len(hyperbolicStructure.mcomplex.Edges)

    penalties, penalty_derivative = _large_angle_penalties_and_derivatives(
        hyperbolicStructure, verbose=verbose)

    all_errors = vector(errors + penalties)

    jacobian = hyperbolicStructure.jacobian()
    penalty_derivative_matrix = matrix(RDF,
                                       penalty_derivative,
                                       ncols=num_edges)

    m = block_matrix([[jacobian], [penalty_derivative_matrix]])

    mInv = _pseudo_inverse(m, verbose=verbose)
    mInvErrs = mInv * all_errors

    for i in range(14):
        step_size = RDF(0.5)**i

        new_edge_params = list(
            vector(hyperbolicStructure.edge_lengths) - step_size * mInvErrs)
        try:
            newHyperbolicStructure = HyperbolicStructure(
                hyperbolicStructure.mcomplex, new_edge_params)
        except BadDihedralAngleError:
            continue

        new_errors_with_norm = _compute_errors_with_norm(
            newHyperbolicStructure)

        if new_errors_with_norm[1] < errors_norm:
            return (newHyperbolicStructure, new_errors_with_norm)

    raise NewtonStepError()
Пример #15
0
def compute_torsion(G,
                    bits_prec,
                    alpha=None,
                    phi=None,
                    phialpha=None,
                    return_parts=False,
                    return_as_poly=True,
                    wada_conventions=False,
                    symmetry_test=True):
    if alpha:
        F = alpha('a').base_ring()
    elif phialpha:
        F = phialpha('a').base_ring().base_ring()
    epsilon = ZZ(2)**(-bits_prec // 3) if not F.is_exact() else None
    big_epsilon = ZZ(2)**(-bits_prec // 5) if not F.is_exact() else None
    gens, rels = G.generators(), G.relators()
    k = len(gens)
    if phi == None:
        phi = MapToGroupRingOfFreeAbelianization(G, F)

    # Make sure this special algorithm applies.
    assert len(rels) == len(gens) - 1 and len(phi.range().gens()) == 1

    # Want the first variable to be homologically nontrivial
    i0 = [i for i, g in enumerate(gens) if phi(g) != 1][0]
    gens = gens[i0:] + gens[:i0]
    if phialpha == None:
        phialpha = PhiAlpha(phi, alpha)

    # Boundary maps for chain complex

    if not wada_conventions:  # Using the conventions of our paper.
        d2 = [[fox_derivative_with_involution(R, phialpha, g) for R in rels]
              for g in gens]
        d2 = block_matrix(d2, nrows=k, ncols=k - 1)
        d1 = [phialpha(g.swapcase()) - 1 for g in gens]
        d1 = block_matrix(d1, nrows=1, ncols=k)
        dsquared = d1 * d2

    else:  # Using those implicit in Wada's paper.
        d2 = [[fox_derivative(R, phialpha, g) for g in gens] for R in rels]
        d2 = block_matrix(sum(d2, []), nrows=k - 1, ncols=k)
        d1 = [phialpha(g) - 1 for g in gens]
        d1 = block_matrix(d1, nrows=k, ncols=1)
        dsquared = d2 * d1

    if not matrix_has_small_entries(dsquared, epsilon):
        raise TorsionComputationError("(boundary)^2 != 0")

    T = last_square_submatrix(d2)
    if return_as_poly:
        T = fast_determinant_of_laurent_poly_matrix(T)
    else:
        T = det(T)
    B = first_square_submatrix(d1)
    B = det(B)
    if return_as_poly:
        T = clean_laurent_to_poly(T, epsilon)
        B = clean_laurent_to_poly(B, epsilon)
    else:
        T = clean_laurent(T, epsilon)
        B = clean_laurent(B, epsilon)

    if return_parts:
        return (T, B)

    q, r = T.quo_rem(B)
    ans = clean_laurent_to_poly(q, epsilon)
    if univ_abs(r) > epsilon:
        raise TorsionComputationError("Division failed")

    # Now do a quick sanity check

    if symmetry_test:
        coeffs = ans.coefficients()
        error = max(
            [univ_abs(a - b) for a, b in zip(coeffs, reversed(coeffs))])
        if error > epsilon:
            raise TorsionComputationError(
                "Torsion polynomial doesn't seem symmetric")

    return ans
Пример #16
0
def Adjdual(G, g):
    from sage.all import block_matrix, zero_matrix
    R = G[0:3, 0:3]
    p = G[0:3, 3]
    return block_matrix([[R, zero_matrix(3, 3)], [skew(p) * R, R]],
                        subdivide=False).transpose() * g
Пример #17
0
def prune_dg_module_on_poset(dgm, ab, verbose=False, assume_sorted=False):
    a, b = ab
    tv = dgm.cat.objects[0]
    ring = dgm.ring
    cat = dgm.target_cat
    #diff_dict = {d:dgm.differential(tv, (d,)) for d in range(a - 1, b + 1)}
    diff_dict = {}
    for d in range(a - 1, b + 1):
        if verbose:
            print('computing differential in degree ' + str(d))
        diff_dict[d] = dgm.differential(tv, (d,))
    if verbose:
        print('original differentials computed')

    # Since we assume that cat is a poset,
    # we may convert the differentials to usual sagemath matrices
    # as long as we keep track of the row labels.
    #
    # triv = cat.trivial_representation(ring)
    # m_dict = {}
    # for d in range(a - 1, b + 1):
    #     m_dict[d] = triv(diff_dict[d])

    m_dict = {}
    for d in range(a - 1, b + 1):
        if verbose:
            print('Expanding the differential in degree ' + str(d))
        entries = []
        z = 0
        dv = diff_dict[d].data_vector
        source = diff_dict[d].source
        target = diff_dict[d].target
        for x in source:
            for y in target:
                if len(cat.hom(x, y)) == 1:
                    entries += [dv[z]]
                    z += 1
                else:
                    entries += [ring(0)]
        m_dict[d] = matrix(ring, len(source), len(target), entries)

    # This dict will keep track of the row labels
    m_source = {}
    # and dict will keep track of the target labels
    m_target = {}

    if assume_sorted:
        for d in range(a - 1, b + 1):
            for x in cat.objects:
                m_source[d, x] = 0
                m_target[d, x] = 0
                for y in diff_dict[d].source:
                    if x == y:
                        m_source[d, x] += 1
                for y in diff_dict[d].target:
                    if x == y:
                        m_target[d, x] += 1
            source_assumed = [x for x in cat.objects for _ in range(m_source[d, x])]
            if diff_dict[d].source != source_assumed:
                raise ValueError('This dgModule is not sorted in degree ' + str(d))
    else:
        # Time to sort the rows
        for d in range(a - 1, b + 1):
            targ = m_dict[d].ncols()
            rows = m_dict[d].rows()
            new_rows = []
            for x in cat.objects:
                m_source[d, x] = 0
                for i, r in enumerate(rows):
                    if diff_dict[d].source[i] == x:
                        m_source[d, x] += 1
                        new_rows += [r]
            if len(new_rows) == 0:
                m_dict[d] = zero_matrix(ring, 0, targ)
            else:
                m_dict[d] = block_matrix(ring, [[matrix(ring, 1, targ, list(r))] for r in new_rows])

        # and now the columns
        for d in range(a - 1, b + 1):
            sour = m_dict[d].nrows()
            cols = m_dict[d].columns()
            new_cols = []
            for x in cat.objects:
                m_target[d, x] = 0
                for i, c in enumerate(cols):
                    if diff_dict[d].target[i] == x:
                        m_target[d, x] += 1
                        new_cols += [c]
            if len(new_cols) == 0:
                m_dict[d] = zero_matrix(ring, sour, 0)
            else:
                m_dict[d] = block_matrix(ring, [[matrix(ring, sour, 1, list(c)) for c in new_cols]])

    # if verbose:
    #     for d in range(a - 1, b + 1):
    #         print
    #         print [m_source[d, x] for x in cat.objects]
    #         for r in m_dict[d]:
    #             print r
    #         print [m_target[d, x] for x in cat.objects]

    # Find the desired row- and column-operations
    # and change the labels (slightly prematurely)
    for d in range(a, b):
        for x in cat.objects:
            upper_left = m_dict[d][:m_source[d, x], :m_target[d, x]]
            if verbose:
                print('Computing Smith form of a matrix with dimensions ' + str(upper_left.dimensions()))
            dropped, sc, sr, tc, tr = prune_matrix(upper_left)
            if verbose:
                print('Dropping ' + str(dropped) + ' out of ' + str(m_source[d, x]) + \
                      ' occurrences of ' + str(x) + ' in degree ' + str(d - 1))
            m_target[d - 1, x] -= dropped
            m_source[d + 1, x] -= dropped
            cid = m_dict[d - 1].ncols() - sc.nrows()
            zul = zero_matrix(ring, sc.nrows(), cid)
            zlr = zero_matrix(ring, cid, sc.ncols())
            m_dict[d - 1] = m_dict[d - 1] * block_matrix([[zul, sc], [identity_matrix(ring, cid), zlr]])
            rid = m_dict[d + 1].nrows() - tr.ncols()
            zul = zero_matrix(ring, rid, tr.ncols())
            zlr = zero_matrix(ring, tr.nrows(), rid)
            m_dict[d + 1] = block_matrix([[zul, identity_matrix(ring, rid)], [tr, zlr]]) * m_dict[d + 1]

            row_rest = m_dict[d].nrows() - m_source[d, x]
            col_rest = m_dict[d].ncols() - m_target[d, x]

            m_dict[d] = block_diagonal_matrix([sr, identity_matrix(ring, row_rest)]) * m_dict[d]
            m_dict[d] = m_dict[d] * block_diagonal_matrix([tc, identity_matrix(ring, col_rest)])

            rest_rest = m_dict[d][m_source[d, x]:, m_target[d, x]:]
            rest_dropped = m_dict[d][m_source[d, x]:, :dropped]
            dropped_rest = m_dict[d][:dropped, m_target[d, x]:]
            rest_kept = m_dict[d][m_source[d, x]:, dropped:m_target[d, x]]
            kept_rest = m_dict[d][dropped:m_source[d, x], m_target[d, x]:]
            kept_kept = m_dict[d][dropped:m_source[d, x], dropped:m_target[d, x]]
            m_dict[d] = block_matrix(ring, [[rest_rest - rest_dropped * dropped_rest, rest_kept],
                                            [kept_rest,                               kept_kept]])
            m_source[d, x] -= dropped
            m_target[d, x] -= dropped

    for d in range(a - 1, b + 1):
        source = [x for x in cat.objects for _ in range(m_source[d, x])]
        target = [x for x in cat.objects for _ in range(m_target[d, x])]
        dv = [w for i, r in enumerate(m_dict[d].rows()) for j, w in enumerate(r)
              if len(cat.hom(source[i], target[j])) == 1]
        data_vector = vector(ring, dv)
        diff_dict[d] = CatMat(ring, cat, source, data_vector, target)

    def pruned_f_law(d_singleton, x, f, y):
        d = d_singleton[0]
        if d in range(a - 1, b + 1):
            return CatMat.identity_matrix(ring, cat, diff_dict[d].source)
        return dgm.module_in_degree((d,))(x, f, y)

    def pruned_d_law(x, d_singleton):
        d = d_singleton[0]
        if d in range(a - 1, b + 1):
            return diff_dict[d]
        return dgm.differential(x, (d,))

    return dgModule(TerminalCategory, ring, pruned_f_law, [pruned_d_law], target_cat=cat)
Пример #18
0
def inverse_T(T):
    from sage.all import block_matrix, zero_matrix, Integer
    return block_matrix(
        [[T[0:3, 0:3].transpose(), -T[0:3, 0:3].transpose() * T[0:3, 3]],
         [zero_matrix(1, 3), Integer(1)]],
        subdivide=False)
Пример #19
0
def PositiveOrthant(d):
    if d == 0:
        return Polyhedron(ambient_dim=0, eqns=[], ieqs=[(0, )], base_ring=QQ)
    else:
        return Polyhedron(ieqs=block_matrix(
            [[matrix(QQ, d, 1), identity_matrix(QQ, d)]]))
def conf_model(n, X, ring=ZZ, output_file_name=None, verbose=False, parallelize=True, display_degree=7):

    # Set up our graphs
    vertices = range(1, n + 1)
    edges = [(i, j) for i, j in Combinations(vertices, 2)]
    graphs = list(Subsets(edges))

    # Define the poset G(n) as a category
    def G_one(x):
        return '*'
    def G_hom(x, y):
        if x.issubset(y):
            return ['*']
        return []
    def G_comp(x, f, y, g, z):
        return '*'
    G = FiniteCategory(graphs, G_one, G_hom, G_comp)
    Gop = G.op()

    # Print out all the homsets
    if verbose:
        for x in G.objects:
            for y in G.objects:
                print 'Hom(' + str(x) + ', ' + str(y) + ') = ' + str(G.hom(x, y))

    # Build the vertices of X^n

    # Given a tuple of dimensions, this function builds all integer matrices with first column zero,
    # last column dim_tuple, all columns distinct, and where consecutive entries in a row have difference 0 or 1.
    gen_prod_mat = {}


    def generic_prod_mat(dim_tuple):
        if dim_tuple in gen_prod_mat:
            return gen_prod_mat[dim_tuple]
        k = len(dim_tuple)
        first_column = zero_matrix(ZZ, k, 1)
        last_column = matrix(ZZ, k, 1, [d for d in dim_tuple])
        # If dim_list is all zeros, then return a single matrix of zeros.
        if first_column == last_column:
            return [first_column]
        current_batch = [first_column]
        next_batch = []
        gpms = []
        while len(current_batch) != 0:
            for m in current_batch:
                l = m.ncols()
                next_column_options = [range(m[r, l - 1], min(m[r, l - 1] + 2, dim_tuple[r] + 1)) for r in range(k)]
                new_column_iterator = itertools.product(*next_column_options)
                # we don't want the same column again.
                drop = next(new_column_iterator)
                for next_column_tuple in new_column_iterator:
                    next_column = matrix(ZZ, k, 1, next_column_tuple)
                    mm = block_matrix([[m, matrix(ZZ, k, 1, next_column)]], subdivide=False)
                    if next_column == last_column:
                        gpms += [mm]
                    else:
                        next_batch += [mm]
            current_batch = next_batch
            next_batch = []
        gen_prod_mat[dim_tuple] = gpms
        return gpms


    # This set will contain a list of all the Gamma-conf matrices
    # where Gamma is the empty graph on n nodes.
    prod_mats = set()

    nonempty_faces = X.face_iterator(increasing=True)
    # This line pops off the empty face
    next(nonempty_faces)

    for simplex_tuple in itertools.product(nonempty_faces, repeat=n):
        dim_tuple = tuple(s.dimension() for s in simplex_tuple)
        for gpm in generic_prod_mat(dim_tuple):
            l = gpm.ncols()
            m = matrix(ZZ, n, l, [simplex_tuple[r][gpm[r, c]] for r in range(n) for c in range(l)])
            m.set_immutable()
            prod_mats.add(m)

    # Each prod matrix gets assigned a number.  Build the translation dicts both ways.
    # While we're looping, we also compute the row-distinctness graph for each prod matrix
    pm_to_nn = {}
    nn_to_pm = {}
    gammas = {}
    nns_by_gamma = {graph: [] for graph in graphs}
    for nn, pm in enumerate(prod_mats):
        pm_to_nn[pm] = nn
        nn_to_pm[nn] = pm
        graph = Set((i, j) for i, j in edges if pm.row(vertices.index(i)) != pm.row(vertices.index(j)))
        gammas[nn] = graph
        nns_by_gamma[graph] += [nn]

    # The matrix cmb is the combination table.  The (i, j)-entry gives the index of the smallest prod mat that
    # contains the columns of the ith and jth prod mat.  If no such prod mat exists, the table gives -1.
    pmt = len(prod_mats)
    if verbose:
        print 'Preparing combination table'
        print 'Total number of rows: ' + str(pmt)


    # def prep_cmb_row(i):
    #     row = zero_matrix(ZZ, 1, pmt)
    #     p_cols = nn_to_pm[i].columns()
    #     for j in range(i + 1, pmt):
    #         q = nn_to_pm[j]
    #         both_cols = list(set(p_cols + q.columns()))
    #         both_cols.sort()
    #         combined = block_matrix([[matrix(ZZ, n, 1, list(v)) for v in both_cols]], subdivide=False)
    #         combined.set_immutable()
    #         if combined in prod_mats:
    #             row[0, j] = pm_to_nn[combined]
    #         else:
    #             row[0, j] = -1
    #     if verbose:
    #         if i % 100 == 0:
    #             print 'Finished row ' + str(i)
    #     return [row]

    if parallelize:
        pool = Pool()

        def arg_gen(zed):
            num = 0
            while num < zed:
                yield (num, n, pmt, nn_to_pm, prod_mats, pm_to_nn)
                num += 1

        cmb_row_list = pool.map(prep_cmb_row, arg_gen(pmt))
        pool.close()
        pool.join()
    else:
        cmb_row_list = [prep_cmb_row(i) for i in range(pmt)]
    cmb = block_matrix(cmb_row_list)
    cmb = cmb + cmb.transpose() + diagonal_matrix(range(pmt))


    # Check if a list of prod matrices can have their columns assembled into a single prod matrix
    def index_compatible(list_of_indices):
        if len(list_of_indices) <= 1:
            return True
        cur = list_of_indices[0]
        for i in list_of_indices[1:]:
            cur = cmb[cur, i]
            if cur == -1:
                return False
        return True


    # For each graph Gamma, compute the minimal prod matrices of type Gamma.
    min_prod_mat_indices = []
    min_prod_mat_indices_by_gamma = {}
    for gamma in graphs:
        def leq(i, j):
            return cmb[i, j] == j
        poset = Poset((nns_by_gamma[gamma], leq))
        min_prod_mat_indices_by_gamma[gamma] = poset.minimal_elements()
        min_prod_mat_indices += min_prod_mat_indices_by_gamma[gamma]

    # Build the resulting simplicial complex model for the product
    if verbose:
        print
        print 'Building the souped-up model for the product'
        print

    # My copy of sagemath has a verbose flag for SimplicialComplex, but this is not standard yet
    prod_model = SimplicialComplex(from_characteristic_function=(index_compatible, min_prod_mat_indices))
    dim = prod_model.dimension()


    # for graph in graphs:
    #     Y = SimplicialComplex(from_characteristic_function=(index_compatible,
    #                      [i for gamma in graphs if graph.issubset(gamma) for i in min_prod_mat_indices_by_gamma[gamma]]))
    #     print 'Graph ' + str(graph)
    #     for d in range(Y.dimension() + 1):
    #         print 'Faces of dimension ' + str(d) + ': ' + str(len(Y.n_faces(d)))
    #     print Y.homology()
    #     print
    #
    #
    # sys.exit(0)

    if verbose:
        print 'Computing generator degrees'
    z = 1
    zz = sum(len(prod_model.n_faces(d)) for d in range(dim + 1))
    sorted_basis = {}
    for d in range(dim + 1):
        sorted_basis[d] = {graph: [] for graph in graphs}
        for f in prod_model.n_faces(d):
            if verbose:
                print '\r' + str(z) + '/' + str(zz),
                sys.stdout.flush()
                z += 1
            gamma = Set(set(edges).intersection(*[set(gammas[m]) for m in f]))
            sorted_basis[d][gamma] += [f]
    print

    # In degree d, this dict holds a list of faces of prod_model
    basis = {}
    # labels[d] has the same length as basis[d] and tells you which graph
    labels = {}
    for d in range(-1, dim + 2):
        basis[d] = []
        labels[d] = []
        if d in range(dim + 1):
            for graph in graphs:
                batch = sorted_basis[d][graph]
                basis[d] += batch
                labels[d] += [graph] * len(batch)


    def f_law((d,), x, f, y):
        if d in labels:
            return CatMat.identity_matrix(ring, Gop, labels[d])
        else:
            return CatMat.identity_matrix(ring, Gop, [])
Пример #21
0
def se3skew(g):
    from sage.all import block_matrix, zero_matrix, Integer
    w = g[0:3, 0]
    v = g[3:6, 0]
    return block_matrix(
        [[skew(w), v], [zero_matrix(1, 3), Integer(0)]], subdivide=False)