Esempio n. 1
0
    def as_explicit(self, applyFunc=None):
        if self.shape == (1, 1):
            return self

        if isinstance(self.shape[0], Symbol) or isinstance(
                self.shape[1], Symbol):
            loggingCritical(
                "Error : a Matrix with symbolic number of generations as rows and/or columns cannot be given as an explicit matrix."
            )
            exit()

        mat = SparseMatrix(*self.shape, {})

        for i in range(self.shape[0]):
            for j in range(self.shape[1]):
                assump = {}
                if self.is_realMatrix or (self.is_hermitian and i == j):
                    assump['real'] = True
                else:
                    assump['complex'] = True

                if i == j and self.is_antisymmetric:
                    mat[i, j] = 0
                elif i <= j:
                    mat[i, j] = Symbol(
                        '{' + str(self) + '}_{' + str(i + 1) + str(j + 1) +
                        '}', **assump)
                else:
                    if self.is_symmetric:
                        mat[i, j] = mat[j, i]
                    elif self.is_antisymmetric:
                        mat[i, j] = -1 * mat[j, i]
                    elif self.is_hermitian:
                        mat[i, j] = conjugate(mat[j, i])
                    else:
                        mat[i, j] = Symbol(
                            '{' + str(self) + '}_{' + str(i + 1) + str(j + 1) +
                            '}', **assump)

        if applyFunc is None:
            return Matrix(mat)

        # The following case is needed in Python export
        retList = mat.tolist()
        for i, row in enumerate(retList):
            for j, el in enumerate(row):
                retList[i][j] = applyFunc(el)

        return retList
Esempio n. 2
0
def matrix_coeff(m, s):
    """returns the matrix valued coefficients N_i in m(x) = N_1 * x**(n-1) + N_2 * x**(n-2) + .. + N_deg(m)

    Parameters
    ==========

    m : Matrix
        matrix to get coefficient matrices from
    s :
        symbol to compute coefficient list (coefficients are ambiguous for expressins with multiple symbols)
    """

    m_deg = matrix_degree(m, s)
    res = [zeros(m.shape[0], m.shape[1])] * (m_deg + 1)

    for r, row in enumerate(m.tolist()):
        for e, entry in enumerate(row):

            entry_coeff_list = Poly(entry, s).all_coeffs()
            if simplify(entry) == 0:
                coeff_deg = 0
            else:
                coeff_deg = degree(entry, s)

            for c, coeff in enumerate(entry_coeff_list):
                res[c + m_deg - coeff_deg] += \
                    SparseMatrix(m.shape[0], m.shape[1], {(r, e): 1}) * coeff
    return res
Esempio n. 3
0
def test_as_immutable():
    data = [[1, 2], [3, 4]]
    X = Matrix(data)
    assert sympify(X) == X.as_immutable() == ImmutableMatrix(data)

    data = {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4}
    X = SparseMatrix(2, 2, data)
    assert sympify(X) == X.as_immutable() == ImmutableSparseMatrix(2, 2, data)
Esempio n. 4
0
def _csrtodok(csr):
    """Converts a CSR representation to DOK representation"""
    smat = {}
    A, JA, IA, shape = csr
    for i in range(len(IA) - 1):
        indices = slice(IA[i], IA[i + 1])
        for l, m in zip(A[indices], JA[indices]):
            smat[i, m] = l
    return SparseMatrix(*(shape + [smat]))
Esempio n. 5
0
    def forward_stoichiometry(self):
        """The forward stoichiometric matrix"""
        matrix = SparseMatrix(len(self._species), len(self._reactions), {})
        for col, (back_species, _, _,
                  _) in enumerate(self._reactions.values()):
            for species, qty in back_species.items():
                matrix[(self.species.index(species), col)] = qty

        return matrix
Esempio n. 6
0
def test_csrtodok():
    h = [[5, 7, 5], [2, 1, 3], [0, 1, 1, 3], [3, 4]]
    g = [[12, 5, 4], [2, 4, 2], [0, 1, 2, 3], [3, 7]]
    i = [[1, 3, 12], [0, 2, 4], [0, 2, 3], [2, 5]]
    j = [[11, 15, 12, 15], [2, 4, 1, 2], [0, 1, 1, 2, 3, 4], [5, 8]]
    k = [[1, 3], [2, 1], [0, 1, 1, 2], [3, 3]]
    m = _csrtodok(h)
    assert isinstance(m, SparseMatrix)
    assert m == SparseMatrix(3, 4, {(0, 2): 5, (2, 1): 7, (2, 3): 5})
    assert _csrtodok(g) == SparseMatrix(3, 7, {
        (0, 2): 12,
        (1, 4): 5,
        (2, 2): 4
    })
    assert _csrtodok(i) == SparseMatrix([[1, 0, 3, 0, 0], [0, 0, 0, 0, 12]])
    assert _csrtodok(j) == SparseMatrix(5, 8, {
        (0, 2): 11,
        (2, 4): 15,
        (3, 1): 12,
        (4, 2): 15
    })
    assert _csrtodok(k) == SparseMatrix(3, 3, {(0, 2): 1, (2, 1): 3})
Esempio n. 7
0
    def fillMappingMatrix(self, mappingMatrix, rank, coeffList, newTerm):
        newMat = SparseMatrix(*mappingMatrix.shape, mappingMatrix._smat)
        pos = []

        for subTerm in newTerm[1].as_coeff_add()[1]:
            splitTerm = flatten(subTerm.as_coeff_mul())
            numeric = [x for x in splitTerm if x.is_number]
            coeff = str([x for x in splitTerm if not x in numeric][0])
            pos.append((coeffList.index(coeff), Mul(*numeric)))

        for el in pos:
            newMat[rank, el[0]] = el[1]

        return newMat
Esempio n. 8
0
    def tomatrix(self):
        """
        Converts MutableDenseNDimArray to Matrix. Can convert only 2-dim array, else will raise error.

        Examples
        ========

        >>> from sympy.tensor.array import MutableSparseNDimArray
        >>> a = MutableSparseNDimArray([1 for i in range(9)], (3, 3))
        >>> b = a.tomatrix()
        >>> b
        Matrix([
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]])
        """
        if self.rank() != 2:
            raise ValueError('Dimensions must be of size of 2')

        mat_sparse = {}
        for key, value in self._sparse_array.items():
            mat_sparse[self._get_tuple_index(key)] = value

        return SparseMatrix(self.shape[0], self.shape[1], mat_sparse)
Esempio n. 9
0
def test_doktocsr():
    a = SparseMatrix([[1, 2, 0, 0], [0, 3, 9, 0], [0, 1, 4, 0]])
    b = SparseMatrix(4, 6, [
        10, 20, 0, 0, 0, 0, 0, 30, 0, 40, 0, 0, 0, 0, 50, 60, 70, 0, 0, 0, 0,
        0, 0, 80
    ])
    c = SparseMatrix(4, 4, [0, 0, 0, 0, 0, 12, 0, 2, 15, 0, 12, 0, 0, 0, 0, 4])
    d = SparseMatrix(10, 10, {(1, 1): 12, (3, 5): 7, (7, 8): 12})
    e = SparseMatrix([[0, 0, 0], [1, 0, 2], [3, 0, 0]])
    f = SparseMatrix(7, 8, {(2, 3): 5, (4, 5): 12})
    assert _doktocsr(a) == [[1, 2, 3, 9, 1, 4], [0, 1, 1, 2, 1, 2],
                            [0, 2, 4, 6], [3, 4]]
    assert _doktocsr(b) == [[10, 20, 30, 40, 50, 60, 70, 80],
                            [0, 1, 1, 3, 2, 3, 4, 5], [0, 2, 4, 7, 8], [4, 6]]
    assert _doktocsr(c) == [[12, 2, 15, 12, 4], [1, 3, 0, 2, 3],
                            [0, 0, 2, 4, 5], [4, 4]]
    assert _doktocsr(d) == [[12, 7, 12], [1, 5, 8],
                            [0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3], [10, 10]]
    assert _doktocsr(e) == [[1, 2, 3], [0, 2, 0], [0, 0, 2, 3], [3, 3]]
    assert _doktocsr(f) == [[5, 12], [3, 5], [0, 0, 0, 1, 1, 2, 2, 2], [7, 8]]
