예제 #1
0
 def _fit_patches(self, X, y):
     self._check_params(X)
     num_samples, _, _, _, _, _, _ = self._get_dims()
     S = self._create_s_matrix(X)
     R = self._create_r_matrix()
     print("Solving the ridge problem...", end='')
     if self.solver == "primal":
         c = np.linalg.lstsq(
             S.T @ S + num_samples *
             (self.lbd * R + self.mu * np.eye(S.shape[1])),
             S.T @ y,
             rcond=None,
         )[0]
     elif self.solver == "dual":
         if self.lbd == 0:
             c = (S.T @ np.linalg.inv(S @ S.T + num_samples * self.mu *
                                      np.eye(S.shape[0])) @ y)
         else:
             B = num_samples * (
                 self.mu * sparse.eye(S.shape[1], format="csc") +
                 self.lbd * R)
             B_inv = sparse_inv(B)
             c = (B_inv @ S.T
                  @ np.linalg.inv(S @ B_inv @ S.T + np.eye(S.shape[0])) @ y)
     else:
         raise ValueError(
             f"solver must be 'primal' or 'dual', got '{self.solver}'")
     print(" OK.")
     self._R, self._S, self._spline_coef = R, S, c
예제 #2
0
파일: gf_sparse.py 프로젝트: suan12/NEGF
 def cal_surface_gf(self, E, order=2, delta=0.000001, epsilon=0.000001):
     I = sparse_eye(self.size).tocsc()
     if order == 1:
         ws = (E + 1j * delta) * I - self.D00
         wb = (E + 1j * delta) * I - self.D11
     else:
         ws = ((E + 1j * delta)**2) * I - self.D00
         wb = ((E + 1j * delta)**2) * I - self.D11
     tau1 = self.D01
     tau2 = tau1.H
     while abs(tau1).max() > epsilon:
         wb_I = sparse_inv(wb)
         ws = ws - tau1 * wb_I * tau2
         wb = wb - tau1 * wb_I * tau2 - tau2 * wb_I * tau1
         tau1 = tau1 * wb_I * tau1
         tau2 = tau2 * wb_I * tau2
     self.gf = sparse_inv(ws)
예제 #3
0
파일: gf_sparse.py 프로젝트: pfliu8903/NEGF
 def cal_surface_gf(self, E, order=2, delta=0.000001, epsilon=0.000001):
     I = sparse_eye(self.size).tocsc()
     if order == 1:
         ws = (E + 1j*delta)*I - self.D00
         wb = (E + 1j*delta)*I - self.D11
     else:
         ws = ((E + 1j*delta)**2)*I - self.D00
         wb = ((E + 1j*delta)**2)*I - self.D11
     tau1 = self.D01
     tau2 = tau1.H
     while abs(tau1).max() > epsilon:
         wb_I = sparse_inv(wb)
         ws = ws - tau1*wb_I*tau2
         wb = wb - tau1*wb_I*tau2 - tau2*wb_I*tau1
         tau1 = tau1*wb_I*tau1
         tau2 = tau2*wb_I*tau2
     self.gf= sparse_inv(ws)
예제 #4
0
파일: gf_sparse.py 프로젝트: pfliu8903/NEGF
    def cal_diag_gf(self):
        """
        calculate diagonal green's function for center area.
        """
        length = self.length
        g = self.g
        # forward iterating
        g[0] = sparse_inv(self.M(0, 0))
        for j in range(1, length):
            g[j] = sparse_inv(self.M(j, j) -
                    self.M(j, j-1)*g[j-1]*self.M(j-1, j))

        G = self.gf
        G[self.length - 1][self.length - 1] = g[self.length - 1]
        # calculate more green's function according to the flag
        # backward iterating
        for j in list(range(self.length - 1))[::-1]:
            G[j][j] = g[j] + g[j]*self.M(j, j+1)*G[j+1][j+1]*self.M(j+1, j)*g[j]