Esempio n. 10
0
def test_sparse_matrix():
    return
    def eye(n):
        tmp = SparseMatrix(n,n,lambda i,j:0)
        for i in range(tmp.rows):
            tmp[i,i] = 1
        return tmp
    def zeros(n):
        return SparseMatrix(n,n,lambda i,j:0)

    # test_multiplication
    a=SparseMatrix((
        (1, 2),
        (3, 1),
        (0, 6),
        ))

    b = SparseMatrix ((
        (1, 2),
        (3, 0),
        ))

    c= a*b
    assert c[0,0]==7
    assert c[0,1]==2
    assert c[1,0]==6
    assert c[1,1]==6
    assert c[2,0]==18
    assert c[2,1]==0

    x = Symbol("x")

    c = b * Symbol("x")
    assert isinstance(c,SparseMatrix)
    assert c[0,0] == x
    assert c[0,1] == 2*x
    assert c[1,0] == 3*x
    assert c[1,1] == 0

    c = 5 * b
    assert isinstance(c,SparseMatrix)
    assert c[0,0] == 5
    assert c[0,1] == 2*5
    assert c[1,0] == 3*5
    assert c[1,1] == 0

    #test_power
    A = SparseMatrix([[2,3],[4,5]])
    assert (A**5)[:] == [6140, 8097, 10796, 14237]
    A = SparseMatrix([[2, 1, 3],[4,2, 4], [6,12, 1]])
    assert (A**3)[:] == [290, 262, 251, 448, 440, 368, 702, 954, 433]


    # test_creation
    x = Symbol("x")
    a = SparseMatrix([x, 0], [0, 0])
    m = a
    assert m.cols == m.rows
    assert m.cols == 2
    assert m[:] == [x,0,0,0]
    b = SparseMatrix(2,2, [x, 0, 0, 0])
    m = b
    assert m.cols == m.rows
    assert m.cols == 2
    assert m[:] == [x,0,0,0]

    assert a == b

    # test_determinant
    x, y = Symbol('x'), Symbol('y')

    assert SparseMatrix([ [1] ]).det() == 1

    assert SparseMatrix(( (-3,  2),
                    ( 8, -5) )).det() == -1

    assert SparseMatrix(( (x,   1),
                    (y, 2*y) )).det() == 2*x*y-y

    assert SparseMatrix(( (1, 1, 1),
                    (1, 2, 3),
                    (1, 3, 6) )).det() == 1

    assert SparseMatrix(( ( 3, -2,  0, 5),
                    (-2,  1, -2, 2),
                    ( 0, -2,  5, 0),
                    ( 5,  0,  3, 4) )).det() == -289

    assert SparseMatrix(( ( 1,  2,  3,  4),
                    ( 5,  6,  7,  8),
                    ( 9, 10, 11, 12),
                    (13, 14, 15, 16) )).det() == 0

    assert SparseMatrix(( (3, 2, 0, 0, 0),
                    (0, 3, 2, 0, 0),
                    (0, 0, 3, 2, 0),
                    (0, 0, 0, 3, 2),
                    (2, 0, 0, 0, 3) )).det() == 275

    assert SparseMatrix(( (1, 0,  1,  2, 12),
                    (2, 0,  1,  1,  4),
                    (2, 1,  1, -1,  3),
                    (3, 2, -1,  1,  8),
                    (1, 1,  1,  0,  6) )).det() == -55

    assert SparseMatrix(( (-5,  2,  3,  4,  5),
                    ( 1, -4,  3,  4,  5),
                    ( 1,  2, -3,  4,  5),
                    ( 1,  2,  3, -2,  5),
                    ( 1,  2,  3,  4, -1) )).det() == 11664

    assert SparseMatrix(( ( 2,  7, -1, 3, 2),
                    ( 0,  0,  1, 0, 1),
                    (-2,  0,  7, 0, 2),
                    (-3, -2,  4, 5, 3),
                    ( 1,  0,  0, 0, 1) )).det() == 123

    # test_submatrix
    m0 = eye(4)
    assert m0[0:3, 0:3] == eye(3)
    assert m0[2:4, 0:2] == zeros(2)

    m1 = SparseMatrix(3,3, lambda i,j: i+j)
    assert m1[0,:] == SparseMatrix(1,3,(0,1,2))
    assert m1[1:3, 1] == SparseMatrix(2,1,(2,3))

    m2 = SparseMatrix([0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15])
    assert m2[:,-1] == SparseMatrix(4,1,[3,7,11,15])
    assert m2[-2:,:] == SparseMatrix([[8,9,10,11],[12,13,14,15]])

    # test_submatrix_assignment
    m = zeros(4)
    m[2:4, 2:4] = eye(2)
    assert m == SparseMatrix((0,0,0,0),
                        (0,0,0,0),
                        (0,0,1,0),
                        (0,0,0,1))
    m[0:2, 0:2] = eye(2)
    assert m == eye(4)
    m[:,0] = SparseMatrix(4,1,(1,2,3,4))
    assert m == SparseMatrix((1,0,0,0),
                        (2,1,0,0),
                        (3,0,1,0),
                        (4,0,0,1))
    m[:,:] = zeros(4)
    assert m == zeros(4)
    m[:,:] = ((1,2,3,4),(5,6,7,8),(9, 10, 11, 12),(13,14,15,16))
    assert m == SparseMatrix(((1,2,3,4),
                        (5,6,7,8),
                        (9, 10, 11, 12),
                        (13,14,15,16)))
    m[0:2, 0] = [0,0]
    assert m == SparseMatrix(((0,2,3,4),
                        (0,6,7,8),
                        (9, 10, 11, 12),
                        (13,14,15,16)))

    # test_reshape
    m0 = eye(3)
    assert m0.reshape(1,9) == SparseMatrix(1,9,(1,0,0,0,1,0,0,0,1))
    m1 = SparseMatrix(3,4, lambda i,j: i+j)
    assert m1.reshape(4,3) == SparseMatrix((0,1,2), (3,1,2), (3,4,2), (3,4,5))
    assert m1.reshape(2,6) == SparseMatrix((0,1,2,3,1,2), (3,4,2,3,4,5))

    # test_applyfunc
    m0 = eye(3)
    assert m0.applyfunc(lambda x:2*x) == eye(3)*2
    assert m0.applyfunc(lambda x: 0 ) == zeros(3)

    # test_LUdecomp
    testmat = SparseMatrix([[0,2,5,3],
                      [3,3,7,4],
                      [8,4,0,2],
                      [-2,6,3,4]])
    L,U,p = testmat.LUdecomposition()
    assert L.is_lower()
    assert U.is_upper()
    assert (L*U).permuteBkwd(p)-testmat == zeros(4)

    testmat = SparseMatrix([[6,-2,7,4],
                      [0,3,6,7],
                      [1,-2,7,4],
                      [-9,2,6,3]])
    L,U,p = testmat.LUdecomposition()
    assert L.is_lower()
    assert U.is_upper()
    assert (L*U).permuteBkwd(p)-testmat == zeros(4)

    x, y, z = Symbol('x'), Symbol('y'), Symbol('z')
    M = Matrix(((1, x, 1), (2, y, 0), (y, 0, z)))
    L, U, p = M.LUdecomposition()
    assert L.is_lower()
    assert U.is_upper()
    assert (L*U).permuteBkwd(p)-M == zeros(3)

    # test_LUsolve
    A = SparseMatrix([[2,3,5],
                [3,6,2],
                [8,3,6]])
    x = SparseMatrix(3,1,[3,7,5])
    b = A*x
    soln = A.LUsolve(b)
    assert soln == x
    A = SparseMatrix([[0,-1,2],
                [5,10,7],
                [8,3,4]])
    x = SparseMatrix(3,1,[-1,2,5])
    b = A*x
    soln = A.LUsolve(b)
    assert soln == x

    # test_inverse
    A = eye(4)
    assert A.inv() == eye(4)
    assert A.inv("LU") == eye(4)
    assert A.inv("ADJ") == eye(4)
    A = SparseMatrix([[2,3,5],
                [3,6,2],
                [8,3,6]])
    Ainv = A.inv()
    assert A*Ainv == eye(3)
    assert A.inv("LU") == Ainv
    assert A.inv("ADJ") == Ainv

    # test_cross
    v1 = Matrix(1,3,[1,2,3])
    v2 = Matrix(1,3,[3,4,5])
    assert v1.cross(v2) == Matrix(1,3,[-2,4,-2])
    assert v1.norm(v1) == 14

    # test_cofactor
    assert eye(3) == eye(3).cofactorMatrix()
    test = SparseMatrix([[1,3,2],[2,6,3],[2,3,6]])
    assert test.cofactorMatrix() == SparseMatrix([[27,-6,-6],[-12,2,3],[-3,1,0]])
    test = SparseMatrix([[1,2,3],[4,5,6],[7,8,9]])
    assert test.cofactorMatrix() == SparseMatrix([[-3,6,-3],[6,-12,6],[-3,6,-3]])

    # test_jacobian
    x = Symbol('x')
    y = Symbol('y')
    L = SparseMatrix(1,2,[x**2*y, 2*y**2 + x*y])
    syms = [x,y]
    assert L.jacobian(syms) == Matrix([[2*x*y, x**2],[y, 4*y+x]])

    L = SparseMatrix(1,2,[x, x**2*y**3])
    assert L.jacobian(syms) == SparseMatrix([[1, 0], [2*x*y**3, x**2*3*y**2]])

    # test_QR
    A = Matrix([[1,2],[2,3]])
    Q, S = A.QRdecomposition()
    R = Rational
    assert Q == Matrix([[5**R(-1,2), (R(2)/5)*(R(1)/5)**R(-1,2)], [2*5**R(-1,2), (-R(1)/5)*(R(1)/5)**R(-1,2)]])
    assert S == Matrix([[5**R(1,2), 8*5**R(-1,2)], [0, (R(1)/5)**R(1,2)]])
    assert Q*S == A
    assert Q.T * Q == eye(2)

    # test nullspace
    # first test reduced row-ech form
    R = Rational

    M = Matrix([[5,7,2,1],
               [1,6,2,-1]])
    out, tmp = M.rref()
    assert out == Matrix([[1,0,-R(2)/23,R(13)/23],
                              [0,1,R(8)/23, R(-6)/23]])

    M = Matrix([[1,3,0,2,6,3,1],
                [-2,-6,0,-2,-8,3,1],
                [3,9,0,0,6,6,2],
                [-1,-3,0,1,0,9,3]])
    out, tmp = M.rref()
    assert out == Matrix([[1,3,0,0,2,0,0],
                               [0,0,0,1,2,0,0],
                               [0,0,0,0,0,1,R(1)/3],
                               [0,0,0,0,0,0,0]])
    # now check the vectors
    basis = M.nullspace()
    assert basis[0] == Matrix([[-3,1,0,0,0,0,0]])
    assert basis[1] == Matrix([[0,0,1,0,0,0,0]])
    assert basis[2] == Matrix([[-2,0,0,-2,1,0,0]])
    assert basis[3] == Matrix([[0,0,0,0,0,R(-1)/3, 1]])


    # test eigen
    x = Symbol('x')
    y = Symbol('y')
    eye3 = eye(3)
    assert eye3.charpoly(x) == (1-x)**3
    assert eye3.charpoly(y) == (1-y)**3
    # test values
    M = Matrix([(0,1,-1),
                (1,1,0),
                (-1,0,1) ])
    vals = M.eigenvals()
    vals.sort()
    assert vals == [-1, 1, 2]

    R = Rational
    M = Matrix([ [1,0,0],
                 [0,1,0],
                 [0,0,1]])
    assert M.eigenvects() == [[1, 3, [Matrix(1,3,[1,0,0]), Matrix(1,3,[0,1,0]), Matrix(1,3,[0,0,1])]]]
    M = Matrix([ [5,0,2],
                 [3,2,0],
                 [0,0,1]])
    assert M.eigenvects() == [[1, 1, [Matrix(1,3,[R(-1)/2,R(3)/2,1])]],
                              [2, 1, [Matrix(1,3,[0,1,0])]],
                              [5, 1, [Matrix(1,3,[1,1,0])]]]

    assert M.zeros((3, 5)) == SparseMatrix(3, 5, {})