예제 #5
0
파일: gf_sparse.py 프로젝트: suan12/NEGF
    def cal_diag_gf(self):
        """
        calculate diagonal green's function for center area.
        """
        length = self.length
        g = self.g
        # forward iterating
        g[0] = sparse_inv(self.M(0, 0))
        for j in range(1, length):
            g[j] = sparse_inv(
                self.M(j, j) - self.M(j, j - 1) * g[j - 1] * self.M(j - 1, j))

        G = self.gf
        G[self.length - 1][self.length - 1] = g[self.length - 1]
        # calculate more green's function according to the flag
        # backward iterating
        for j in list(range(self.length - 1))[::-1]:
            G[j][j] = g[j] + g[j] * self.M(
                j, j + 1) * G[j + 1][j + 1] * self.M(j + 1, j) * g[j]
예제 #6
0
def LBOAproximation(v, f, scalar_function, k, cls='half_cotangent'):

    eig_vals, eig_vects = laplacian_spectrum(v, f, k, cls)
    M = barycenter_vertex_mass_matrix(v, f)
    L = Laplacian(v, f, cls)

    scalar_function_hat = eig_vects @ eig_vects.T @ M @ scalar_function
    normlized_laplacian_scalarFunc = sparse_inv(
        csc_matrix(M)) @ L @ scalar_function

    return scalar_function_hat, normlized_laplacian_scalarFunc
예제 #7
0
def LaplacianDiscreteMeanCurveture(v, f, cls='half_cotangent', W=None):

    L = Laplacian(v, f, cls, W=W)
    M = barycenter_vertex_mass_matrix(v, f)
    Hn = sparse_inv(csc_matrix(M)) @ L @ v
    #Hn = sparse_inv(M) @ L @ v
    Hn_abs = np.linalg.norm(Hn, axis=1)

    #Get curveture sign by checking direction of curveture and the normal
    mesh = Mesh(v=v, f=f)
    normals = mesh.vertexNormals()
    Hn_normlized = Hn / Hn_abs.reshape((len(v), 1))
    Hn_signs = np.sign(np.diag(Hn_normlized @ normals.T))

    Hn_scalarFunc = Hn_abs * Hn_signs

    return Hn_scalarFunc
예제 #8
0
def solve_flows(
    net: nx.Graph,
    boundary_conditions: Dict[str, float],
    root: Union[List[str], str] = None,
    viscosity=1.,
):
    # root must be a list of nodes
    assert root is not None
    if isinstance(root, str):
        root = [root]
    # convert viscosity to (mmHg s) units
    _viscosity = viscosity * 1e-6 * 7.5006

    # define internal and external nodes
    internal_nodes = [node for node, k in net.degree if k > 1]
    external_nodes = [node for node, k in net.degree if k == 1]

    # index to label conversions for nodes
    nodes_idx2label = dict(enumerate(net.nodes))
    nodes_label2idx = {v: k for k, v in nodes_idx2label.items()}

    # sparse matrices to solve the linear algebra problem
    N = len(net.nodes)
    b = dok_matrix((N, 1))
    S = dok_matrix((N, N))

    # initial condition
    p = np.zeros(N)
    # set pressure of root
    for node, press in boundary_conditions.items():
        p[nodes_label2idx[node]] = press

    # fill in coefficients
    for u, v in net.edges:
        r = net[u][v]["radius"]
        length = net[u][v]["length"]
        cij = np.math.pi * (2 * r)**4 / (128 * _viscosity * length)
        i = nodes_label2idx[u]
        j = nodes_label2idx[v]
        if u in internal_nodes:
            S[i, i] += cij
            S[j, i] += -cij
        else:
            b[j] += cij * p[i]
        if v in internal_nodes:
            S[j, j] += cij
            S[i, j] += -cij
        else:
            b[i] += cij * p[j]
    bb = [x in internal_nodes for x in net.nodes]
    SS = csc_matrix(S.todense()[bb].T[bb].T)
    # solve the system
    # i.e. find pressure at each node
    SS_inv = sparse_inv(SS)
    sol = SS_inv.dot(csc_matrix(b.todense()[bb]))
    pressure_internal = dict(zip(internal_nodes, (sol.toarray().T[0])))
    pressure_external = dict(
        zip(external_nodes, p[[x in external_nodes for x in net.nodes]]))
    pressure_all_nodes = {**pressure_internal, **pressure_external}
    # fill in network with pressure and flows
    dinet = nx.DiGraph()
    dinet.add_nodes_from(net.nodes)
    # copy over node positions
    dd = nx.get_node_attributes(net, "position")
    nx.set_node_attributes(dinet, dd, "position")
    # write pressures dict
    nx.set_node_attributes(dinet, pressure_all_nodes, "pressure")

    edge_attrs = {}
    pressure_dict = nx.get_node_attributes(dinet, "pressure")
    for i, (u, v) in enumerate(net.edges):
        # get its properties
        pu = pressure_dict[u]
        pv = pressure_dict[v]
        r = net[u][v]["radius"]
        length = net[u][v]["length"]
        cij = np.math.pi * (2 * r)**4 / (128 * _viscosity * length)
        flow = cij * (pu - pv)
        if flow < 0:
            flow = -flow
            u, v = v, u
        speed = flow / (np.math.pi * r**2)
        time = length / speed
        # create the edge
        dinet.add_edge(u, v)
        # save properties in dict entry
        edge_attrs[(u, v)] = {
            "flow": flow,
            "speed": speed,
            "time": time,
            "radius": r,
            "length": length
        }
    nx.set_edge_attributes(dinet, edge_attrs)
    return dinet
예제 #9
0
    def solve_flows(self,
                    root: Union[List[str], str] = None,
                    viscosity=1.,
                    iterative_min_rad=1,
                    bin_s=0.3,
                    cc_idx=0,
                    force_root: bool = False):
        """
        Solve the flows problem.

        Parameters
        ----------
        root: str
            Label of root node in the format "FJ????_submesh?_node?".
        viscosity: float
            The viscosity of blood, relative to water = 1.
        iterative_min_rad: float
            In iterative solving mode, sets the radius below wich nodes'
            preassure is *not* updated iteratively.
        bin_s: float
            In iterative solving mode, radius tolerance to infer pressures.
        cc_idx: int
            Which connected compoent (from large to small) to use
        force_root: bool
            If passed source node is not a viable root, force it to be by
            adding a phantom node.
        """
        # root must be a list of nodes
        assert root is not None
        if isinstance(root, str):
            root = [root]
        # convert viscosity to (mmHg s) units
        self.viscosity = viscosity * 1e-6 * 7.5006
        # get largest connected component
        cc = nx.connected_component_subgraphs(self.network)
        sorted_cc = sorted(cc, key=len, reverse=True)
        net = sorted_cc[cc_idx]

        # if root has not degree 1, force it
        if force_root:
            _root = []
            for roo in root:
                if net.degree[roo] > 1:
                    sroo = "source_" + roo
                    net.add_node(sroo)
                    r = np.mean(
                        [net[roo][v]["radius"] for v in net.neighbors(roo)])
                    net.add_edge(sroo, roo, radius=r, length=1)
                    _root.append(sroo)
                else:
                    _root.append(roo, )
            root = _root
            self.fill_missing_radiuses()

        # define internal and external nodes
        internal_nodes = [node for node, k in net.degree if k > 1]
        external_nodes = [node for node, k in net.degree if k == 1]
        for roo in root:
            if roo not in external_nodes:
                raise RuntimeError(
                    f"Node {roo} was passed as source node but is not a leaf")

        # index to label conversions for nodes
        nodes_idx2label = dict(enumerate(net.nodes))
        nodes_label2idx = {v: k for k, v in nodes_idx2label.items()}

        # sparse matrices to solve the linear algebra problem
        N = len(net.nodes)
        b = dok_matrix((N, 1))
        S = dok_matrix((N, N))

        # initial condition
        p = np.zeros(N) + 20
        # set pressure of root
        for roo in root:
            p[nodes_label2idx[roo]] = 100
        # if not first iteration, guess boundary conditions
        if self.solved:
            # auxiliar df to infer pressures
            p_dict = nx.get_node_attributes(self.network_solved, "pressure")
            r_dict = nx.get_node_attributes(self.network, "radius")
            df = pd.DataFrame(data=[r_dict, p_dict],
                              index=["radius", "pressure"]).T.dropna()
            # set boundary conditions of external nodes except root
            for node in external_nodes:
                if node not in root:
                    i = nodes_label2idx[node]
                    target_r = df.loc[node, "radius"]
                    if target_r > iterative_min_rad:
                        inferred_p = infer_pressure(df=df,
                                                    target_r=target_r,
                                                    bin_s=bin_s)
                        p[i] = inferred_p

        # fill in coefficients
        for u, v in net.edges:
            r = net[u][v]["radius"]
            length = net[u][v]["length"]
            cij = np.math.pi * (2 * r)**4 / (128 * self.viscosity * length)
            i = nodes_label2idx[u]
            j = nodes_label2idx[v]
            if u in internal_nodes:
                S[i, i] += cij
                S[j, i] += -cij
            else:
                b[j] += cij * p[i]
            if v in internal_nodes:
                S[j, j] += cij
                S[i, j] += -cij
            else:
                b[i] += cij * p[j]
        bb = [x in internal_nodes for x in net.nodes]
        SS = csc_matrix(S.todense()[bb].T[bb].T)
        # solve the system
        # i.e. find pressure at each node
        SS_inv = sparse_inv(SS)
        sol = SS_inv.dot(csc_matrix(b.todense()[bb]))
        pressure_internal = dict(zip(internal_nodes, (sol.toarray().T[0])))
        pressure_external = dict(
            zip(external_nodes, p[[x in external_nodes for x in net.nodes]]))
        pressure_all_nodes = {**pressure_internal, **pressure_external}
        # fill in network with pressure and flows
        dinet = nx.DiGraph()
        dinet.add_nodes_from(net.nodes)
        # copy over node positions
        dd = nx.get_node_attributes(net, "position")
        nx.set_node_attributes(dinet, dd, "position")
        # write pressures dict
        nx.set_node_attributes(dinet, pressure_all_nodes, "pressure")
        # mark the system as solved
        self.solved = True

        edge_attrs = {}
        pressure_dict = nx.get_node_attributes(dinet, "pressure")
        for i, (u, v) in enumerate(net.edges):
            # get its properties
            pu = pressure_dict[u]
            pv = pressure_dict[v]
            r = net[u][v]["radius"]
            length = net[u][v]["length"]
            cij = np.math.pi * (2 * r)**4 / (128 * self.viscosity * length)
            flow = cij * (pu - pv)
            if flow < 0:
                flow = -flow
                u, v = v, u
            speed = flow / (np.math.pi * r**2)
            time = length / speed
            # create the edge
            dinet.add_edge(u, v)
            # save properties in dict entry
            edge_attrs[(u, v)] = {
                "flow": flow,
                "speed": speed,
                "time": time,
                "radius": r,
                "length": length
            }
        nx.set_edge_attributes(dinet, edge_attrs)
        self.network_solved = dinet