Esempio n. 11
0
    def generate_jacobians(self):
        """
        Generate Jacobians and store to corresponding triplets.

        The internal indices of equations and variables are stored, alongside the lambda functions.

        For example, dg/dy is a sparse matrix whose elements are ``(row, col, val)``, where ``row`` and ``col``
        are the internal indices, and ``val`` is the numerical lambda function. They will be stored to

            row -> self.calls._igy
            col -> self.calls._jgy
            val -> self.calls._vgy

        """
        logger.debug(f'- Generating Jacobians for {self.class_name}')

        # clear storage
        self.df_syms, self.dg_syms = Matrix([]), Matrix([])
        self.calls.clear_ijv()

        # NOTE: SymPy does not allow getting the derivative of an empty array
        if len(self.g_matrix) > 0:
            self.dg_syms = self.g_matrix.jacobian(self.vars_list)

        if len(self.f_matrix) > 0:
            self.df_syms = self.f_matrix.jacobian(self.vars_list)

        self.df_sparse = SparseMatrix(self.df_syms)
        self.dg_sparse = SparseMatrix(self.dg_syms)

        vars_syms_list = list(self.vars_dict)
        algebs_and_ext_list = list(self.cache.algebs_and_ext)
        states_and_ext_list = list(self.cache.states_and_ext)

        fg_sparse = [self.df_sparse, self.dg_sparse]
        j_args = defaultdict(list)   # argument list for each jacobian call
        j_calls = defaultdict(list)  # jacobian functions (one for each type)

        for idx, eq_sparse in enumerate(fg_sparse):
            for item in eq_sparse.row_list():
                e_idx, v_idx, e_symbolic = item
                if idx == 0:
                    eq_name = states_and_ext_list[e_idx]
                else:
                    eq_name = algebs_and_ext_list[e_idx]

                var_name = vars_syms_list[v_idx]
                eqn = self.cache.all_vars[eq_name]    # `BaseVar` that corr. to the equation
                var = self.cache.all_vars[var_name]   # `BaseVar` that corr. to the variable
                jname = f'{eqn.e_code}{var.v_code}'

                # jac calls with all arguments and stored individually
                self.calls.append_ijv(jname, e_idx, v_idx, 0)

                # collect unique arguments for jac calls
                free_syms = self._check_expr_symbols(e_symbolic)
                for fs in free_syms:
                    if fs not in j_args[jname]:
                        j_args[jname].append(fs)
                j_calls[jname].append(e_symbolic)

        for jname in j_calls:
            self.calls.j_args[jname] = [str(i) for i in j_args[jname]]
            self.calls.j[jname] = lambdify(j_args[jname], tuple(j_calls[jname]), modules=self.lambdify_func)

        self.calls.j_names = list(j_calls.keys())

        # The for-loop below is intended to add an epsilon small value to the diagonal of `gy`.
        # The user should take care of the algebraic equations by using `diag_eps` in `Algeb` definition

        for var in self.parent.cache.vars_int.values():
            if var.diag_eps == 0.0:
                continue
            elif var.diag_eps is True:
                eps = self.parent.system.config.diag_eps
            else:
                eps = var.diag_eps

            if var.e_code == 'g':
                eq_list = algebs_and_ext_list
            else:
                eq_list = states_and_ext_list

            e_idx = eq_list.index(var.name)
            v_idx = vars_syms_list.index(var.name)

            self.calls.append_ijv(f'{var.e_code}{var.v_code}c', e_idx, v_idx, eps)