예제 #10
0
    def __call__(self,
                 fluxes,
                 concentrations,
                 parameters,
                 flux_jacobian=False):
        """
        :param fluxes: `Dict` or `pd.Series` of reference flux vector
        :param concentrations: `Dict` or `pd.Series` of reference concentration vector
        :param parameters: `Dict` or `pd.Series` of reference parameters vector
        """
        # TODO:
        # Attention the Fluxes and concentrations need to be sorted
        # according to the model!
        if self.volume_ratio_function is None:
            volume_ratios = array([
                1,
            ] * len(concentrations))
        else:
            volume_ratios = self.volume_ratio_function(parameters)

        #Calculate the Jacobian
        flux_matrix = diags(array(fluxes), 0).tocsc()

        # Elasticity matrix
        if self.conservation_relation.nnz == 0:

            volume_ratio_matrix_indep = diags(array(volume_ratios)).tocsc()

            concentration_matrix = diags(array(concentrations)).tocsc()
            inv_concentration_matrix = sparse_inv(concentration_matrix)
            elasticity_matrix = self.independent_elasticity_function(
                concentrations, parameters)
        else:
            # We need to get only the concentrations of the independent metabolites
            ix = self.independent_variable_ix
            volume_ratio_matrix_indep = diags(array(volume_ratios)[ix]).tocsc()
            inv_volume_ratio_matrix_indep = sparse_inv(
                volume_ratio_matrix_indep)
            ix_dep = self.dependent_variable_ix
            volume_ratio_matrix_dep = diags(
                array(volume_ratios)[ix_dep]).tocsc()

            concentration_matrix = diags(array(concentrations)[ix]).tocsc()
            inv_concentration_matrix = sparse_inv(concentration_matrix)

            elasticity_matrix = self.independent_elasticity_function(
                concentrations, parameters)

            dependent_weights = self.dependent_elasticity_function.\
                get_dependent_weights(
                                concentration_vector=concentrations,
                                L0=self.conservation_relation,
                                all_dependent_ix=self.dependent_variable_ix,
                                all_independent_ix=self.independent_variable_ix,
                                volume_ratios=volume_ratios
                            )

            elasticity_matrix += self.dependent_elasticity_function(concentrations, parameters)\
                                 .dot(dependent_weights)

        if flux_jacobian:
            jacobian = flux_matrix.dot(elasticity_matrix)\
                .dot(inv_concentration_matrix)\
                .dot(volume_ratio_matrix_indep)\
                .dot(self.reduced_stoichometry)

        else:
            jacobian = volume_ratio_matrix_indep.dot(self.reduced_stoichometry)\
                        .dot(flux_matrix)\
                        .dot(elasticity_matrix)\
                        .dot(inv_concentration_matrix)

        return jacobian