Esempio n. 12
0
class SymProcessor:
    """
    A helper class for symbolic processing and code generation.

    Parameters
    ----------
    parent : Model
        The `Model` instance to document

    Attributes
    ----------
    xy : sympy.Matrix
        variables pretty print in the order of State, ExtState, Algeb, ExtAlgeb
    f : sympy.Matrix
        differential equations pretty print
    g : sympy.Matrix
        algebraic equations pretty print
    df : sympy.SparseMatrix
        df /d (xy) pretty print
    dg : sympy.SparseMatrix
        dg /d (xy) pretty print
    inputs_dict : OrderedDict
        All possible symbols in equations, including variables, parameters, discrete flags, and
        config flags. It has the same variables as what ``get_inputs()`` returns.
    vars_dict : OrderedDict
        variable-only symbols, which are useful when getting the Jacobian matrices.

    """

    def __init__(self, parent):

        self.parent = parent
        # symbols that are input to lambda functions
        # including parameters, variables, services, configs, and scalars (dae_t, sys_f, sys_mva)
        self.inputs_dict = OrderedDict()
        self.lambdify_func = [dict(), 'numpy']

        self.vars_dict = OrderedDict()
        self.vars_int_dict = OrderedDict()   # internal variables only
        self.vars_list = list()

        self.f_list, self.g_list = list(), list()  # symbolic equations in lists
        self.f_matrix, self.g_matrix, self.s_matrix = list(), list(), list()  # equations in matrices

        # pretty print of variables
        self.xy = list()  # variables in the order of states, algebs
        self.f, self.g, self.s = list(), list(), list()
        self.df, self.dg = None, None

        # get references to the parent attributes
        self.calls = parent.calls
        self.cache = parent.cache
        self.config = parent.config
        self.class_name = parent.class_name
        self.tex_names = OrderedDict()

    def generate_symbols(self):
        """
        Generate symbols for symbolic equation generations.

        This function should run before other generate equations.

        Attributes
        ----------
        inputs_dict : OrderedDict
            name-symbol pair of all parameters, variables and configs

        vars_dict : OrderedDict
            name-symbol pair of all variables, in the order of (states_and_ext + algebs_and_ext)

        """

        logger.debug(f'- Generating symbols for {self.class_name}')

        # clear symbols storage
        self.f_list, self.g_list = list(), list()
        self.f_matrix, self.g_matrix = Matrix([]), Matrix([])

        # process tex_names defined in model
        # -----------------------------------------------------------
        for key in self.parent.tex_names.keys():
            self.tex_names[key] = Symbol(self.parent.tex_names[key])
        for instance in self.parent.discrete.values():
            for name, tex_name in zip(instance.get_names(), instance.get_tex_names()):
                self.tex_names[name] = tex_name
        # -----------------------------------------------------------

        for var in self.cache.all_params_names:
            self.inputs_dict[var] = Symbol(var)

        for var in self.cache.all_vars_names:
            tmp = Symbol(var)
            self.vars_dict[var] = tmp
            self.inputs_dict[var] = tmp
            if var in self.cache.vars_int:
                self.vars_int_dict[var] = tmp

        # store tex names defined in `self.config`
        for key in self.config.as_dict():
            tmp = Symbol(key)
            self.inputs_dict[key] = tmp
            if key in self.config.tex_names:
                self.tex_names[tmp] = Symbol(self.config.tex_names[key])

        # store tex names for pretty printing replacement later
        for var in self.inputs_dict:
            if var in self.parent.__dict__ and self.parent.__dict__[var].tex_name is not None:
                self.tex_names[Symbol(var)] = Symbol(self.parent.__dict__[var].tex_name)

        self.inputs_dict['dae_t'] = Symbol('dae_t')
        self.inputs_dict['sys_f'] = Symbol('sys_f')
        self.inputs_dict['sys_mva'] = Symbol('sys_mva')

        self.lambdify_func[0]['Indicator'] = lambda x: x
        self.lambdify_func[0]['imag'] = np.imag
        self.lambdify_func[0]['real'] = np.real
        self.lambdify_func[0]['im'] = np.imag
        self.lambdify_func[0]['re'] = np.real

        self.vars_list = list(self.vars_dict.values())  # useful for ``.jacobian()``

    def _check_expr_symbols(self, expr):
        """
        Check if expression contains unknown symbols.
        """
        fs = expr.free_symbols
        for item in fs:
            if item not in self.inputs_dict.values():
                raise ValueError(f'{self.class_name} expression "{expr}" contains unknown symbol "{item}"')

        return fs

    def generate_equations(self):
        logger.debug(f'- Generating equations for {self.class_name}')

        self.f_list, self.g_list = list(), list()

        self.calls.f = None
        self.calls.g = None
        self.calls.f_args = list()
        self.calls.g_args = list()

        vars_list = [self.cache.states_and_ext, self.cache.algebs_and_ext]
        expr_list = [self.f_list, self.g_list]

        eqn_names = ['f', 'g']
        eqn_args = [self.calls.f_args, self.calls.g_args]

        for vlist, elist, ename, eargs in zip(vars_list, expr_list, eqn_names, eqn_args):
            sym_args = list()
            for name, instance in vlist.items():
                if instance.e_str is None:
                    elist.append(0)
                else:
                    try:
                        expr = sympify(instance.e_str, locals=self.inputs_dict)
                    except (SympifyError, TypeError) as e:
                        logger.error('Error parsing equation "%s "for %s.%s',
                                     instance.e_str, instance.owner.class_name, name)
                        raise e

                    free_syms = self._check_expr_symbols(expr)
                    for s in free_syms:
                        if s not in sym_args:
                            sym_args.append(s)
                            eargs.append(str(s))

                    elist.append(expr)
            if len(elist) == 0 or not any(elist):  # `any`, not `all`
                self.calls.__dict__[ename] = None
            else:
                self.calls.__dict__[ename] = lambdify(sym_args, tuple(elist),
                                                      modules=self.lambdify_func)

        # convert to SymPy matrices
        self.f_matrix = Matrix(self.f_list)
        self.g_matrix = Matrix(self.g_list)

    def generate_services(self):
        """
        Generate calls for services, including ``ConstService`` and
        ``VarService`` among others.

        Sequence is preserved due to possible dependency
        """

        s_args = OrderedDict()
        s_syms = OrderedDict()
        s_calls = OrderedDict()

        for name, instance in self.parent.services.items():
            v_str = '0' if instance.v_str is None else instance.v_str
            try:
                expr = sympify(v_str, locals=self.inputs_dict)
            except (SympifyError, TypeError) as e:
                logger.error(f'Error parsing equation for {instance.owner.class_name}.{name}')
                raise e
            self._check_expr_symbols(expr)
            s_syms[name] = expr
            s_args[name] = [str(i) for i in expr.free_symbols]
            s_calls[name] = lambdify(s_args[name], s_syms[name], modules=self.lambdify_func)

        self.s_matrix = Matrix(list(s_syms.values()))
        self.calls.s = s_calls
        self.calls.s_args = s_args

    def generate_jacobians(self):
        """
        Generate Jacobians and store to corresponding triplets.

        The internal indices of equations and variables are stored, alongside the lambda functions.

        For example, dg/dy is a sparse matrix whose elements are ``(row, col, val)``, where ``row`` and ``col``
        are the internal indices, and ``val`` is the numerical lambda function. They will be stored to

            row -> self.calls._igy
            col -> self.calls._jgy
            val -> self.calls._vgy

        """
        logger.debug(f'- Generating Jacobians for {self.class_name}')

        # clear storage
        self.df_syms, self.dg_syms = Matrix([]), Matrix([])
        self.calls.clear_ijv()

        # NOTE: SymPy does not allow getting the derivative of an empty array
        if len(self.g_matrix) > 0:
            self.dg_syms = self.g_matrix.jacobian(self.vars_list)

        if len(self.f_matrix) > 0:
            self.df_syms = self.f_matrix.jacobian(self.vars_list)

        self.df_sparse = SparseMatrix(self.df_syms)
        self.dg_sparse = SparseMatrix(self.dg_syms)

        vars_syms_list = list(self.vars_dict)
        algebs_and_ext_list = list(self.cache.algebs_and_ext)
        states_and_ext_list = list(self.cache.states_and_ext)

        fg_sparse = [self.df_sparse, self.dg_sparse]
        j_args = defaultdict(list)   # argument list for each jacobian call
        j_calls = defaultdict(list)  # jacobian functions (one for each type)

        for idx, eq_sparse in enumerate(fg_sparse):
            for item in eq_sparse.row_list():
                e_idx, v_idx, e_symbolic = item
                if idx == 0:
                    eq_name = states_and_ext_list[e_idx]
                else:
                    eq_name = algebs_and_ext_list[e_idx]

                var_name = vars_syms_list[v_idx]
                eqn = self.cache.all_vars[eq_name]    # `BaseVar` that corr. to the equation
                var = self.cache.all_vars[var_name]   # `BaseVar` that corr. to the variable
                jname = f'{eqn.e_code}{var.v_code}'

                # jac calls with all arguments and stored individually
                self.calls.append_ijv(jname, e_idx, v_idx, 0)

                # collect unique arguments for jac calls
                free_syms = self._check_expr_symbols(e_symbolic)
                for fs in free_syms:
                    if fs not in j_args[jname]:
                        j_args[jname].append(fs)
                j_calls[jname].append(e_symbolic)

        for jname in j_calls:
            self.calls.j_args[jname] = [str(i) for i in j_args[jname]]
            self.calls.j[jname] = lambdify(j_args[jname], tuple(j_calls[jname]), modules=self.lambdify_func)

        self.calls.j_names = list(j_calls.keys())

        # The for-loop below is intended to add an epsilon small value to the diagonal of `gy`.
        # The user should take care of the algebraic equations by using `diag_eps` in `Algeb` definition

        for var in self.parent.cache.vars_int.values():
            if var.diag_eps == 0.0:
                continue
            elif var.diag_eps is True:
                eps = self.parent.system.config.diag_eps
            else:
                eps = var.diag_eps

            if var.e_code == 'g':
                eq_list = algebs_and_ext_list
            else:
                eq_list = states_and_ext_list

            e_idx = eq_list.index(var.name)
            v_idx = vars_syms_list.index(var.name)

            self.calls.append_ijv(f'{var.e_code}{var.v_code}c', e_idx, v_idx, eps)

    def generate_pretty_print(self):
        """
        Generate pretty print variables and equations.
        """
        logger.debug(f"- Generating pretty prints for {self.class_name}")

        # equation symbols for pretty printing
        self.f, self.g = Matrix([]), Matrix([])

        self.xy = Matrix(list(self.vars_dict.values())).subs(self.tex_names)

        # get pretty printing equations by substituting symbols
        self.f = self.f_matrix.subs(self.tex_names)
        self.g = self.g_matrix.subs(self.tex_names)
        self.s = self.s_matrix.subs(self.tex_names)

        # store latex strings
        nx = len(self.f)
        ny = len(self.g)
        self.calls.x_latex = [latex(item) for item in self.xy[:nx]]
        self.calls.y_latex = [latex(item) for item in self.xy[nx:nx + ny]]

        self.calls.f_latex = [latex(item) for item in self.f]
        self.calls.g_latex = [latex(item) for item in self.g]
        self.calls.s_latex = [latex(item) for item in self.s]

        self.df = self.df_sparse.subs(self.tex_names)
        self.dg = self.dg_sparse.subs(self.tex_names)

        # store init latex strings
        init_latex = OrderedDict()
        for name, instance in self.cache.all_vars.items():
            if instance.v_str is None and instance.v_iter is None:
                init_latex[name] = ''
            else:
                if instance.v_str is not None:
                    init_latex[name] = latex(self.v_str_syms[name].subs(self.tex_names))
                if instance.v_iter is not None:
                    init_latex[name] = latex(self.v_iter_syms[name].subs(self.tex_names))

        self.calls.init_latex = init_latex

    def generate_pycode(self, pycode_path):
        """
        Create output source code file for generated code.

        Generated code are stored at ``~/.andes/pycode``.
        """

        import pprint
        pycode_path = get_pycode_path(pycode_path, mkdir=True)

        file_path = os.path.join(pycode_path, f'{self.class_name}.py')
        header = \
            """from collections import OrderedDict  # NOQA

from numpy import nan, pi, sin, cos, tan, sqrt, exp, select  # NOQA
from numpy import greater_equal, less_equal, greater, less   # NOQA
from numpy import logical_and, logical_or, logical_not  # NOQA
from numpy import array, real, imag, conj, angle, arctan, radians  # NOQA
from numpy import log  # NOQA


"""

        with open(file_path, 'w') as f:
            f.write(header)
            f.write(self._rename_func(self.calls.f, 'f_update'))
            f.write(self._rename_func(self.calls.g, 'g_update'))

            for name in self.calls.j:
                f.write(self._rename_func(self.calls.j[name], f'{name}_update'))

            # initialization: assignments
            for name in self.calls.ia:
                f.write(self._rename_func(self.calls.ia[name], f'{name}_ia'))
            for name in self.calls.ii:
                f.write(self._rename_func(self.calls.ii[name], f'{name}_ii'))
            for name in self.calls.ij:
                f.write(self._rename_func(self.calls.ij[name], f'{name}_ij'))

            # services
            for name in self.calls.s:
                f.write(self._rename_func(self.calls.s[name], f'{name}_svc'))

            # variables
            for name in dilled_vars:
                f.write(f'\n{name} = ' + pprint.pformat(self.calls.__dict__[name]))

    def _rename_func(self, func, func_name):
        """
        Rename the function name and return source code.

        This function does not check for name conflicts.
        Install `yapf` for optional code reformatting (takes extra processing time).
        """
        import inspect

        if func is None:
            return f"# empty {func_name}\n"

        src = inspect.getsource(func)
        src = src.replace("def _lambdifygenerated(", f"def {func_name}(")
        # remove `Indicator`
        src = src.replace("Indicator", "")

        if self.parent.system.config.yapf_pycode:
            try:
                from yapf.yapflib.yapf_api import FormatCode
                src = FormatCode(src, style_config='pep8')[0]  # drop the encoding `None`
            except ImportError:
                logger.warning("`yapf` not installed. Skipped code reformatting.")

        src += '\n'
        return src

    def generate_dependency(self):
        """
        Generate dependency list and initialization order.
        """
        self.v_str_syms = OrderedDict()
        self.v_iter_syms = OrderedDict()
        deps = dict()

        # convert to symbols
        for name, instance in self.cache.all_vars.items():
            if instance.v_str is not None:
                sympified = sympify(instance.v_str, locals=self.inputs_dict)
                self._check_expr_symbols(sympified)
                self.v_str_syms[name] = sympified
            else:
                # default initial values to zero
                sympified = sympify('0.0', locals=self.inputs_dict)
                self.v_str_syms[name] = sympified

            if instance.v_iter is not None:
                sympified = sympify(instance.v_iter, locals=self.inputs_dict)
                self._check_expr_symbols(sympified)
                self.v_iter_syms[name] = sympified

        # store deps for explicit and iterative initializers
        for name, expr in self.v_str_syms.items():
            _store_deps(name, expr, self.vars_dict, deps)

        for name, expr in self.v_iter_syms.items():
            _store_deps(name, expr, self.vars_dict, deps)

        # resolve dependency
        self.init_seq = resolve_deps(deps)
        self.calls.init_seq = self.init_seq

    def check_v_iter(self):
        """
        Helper function to check if `v_iter` is defined for variables
        with circular dependencies.
        """

        for item in self.init_seq:
            if not isinstance(item, list):
                continue

            for vi in item:
                if self.cache.all_vars[vi].v_iter is None:
                    logger.error("%s: v_iter not defined for %s" % (self.class_name, vi))

    def generate_init(self):
        """
        Generate initialization equations.
        """

        self.generate_dependency()
        self.check_v_iter()
        self.generate_init_eqn()
        self.lambdify_init()

    def generate_init_eqn(self):
        """
        Generate initialization equations.

        The RHS of assignment equations ``v = v_str(x, y)`` or RHS of iterative
        initialization equations in the form of ``0 = v_iter(x, y)`` will be
        stored to ``self.init_list``.

        A list of flags will be stored to ``self.init_flag`` with 0 for
        assignments and 1 for iterative.

        For iteratively initialized variables that require assigned initial
        values (to improve convergence), the initial value can be provided
        through `self.v_str`.
        """

        self.init_asn = OrderedDict()       # assignment-type initialization
        self.init_itn = OrderedDict()       # iterative initialization
        self.init_itn_vars = OrderedDict()  # variables corr. to iterative vars
        self.init_jac = OrderedDict()

        for item in self.init_seq:
            if isinstance(item, str):
                instance = self.parent.__dict__[item]
                if instance.v_str is not None:
                    self.init_asn[item] = self.v_str_syms[item]
                if instance.v_iter is not None:
                    self.init_itn[item] = self.v_iter_syms[item]

            elif isinstance(item, list):
                name_concat = '_'.join(item)
                eqn_set = Matrix([self.v_iter_syms[name] for name in item])
                self.init_itn[name_concat] = eqn_set
                self.init_itn_vars[name_concat] = item
                for vv in item:
                    instance = self.parent.__dict__[vv]
                    if instance.v_str is not None:
                        self.init_asn[vv] = self.v_str_syms[vv]

        for name, expr in self.init_itn.items():
            vars_iter = OrderedDict()
            for item in self.init_itn_vars[name]:
                vars_iter[item] = self.vars_dict[item]

            self.init_jac[name] = expr.jacobian(list(vars_iter.values()))

    def lambdify_init(self):
        """
        Convert equations and Jacobians to lambda functions.
        """

        init_a = OrderedDict()
        init_i = OrderedDict()
        init_j = OrderedDict()
        ia_args = OrderedDict()  # arguments for assignment init.
        ii_args = OrderedDict()  # arguments for iterative init.
        ij_args = OrderedDict()

        for name, expr in self.init_asn.items():
            self._check_expr_symbols(expr)
            ia_args[name] = [str(i) for i in expr.free_symbols]
            init_a[name] = lambdify(ia_args[name], expr, modules=self.lambdify_func)

        for name, expr in self.init_itn.items():
            self._check_expr_symbols(expr)
            ii_args[name] = [str(i) for i in expr.free_symbols]
            init_i[name] = lambdify(ii_args[name], expr, modules=self.lambdify_func)

            jexpr = self.init_jac[name]
            ij_args[name] = [str(i) for i in jexpr.free_symbols]
            init_j[name] = lambdify(ij_args[name], jexpr, modules=self.lambdify_func)

        self.calls.ia = init_a
        self.calls.ii = init_i
        self.calls.ij = init_j
        self.calls.ia_args = ia_args
        self.calls.ii_args = ii_args
        self.calls.ij_args = ij_args
Esempio n. 13
0
 def C2Fmat(self):
     return SparseMatrix(self.nF, self.nF,
                         {k: v
                          for k, v in self.C2F.dic.items()})
Esempio n. 14
0
 def eye(n):
     tmp = SparseMatrix(n,n,lambda i,j:0)
     for i in range(tmp.rows):
         tmp[i,i] = 1
     return tmp
Esempio n. 15
0
def banded(*args, **kwargs):
    """Returns a SparseMatrix from the given dictionary describing
    the diagonals of the matrix. The keys are positive for upper
    diagonals and negative for those below the main diagonal. The
    values may be:
        * expressions or single-argument functions,
        * lists or tuples of values,
        * matrices
    Unless dimensions are given, the size of the returned matrix will
    be large enough to contain the largest non-zero value provided.

    kwargs
    ======

    rows : rows of the resulting matrix; computed if
           not given.

    cols : columns of the resulting matrix; computed if
           not given.

    Examples
    ========

    >>> from sympy import banded, ones, Matrix
    >>> from sympy.abc import x

    If explicit values are given in tuples,
    the matrix will autosize to contain all values, otherwise
    a single value is filled onto the entire diagonal:

    >>> banded({1: (1, 2, 3), -1: (4, 5, 6), 0: x})
    Matrix([
    [x, 1, 0, 0],
    [4, x, 2, 0],
    [0, 5, x, 3],
    [0, 0, 6, x]])

    A function accepting a single argument can be used to fill the
    diagonal as a function of diagonal index (which starts at 0).
    The size (or shape) of the matrix must be given to obtain more
    than a 1x1 matrix:

    >>> s = lambda d: (1 + d)**2
    >>> banded(5, {0: s, 2: s, -2: 2})
    Matrix([
    [1, 0, 1,  0,  0],
    [0, 4, 0,  4,  0],
    [2, 0, 9,  0,  9],
    [0, 2, 0, 16,  0],
    [0, 0, 2,  0, 25]])

    The diagonal of matrices placed on a diagonal will coincide
    with the indicated diagonal:

    >>> vert = Matrix([1, 2, 3])
    >>> banded({0: vert}, cols=3)
    Matrix([
    [1, 0, 0],
    [2, 1, 0],
    [3, 2, 1],
    [0, 3, 2],
    [0, 0, 3]])

    >>> banded(4, {0: ones(2)})
    Matrix([
    [1, 1, 0, 0],
    [1, 1, 0, 0],
    [0, 0, 1, 1],
    [0, 0, 1, 1]])

    Errors are raised if the designated size will not hold
    all values an integral number of times. Here, the rows
    are designated as odd (but an even number is required to
    hold the off-diagonal 2x2 ones):

    >>> banded({0: 2, 1: ones(2)}, rows=5)
    Traceback (most recent call last):
    ...
    ValueError:
    sequence does not fit an integral number of times in the matrix

    And here, an even number of rows is given...but the square
    matrix has an even number of columns, too. As we saw
    in the previous example, an odd number is required:

    >>> banded(4, {0: 2, 1: ones(2)})  # trying to make 4x4 and cols must be odd
    Traceback (most recent call last):
    ...
    ValueError:
    sequence does not fit an integral number of times in the matrix

    A way around having to count rows is to enclosing matrix elements
    in a tuple and indicate the desired number of them to the right:

    >>> banded({0: 2, 2: (ones(2),)*3})
    Matrix([
    [2, 0, 1, 1, 0, 0, 0, 0],
    [0, 2, 1, 1, 0, 0, 0, 0],
    [0, 0, 2, 0, 1, 1, 0, 0],
    [0, 0, 0, 2, 1, 1, 0, 0],
    [0, 0, 0, 0, 2, 0, 1, 1],
    [0, 0, 0, 0, 0, 2, 1, 1]])

    An error will be raised if more than one value
    is written to a given entry. Here, the ones overlap
    with the main diagonal if they are placed on the
    first diagonal:

    >>> banded({0: (2,)*5, 1: (ones(2),)*3})
    Traceback (most recent call last):
    ...
    ValueError: collision at (1, 1)

    By placing a 0 at the bottom left of the 2x2 matrix of
    ones, the collision is avoided:

    >>> u2 = Matrix([
    ... [1, 1],
    ... [0, 1]])
    >>> banded({0: [2]*5, 1: [u2]*3})
    Matrix([
    [2, 1, 1, 0, 0, 0, 0],
    [0, 2, 1, 0, 0, 0, 0],
    [0, 0, 2, 1, 1, 0, 0],
    [0, 0, 0, 2, 1, 0, 0],
    [0, 0, 0, 0, 2, 1, 1],
    [0, 0, 0, 0, 0, 0, 1]])
    """
    from sympy import Dict, Dummy, SparseMatrix
    try:
        if len(args) not in (1, 2, 3):
            raise TypeError
        if not isinstance(args[-1], (dict, Dict)):
            raise TypeError
        if len(args) == 1:
            rows = kwargs.get('rows', None)
            cols = kwargs.get('cols', None)
            if rows is not None:
                rows = as_int(rows)
            if cols is not None:
                cols = as_int(cols)
        elif len(args) == 2:
            rows = cols = as_int(args[0])
        else:
            rows, cols = map(as_int, args[:2])
        # fails with ValueError if any keys are not ints
        _ = all(as_int(k) for k in args[-1])
    except (ValueError, TypeError):
        raise TypeError(
            filldedent('''unrecognized input to banded:
            expecting [[row,] col,] {int: value}'''))

    def rc(d):
        # return row,col coord of diagonal start
        r = -d if d < 0 else 0
        c = 0 if r else d
        return r, c

    smat = {}
    undone = []
    tba = Dummy()
    # first handle objects with size
    for d, v in args[-1].items():
        r, c = rc(d)
        # note: only list and tuple are recognized since this
        # will allow other Basic objects like Tuple
        # into the matrix if so desired
        if isinstance(v, (list, tuple)):
            extra = 0
            for i, vi in enumerate(v):
                i += extra
                if is_sequence(vi):
                    vi = SparseMatrix(vi)
                    smat[r + i, c + i] = vi
                    extra += min(vi.shape) - 1
                else:
                    smat[r + i, c + i] = vi
        elif is_sequence(v):
            v = SparseMatrix(v)
            rv, cv = v.shape
            if rows and cols:
                nr, xr = divmod(rows - r, rv)
                nc, xc = divmod(cols - c, cv)
                x = xr or xc
                do = min(nr, nc)
            elif rows:
                do, x = divmod(rows - r, rv)
            elif cols:
                do, x = divmod(cols - c, cv)
            else:
                do = 1
                x = 0
            if x:
                raise ValueError(
                    filldedent('''
                    sequence does not fit an integral number of times
                    in the matrix'''))
            j = min(v.shape)
            for i in range(do):
                smat[r, c] = v
                r += j
                c += j
        elif v:
            smat[r, c] = tba
            undone.append((d, v))
    s = SparseMatrix(None, smat)  # to expand matrices
    smat = s._smat
    # check for dim errors here
    if rows is not None and rows < s.rows:
        raise ValueError('Designated rows %s < needed %s' % (rows, s.rows))
    if cols is not None and cols < s.cols:
        raise ValueError('Designated cols %s < needed %s' % (cols, s.cols))
    if rows is cols is None:
        rows = s.rows
        cols = s.cols
    elif rows is not None and cols is None:
        cols = max(rows, s.cols)
    elif cols is not None and rows is None:
        rows = max(cols, s.rows)

    def update(i, j, v):
        # update smat and make sure there are
        # no collisions
        if v:
            if (i, j) in smat and smat[i, j] not in (tba, v):
                raise ValueError('collision at %s' % ((i, j), ))
            smat[i, j] = v

    if undone:
        for d, vi in undone:
            r, c = rc(d)
            v = vi if callable(vi) else lambda _: vi
            i = 0
            while r + i < rows and c + i < cols:
                update(r + i, c + i, v(i))
                i += 1
    return SparseMatrix(rows, cols, smat)