예제 #11
0
    def __call__(self, flux_dict, concentration_dict, parameter_population):

        # Calculate the Concentration Control coefficients
        # Log response of the concentration with respect to the log change in a Parameter
        #
        # C_Xi_P = -(N_r*V*E_i + N_r*V*E_d*Q_i)(N_r*V*Pi)
        #

        fluxes = [flux_dict[r] for r in self.model.reactions]

        # Only consider independent concentrations
        concentrations = [concentration_dict[r] for r in self.model.reactants]

        num_parameters = len(
            self.parameter_elasticity_function.respective_variables)
        num_concentration = len(self.independent_variable_ix)
        population_size = len(parameter_population)

        concentration_control_coefficients = zeros(
            (num_concentration, num_parameters, population_size))

        for i, parameters in enumerate(parameter_population):

            flux_matrix = diags(array(fluxes), 0).tocsc()

            if self.volume_ratio_function is None:
                volume_ratios = array([
                    1,
                ] * len(concentrations))
            else:
                volume_ratios = self.volume_ratio_function(parameters)

            # Elasticity matrix

            if self.conservation_relation.nnz == 0:
                # If there are no moieties
                volume_ratio_matrix = diags(array(volume_ratios)).tocsc()

                elasticity_matrix = self.independent_elasticity_function(
                    concentrations, parameters)

            else:
                # If there are moieties
                ix = self.independent_variable_ix

                volume_ratio_matrix = diags(array(volume_ratios)[ix]).tocsc()

                elasticity_matrix = self.independent_elasticity_function(
                    concentrations, parameters)

                dependent_weights = self.dependent_elasticity_function.\
                    get_dependent_weights(
                                    concentration_vector=concentrations,
                                    L0=self.conservation_relation,
                                    all_dependent_ix=self.dependent_variable_ix,
                                    all_independent_ix=self.independent_variable_ix,
                                    volume_ratios=volume_ratios
                                )

                # Calculate the effective elasticises
                elasticity_matrix += self.dependent_elasticity_function(concentrations, parameters)\
                                     .dot(dependent_weights)

            N_E_V = volume_ratio_matrix.dot(self.reduced_stoichometry).dot(
                flux_matrix).dot(elasticity_matrix)
            N_E_V_inv = sparse_inv(N_E_V)

            parameter_elasticity_matrix = self.parameter_elasticity_function(
                concentrations, parameters)

            N_E_P = volume_ratio_matrix.dot(self.reduced_stoichometry).dot(
                flux_matrix).dot(parameter_elasticity_matrix)

            this_cc = -N_E_V_inv.dot(N_E_P)
            concentration_control_coefficients[:, :, i] = this_cc.todense()

        concentration_index = pd.Index([
            self.model.reactants.iloc(i)[0]
            for i in self.independent_variable_ix
        ],
                                       name="concentration")
        parameter_index = pd.Index(
            self.parameter_elasticity_function.respective_variables,
            name="parameter")
        sample_index = pd.Index(range(population_size), name="sample")

        tensor_ccc = Tensor(
            concentration_control_coefficients,
            [concentration_index, parameter_index, sample_index])

        return tensor_ccc