Esempio n. 16
0
 def ytmat(self, a):
     return SparseMatrix(
         self.nF, self.nF,
         {k[1:]: v
          for k, v in self.yt.dic.items() if k[0] == a})
Esempio n. 17
0
 def Gmat(self):
     return SparseMatrix(
         self.nGi, self.nGi,
         {(self.gi.index(i), self.gi.index(j)): self.G_(i, j)
          for i in self.gi for j in self.gi})
Esempio n. 18
0
def test_as_immutable():
    X = Matrix([[1, 2], [3, 4]])
    assert sympify(X) == X.as_immutable() == ImmutableMatrix([[1, 2], [3, 4]])
    X = SparseMatrix(5, 5, {})
    assert sympify(X) == X.as_immutable() == ImmutableSparseMatrix(
        [[0 for i in range(5)] for i in range(5)])
Esempio n. 19
0
    def constructMapping(self, RGmodule):
        loggingInfo("Mapping the model onto the general Lagrangian ...")

        #Gauge couplings mapping, taking into account possible kinetic mixing
        noMix = {}
        mix = {}
        alreadyTaken = set()

        for el in itertools.combinations_with_replacement(
                range(RGmodule.nGi), 2):
            A, B = [RGmodule.gi[i] for i in el]
            c = RGmodule.G_(A, B)
            if c != 0 and c not in alreadyTaken:
                dic = noMix if A == B else mix

                if not self.upper:
                    A, B = B, A

                dic[(A, B)] = len(dic)
                alreadyTaken.add(c)

        newInds = {**noMix, **{k: v + len(noMix) for k, v in mix.items()}}
        gaugeMatrix = zeros(len(newInds))

        def delta(A, B):
            if A == B:
                return 1
            return 0

        def G(A, B):
            if RGmodule.G_(A, B) == 0:
                return 0
            if not self.kinMix or A not in RGmodule.Ugauge or B not in RGmodule.Ugauge:
                return sqrt(RGmodule.G_(A, B)).args[0]

            i, j = RGmodule.Ugauge.index(A), RGmodule.Ugauge.index(B)
            return self.kinMat[i, j]

        for (A, B), X in newInds.items():
            for (C, D), Y in newInds.items():
                gaugeMatrix[X,
                            Y] = G(B, D) * delta(A, C) + G(A, D) * delta(B, C)

        gaugeMatrix = simplify(gaugeMatrix.inv())

        couplingType = 'GaugeCouplings'
        self.potential[couplingType] = {}
        for c in self.gaugeCouplings:
            self.potential[couplingType][c] = 0

        self.lagrangianMapping[couplingType] = gaugeMatrix * self.betaFactor
        self.toCalculate[couplingType] = list(newInds.keys())

        count = 0
        translation = self.translateDic(RGmodule)
        for couplingType in self.potential:
            if couplingType == 'Definitions':
                continue
            if (couplingType in translation
                    and self.potential[couplingType] != {}
                    and translation[couplingType] != {}):
                coeffList = []
                dicList = []
                mappingMatrix = []
                sortedList = []

                coeffList = [c for c in self.potential[couplingType].keys()]

                mappingMatrix = SparseMatrix(len(coeffList), len(coeffList), 0)
                sortedList = sorted(
                    [(key, val)
                     for key, val in translation[couplingType].items()
                     if not (type(key[-1]) == bool and key[-1] == True)],
                    key=lambda x:
                    (len(set(x[0])), len(x[1].as_coeff_add()[1]), x[0]))

                trys = 0
                for el in sortedList:
                    trys += 1
                    matTry = self.fillMappingMatrix(mappingMatrix, coeffList,
                                                    el)
                    if (matTry.rank() > mappingMatrix.rank()):
                        mappingMatrix = matTry
                        dicList.append(el[0])

                        count += 1
                        print_progress(count,
                                       self.nCouplings,
                                       prefix=' ' * 4,
                                       bar_length=20,
                                       printTime=self.times,
                                       logProgress=True)

                    if matTry.rank() == len(coeffList):
                        break

                try:
                    self.lagrangianMapping[couplingType] = Matrix(
                        mappingMatrix).inv() * self.betaFactor
                except:
                    # from sympy import pretty
                    loggingCritical(
                        "\nError in Lagrangian mapping : matrix of couplings is not invertible."
                    )
                    loggingCritical("\tCoupling type : " + couplingType)
                    # loggingCritical("\t\t" + pretty(mappingMatrix).replace("\n", "\n\t\t"))
                    exit()

                self.toCalculate[couplingType] = dicList

        # Add vevs and anomalous dimensions by hand (not related to the Lagrangian)
        if self.vevs != {}:
            couplingType = 'Vevs'

            self.potential[couplingType] = {}
            for c in self.vevs:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(len(
                self.vevs)) * self.betaFactor
            self.toCalculate[couplingType] = list(RGmodule.Vdic.keys())

        if self.fermionAnomalous != {}:
            couplingType = 'FermionAnomalous'

            self.potential[couplingType] = {}
            for c in self.fermionAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.fermionAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaFdic.keys())

        if self.scalarAnomalous != {}:
            couplingType = 'ScalarAnomalous'

            self.potential[couplingType] = {}
            for c in self.scalarAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.scalarAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaSdic.keys())
Esempio n. 20
0
    def constructMapping(self, RGmodule):
        loggingInfo("Mapping the model onto the general Lagrangian ...")

        #Gauge couplings mapping, taking into account possible kinetic mixing
        noMix = {}
        mix = {}
        alreadyTaken = set()

        for el in itertools.combinations_with_replacement(
                range(RGmodule.nGi), 2):
            A, B = [RGmodule.gi[i] for i in el]
            c = RGmodule.G_(A, B)
            if c != 0 and c not in alreadyTaken:
                dic = noMix if A == B else mix

                if not self.upper:
                    A, B = B, A

                dic[(A, B)] = len(dic)
                alreadyTaken.add(c)

        newInds = {**noMix, **{k: v + len(noMix) for k, v in mix.items()}}
        gaugeMatrix = zeros(len(newInds))

        def delta(A, B):
            if A == B:
                return 1
            return 0

        def G(A, B):
            if RGmodule.G_(A, B) == 0:
                return 0
            if not self.kinMix or A not in RGmodule.Ugauge or B not in RGmodule.Ugauge:
                return sqrt(RGmodule.G_(A, B)).args[0]

            i, j = RGmodule.Ugauge.index(A), RGmodule.Ugauge.index(B)
            return self.kinMat[i, j]

        for (A, B), X in newInds.items():
            for (C, D), Y in newInds.items():
                gaugeMatrix[X,
                            Y] = G(B, D) * delta(A, C) + G(A, D) * delta(B, C)

        gaugeMatrix = simplify(gaugeMatrix.inv())

        couplingType = 'GaugeCouplings'
        self.potential[couplingType] = {}
        for c in self.gaugeCouplings:
            self.potential[couplingType][c] = 0

        self.lagrangianMapping[couplingType] = gaugeMatrix * self.betaFactor
        self.toCalculate[couplingType] = list(newInds.keys())

        count = 0
        translation = self.translateDic(RGmodule)
        for couplingType in self.potential:
            if couplingType == 'Definitions':
                continue
            if (couplingType in translation
                    and self.potential[couplingType] != {}
                    and translation[couplingType] != {}):
                coeffList = [c for c in self.potential[couplingType].keys()]
                mappingMatrix = SparseMatrix(len(coeffList), len(coeffList), 0)
                dicList = []

                auxDic = {}
                sortFunc = lambda x: (len(set(x[0])),
                                      len(x[1].as_coeff_add()[1]), x[0])

                for key, val in translation[couplingType].items():
                    if key[-1] is True:
                        continue
                    if val not in auxDic:
                        auxDic[val] = key
                    elif sortFunc((key, val)) < sortFunc((auxDic[val], val)):
                        auxDic[val] = key

                rank = 0
                for v, k in auxDic.items():
                    matTry = self.fillMappingMatrix(mappingMatrix, rank,
                                                    coeffList, (k, v))
                    newRank = matTry.rank()
                    if (newRank > rank):
                        mappingMatrix = matTry
                        rank = newRank
                        dicList.append(k)

                        count += 1
                        print_progress(count,
                                       self.nCouplings,
                                       prefix=' ' * 4,
                                       bar_length=20,
                                       printTime=self.times,
                                       logProgress=True)

                    if newRank == len(coeffList):
                        self.lagrangianMapping[couplingType] = Matrix(
                            mappingMatrix).inv() * self.betaFactor
                        break
                else:
                    # The mapping matrix is not invertible
                    ns = mappingMatrix.nullspace()
                    cVec = Matrix([
                        Symbol('O(' + el + ')') for el in coeffList
                    ]).transpose()

                    errorMess = "\n\nError in Lagrangian mapping: matrix of couplings is not invertible. "
                    errorMess += f"The following operators in '{couplingType}' are linearly dependent:\n\n"
                    for vec in ns:
                        errorMess += f"  {(cVec*vec)[0,0]} = 0\n"
                    loggingCritical(errorMess[:-1])
                    exit()

                self.toCalculate[couplingType] = dicList

        # Add vevs and anomalous dimensions by hand (not related to the Lagrangian)
        if self.vevs != {}:
            couplingType = 'Vevs'

            self.potential[couplingType] = {}
            for c in self.vevs:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(len(
                self.vevs)) * self.betaFactor
            self.toCalculate[couplingType] = list(RGmodule.Vdic.keys())

        if self.fermionAnomalous != {}:
            couplingType = 'FermionAnomalous'

            self.potential[couplingType] = {}
            for c in self.fermionAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.fermionAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaFdic.keys())

        if self.scalarAnomalous != {}:
            couplingType = 'ScalarAnomalous'

            self.potential[couplingType] = {}
            for c in self.scalarAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.scalarAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaSdic.keys())
Esempio n. 21
0
def test_SparseMatrix():
    M = SparseMatrix([[x**+1, 1], [y, x + y]])
    assert str(M) == sstr(M) == "[x,     1]\n[y, x + y]"
Esempio n. 22
0
def test_im():
    x, y = symbols('x,y')
    a, b = symbols('a,b', real=True)

    r = Symbol('r', real=True)
    i = Symbol('i', imaginary=True)

    assert im(nan) == nan

    assert im(oo * I) == oo
    assert im(-oo * I) == -oo

    assert im(0) == 0

    assert im(1) == 0
    assert im(-1) == 0

    assert im(E * I) == E
    assert im(-E * I) == -E

    assert unchanged(im, x)
    assert im(x * I) == re(x)
    assert im(r * I) == r
    assert im(r) == 0
    assert im(i * I) == 0
    assert im(i) == -I * i

    assert im(x + y) == im(x + y)
    assert im(x + r) == im(x)
    assert im(x + r * I) == im(x) + r

    assert im(im(x) * I) == im(x)

    assert im(2 + I) == 1
    assert im(x + I) == im(x) + 1

    assert im(x + y * I) == im(x) + re(y)
    assert im(x + r * I) == im(x) + r

    assert im(log(2 * I)) == pi / 2

    assert im((2 + I)**2).expand(complex=True) == 4

    assert im(conjugate(x)) == -im(x)
    assert conjugate(im(x)) == im(x)

    assert im(x).as_real_imag() == (im(x), 0)

    assert im(i * r * x).diff(r) == im(i * x)
    assert im(i * r * x).diff(i) == -I * re(r * x)

    assert im(
        sqrt(a +
             b * I)) == (a**2 + b**2)**Rational(1, 4) * sin(atan2(b, a) / 2)
    assert im(a * (2 + b * I)) == a * b

    assert im((1 + sqrt(a + b*I))/2) == \
        (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2)/2

    assert im(x).rewrite(re) == -S.ImaginaryUnit * (x - re(x))
    assert (x + im(y)).rewrite(im, re) == x - S.ImaginaryUnit * (y - re(y))

    a = Symbol('a', algebraic=True)
    t = Symbol('t', transcendental=True)
    x = Symbol('x')
    assert re(a).is_algebraic
    assert re(x).is_algebraic is None
    assert re(t).is_algebraic is False

    assert im(S.ComplexInfinity) == S.NaN

    n, m, l = symbols('n m l')
    A = MatrixSymbol('A', n, m)

    assert im(A) == (S(1) / (2 * I)) * (A - conjugate(A))

    A = Matrix([[1 + 4 * I, 2], [0, -3 * I]])
    assert im(A) == Matrix([[4, 0], [0, -3]])

    A = ImmutableMatrix([[1 + 3 * I, 3 - 2 * I], [0, 2 * I]])
    assert im(A) == ImmutableMatrix([[3, -2], [0, 2]])

    X = ImmutableSparseMatrix([[i * I + i for i in range(5)]
                               for i in range(5)])
    Y = SparseMatrix([[i for i in range(5)] for i in range(5)])
    assert im(X).as_immutable() == Y

    X = FunctionMatrix(3, 3, Lambda((n, m), n + m * I))
    assert im(X) == Matrix([[0, 1, 2], [0, 1, 2], [0, 1, 2]])
Esempio n. 23
0
 def zeros(n):
     return SparseMatrix(n,n,lambda i,j:0)
Esempio n. 24
0
    def matrices(self):
        '''
        Returns the representation matrices in an orthonormal basis.

        The return value is a dictionary. The key represents the generators
        and the value is a matrix.

        The key may be an integer or a tuple. If it is an integer i, it
        denotes the ith Cartan generator. If it is a tuple, it denotes
        the root given by that tuple (in the q-p notation).
        '''

        cartan_matrix = self.lie_group.cartan_matrix()
        states = self.states()
        representation_dimension = self.dimension()

        representation_matrices = {}

        # calculate representation matrices for simple roots

        for i in range(self.lie_group.dimension):
            simple_root_i_nonzero = {}
            for level in states:
                for weight in states[level]:
                    states_for_this_weight = states[level][weight]["states"]
                    for state in states_for_this_weight:
                        state_index1 = state["index"]
                        matrix_element_information = state[
                            "matrix_element_information"]
                        for entry in matrix_element_information:
                            if entry["direction"] == i:
                                parent_state = states[entry["level"]][
                                    entry["weight"]]["states"][
                                        entry["state_num"]]
                                state_index2 = parent_state["index"]
                                simple_root_i_nonzero[(
                                    state_index2, state_index1)] = (
                                        entry["matrix_element"])
            simple_root_i_matrix = SparseMatrix(representation_dimension,
                                                representation_dimension,
                                                simple_root_i_nonzero)
            representation_matrices[tuple(
                self.lie_group.simple_root_pq(i, cartan_matrix))] = (
                    simple_root_i_matrix)

        # convert to orthonormal basis

        rotation_to_ob_nonzero = {}
        for level in states:
            for weight in states[level]:
                rotation_matrix = states[level][weight]["rotation_to_ob"]
                start_index = states[level][weight]["start_index"]
                end_index = states[level][weight]["end_index"]
                rotation_matrix_nonzero = dict(
                    [((i,j),rotation_matrix[i-start_index, j-start_index]) for
                    i in range(start_index, end_index+1) for
                    j in range(start_index, end_index+1)]
                    )
                rotation_to_ob_nonzero.update(rotation_matrix_nonzero)

        rotation_to_ob = SparseMatrix(representation_dimension,
                                      representation_dimension,
                                      rotation_to_ob_nonzero)

        for key in representation_matrices:
            rotated_matrix = rotation_to_ob.multiply(
                representation_matrices[key].multiply(rotation_to_ob.T))
            rotated_matrix.simplify()
            representation_matrices[key] = rotated_matrix

        # calculate representation matrices for cartan generators

        fundamental_weights = self.lie_group.fundamental_weights()

        cartan_matrices_nonzero = [{} for i in range(
            self.lie_group.dimension)]
        for level in states:
            for weight in states[level]:
                weight_vector = [sum([weight[i]*fundamental_weights[i][j]
                    for i in range(self.lie_group.dimension)])
                    for j in range(self.lie_group.dimension)]
                states_for_this_weight = states[level][weight]["states"]
                for state in states_for_this_weight:
                    state_index = state["index"]
                    for i in range(self.lie_group.dimension):
                        cartan_matrices_nonzero[i][(state_index,
                            state_index)] = weight_vector[i]

        for i in range(self.lie_group.dimension):
            representation_matrices[i] = SparseMatrix(representation_dimension,
                representation_dimension, cartan_matrices_nonzero[i])

        # calculate representation matrices for other positive roots

        positive_roots = self.lie_group.positive_roots()[0]
        positive_roots_list = [(key,) +  positive_roots[key]
                               for key in positive_roots
                               if isinstance(positive_roots[key][1],list)]
        positive_roots_list = sorted(positive_roots_list,
                                     key = lambda item : item[3])

        for i in range(len(positive_roots_list)):
                matrix1 = representation_matrices[positive_roots_list[i][2][0]]
                matrix2 = representation_matrices[positive_roots_list[i][2][1]]
                positive_root_matrix = matrix1.multiply(matrix2).add(
                    - matrix2.multiply(matrix1))
                factor = positive_roots_list[i][1]
                root = positive_roots_list[i][0]

                # sympy cannot multiply a Pow object and a SparseMatrix object
                # to produce a SparseMatrix object. It produces a Mul object
                # instead. That's why factor*positive_root_matrix doesn't work.

                representation_matrices[root] =  positive_root_matrix.applyfunc(
                    lambda i : factor*i)

        # generate matrices for negative roots

        keys = list(representation_matrices.keys())

        for key in keys:
            if isinstance(key,tuple):
                new_key = tuple([-i for i in key])
                representation_matrices[new_key] = (
                    representation_matrices[key].T)

        return representation_matrices
Esempio n. 25
0
 def __new__(self, *args, **kwargs):
     """ sMat(i,j) returns an empty i x j matrix (i.e. SparseMatrix(i,j,{})"""
     if len(args) == 2:
         return SparseMatrix.__new__(self, *args, {})
     return SparseMatrix.__new__(self, *args, **kwargs)
Esempio n. 26
0
 def S2Smat(self):
     return SparseMatrix(
         self.nGi, self.nGi, {(self.gi.index(k[0]), self.gi.index(k[1])): v
                              for k, v in self.S2S.dic.items()})
Esempio n. 27
0
 def Y2Ftmat(self):
     return SparseMatrix(self.nF, self.nF,
                         {k: v
                          for k, v in self.Y2Ft.dic.items()})
Esempio n. 28
0
CD = Matrix(
    S('''[
    [             -3/4,       45/32 - 37*I/16,                   0,                     0],
    [-149/64 + 49*I/32, -177/128 - 1369*I/128,                   0, -2063/256 + 541*I/128],
    [                0,         9/4 + 55*I/16, 2473/256 + 137*I/64,                     0],
    [                0,                     0,                   0, -177/128 - 1369*I/128]]'''
      ))
DD = Matrix(
    S('''[
    [             -3/4,       45/32 - 37*I/16,                   0,                     0],
    [-149/64 + 49*z/32, -177/128 - 1369*I/128,                   0,  541*y/128 - 2063/256],
    [                0,         9/4 + 55*I/16, 137*z/64 + 2473/256,                     0],
    [                0,                     0,                   0, -1369*x/128 - 177/128]]'''
      ))

ADS = SparseMatrix(AD)
BDS = SparseMatrix(BD)
CDS = SparseMatrix(CD)
DDS = SparseMatrix(DD)

O4 = Matrix(4, 1, [1, 1, 1, 1])


class TimePow4:
    def time_A(self):
        A**4

    def time_B(self):
        B**4

    def time_C(self):
Esempio n. 29
0
def test_SparseMatrix():
    M = SparseMatrix([[x**+1, 1], [y, x + y]])
    assert str(M) == "Matrix([[x, 1], [y, x + y]])"
    assert sstr(M) == "Matrix([\n[x,     1],\n[y, x + y]])"
Esempio n. 30
0
 def Y2Smat(self):
     return SparseMatrix(self.nS, self.nS,
                         {k: v
                          for k, v in self.Y2S.dic.items()})
Esempio n. 31
0
def test_re():
    x, y = symbols('x,y')
    a, b = symbols('a,b', real=True)

    r = Symbol('r', real=True)
    i = Symbol('i', imaginary=True)

    assert re(nan) == nan

    assert re(oo) == oo
    assert re(-oo) == -oo

    assert re(0) == 0

    assert re(1) == 1
    assert re(-1) == -1

    assert re(E) == E
    assert re(-E) == -E

    assert unchanged(re, x)
    assert re(x * I) == -im(x)
    assert re(r * I) == 0
    assert re(r) == r
    assert re(i * I) == I * i
    assert re(i) == 0

    assert re(x + y) == re(x + y)
    assert re(x + r) == re(x) + r

    assert re(re(x)) == re(x)

    assert re(2 + I) == 2
    assert re(x + I) == re(x)

    assert re(x + y * I) == re(x) - im(y)
    assert re(x + r * I) == re(x)

    assert re(log(2 * I)) == log(2)

    assert re((2 + I)**2).expand(complex=True) == 3

    assert re(conjugate(x)) == re(x)
    assert conjugate(re(x)) == re(x)

    assert re(x).as_real_imag() == (re(x), 0)

    assert re(i * r * x).diff(r) == re(i * x)
    assert re(i * r * x).diff(i) == I * r * im(x)

    assert re(
        sqrt(a +
             b * I)) == (a**2 + b**2)**Rational(1, 4) * cos(atan2(b, a) / 2)
    assert re(a * (2 + b * I)) == 2 * a

    assert re((1 + sqrt(a + b*I))/2) == \
        (a**2 + b**2)**Rational(1, 4)*cos(atan2(b, a)/2)/2 + Rational(1, 2)

    assert re(x).rewrite(im) == x - S.ImaginaryUnit * im(x)
    assert (x + re(y)).rewrite(re, im) == x + y - S.ImaginaryUnit * im(y)

    a = Symbol('a', algebraic=True)
    t = Symbol('t', transcendental=True)
    x = Symbol('x')
    assert re(a).is_algebraic
    assert re(x).is_algebraic is None
    assert re(t).is_algebraic is False

    assert re(S.ComplexInfinity) == S.NaN

    n, m, l = symbols('n m l')
    A = MatrixSymbol('A', n, m)
    assert re(A) == (S(1) / 2) * (A + conjugate(A))

    A = Matrix([[1 + 4 * I, 2], [0, -3 * I]])
    assert re(A) == Matrix([[1, 2], [0, 0]])

    A = ImmutableMatrix([[1 + 3 * I, 3 - 2 * I], [0, 2 * I]])
    assert re(A) == ImmutableMatrix([[1, 3], [0, 0]])

    X = SparseMatrix([[2 * j + i * I for i in range(5)] for j in range(5)])
    assert re(X) - Matrix([[0, 0, 0, 0, 0], [2, 2, 2, 2, 2], [4, 4, 4, 4, 4],
                           [6, 6, 6, 6, 6], [8, 8, 8, 8, 8]
                           ]) == Matrix.zeros(5)

    assert im(X) - Matrix([[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4],
                           [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]
                           ]) == Matrix.zeros(5)

    X = FunctionMatrix(3, 3, Lambda((n, m), n + m * I))
    assert re(X) == Matrix([[0, 0, 0], [1, 1, 1], [2, 2, 2]])
Esempio n. 32
0
 def Tsmat(self, A):
     return SparseMatrix(
         self.nS, self.nS,
         {k[1:]: v
          for k, v in self.Ts.dic.items() if k[0] == A})