Précalcul de property Python

a marqué ce sujet comme résolu.

Bonjour,

J’ai un problème à vous exposer. Je crée une classe RCModel, pour faire une pseudo-simulation de circuit électrique, qui est basiquement un directed graph sur lequel je rajoute quelques methodes et propriétés. Toutes les propriétés découle de la matrice d’incidence du graphe et des propriétés attachés aux branches et aux noeuds qui sont exprimés comme des expressions SymPy. Par exemple, quand je veux la matrice Ac de mon modèle, je me retrouve avec une matrice d’expressions SymPy. Voilà un subset de mon code qui me permet de faire ça:

class RCModel(object):

    __definition__ = {}

    def __init__(self, name=None):
        self.name = name
        self.network = self.load_from_dict(self.__definition__)
        self.m = sum(['capacity' in data for _, data in self.network.nodes(data=True)])
        self.n = len(self.network.nodes) - 1 - self.m

    # A lot of functions...

    @property
    def _incidence_matrix(self):
        return nx.incidence_matrix(self.network, oriented=True).todense().T

    @property
    def A(self):
        return Matrix(self._incidence_matrix)[:, 1:]

    @property
    def G(self):
        return Matrix(
            np.diag(
                [
                    self.sympy_suffix(
                        sympify(e.get("trigger", 1)) / sympify(e["conductivity"])
                    )
                    for _, _, e in self.network.edges(data=True)
                ]
            )
        )

    @property
    def Cs(self):
        return Matrix(
            np.diag(
                [
                    self.sympy_suffix(sympify(e["capacity"]))
                    for _, e in self.network.nodes(data=True)
                    if "capacity" in e
                ]
            )
        )

    @property
    def K(self):
        return -self.A.T @ self.G @ self.A

    @property
    def K11(self):
        return self.K[: self.n, : self.n]

    # Same type of definitions for K12, K21, K22

    @property
    def Ac(self):
        return self.Cs.inv() @ (-self.K21 @ self.K11.inv() @ self.K12 + self.K22)

Je peux créer un modèle directement en héritant de cette classe, comme avec l’example ci-dessous:

class M3(RCModel):

    __definition__ = {
        "nodes": [
            {"name": "xo", "temperature": "To"},
            {"name": "xso", "heat": "Qo"},
            {"name": "xi", "capacity": "Cj", "heat": "Qh + Qj"},
            {"name": "xw", "capacity": "Cw"},
        ],
        "edges": [
            {"from": "xo", "to": "xi", "conductivity": "Rv"},
            {"from": "xo", "to": "xso", "conductivity": "Rco"},
            {"from": "xso", "to": "xw", "conductivity": "Rw/2"},
            {"from": "xw", "to": "xi", "conductivity": "(Rw/2)+Rci"},
        ],
    }

qui me permet de calculer les propriétés on the fly

In [2]: m = M3()
In [3]: m.Ac
Out[3]: 
Matrix([
[(-1.0/(Rci + Rw/2) - 1.0/Rv)/Cj,                                             1.0/(Cj*(Rci + Rw/2))],
[          1.0/(Cw*(Rci + Rw/2)), (-1.0/(Rci + Rw/2) - 2.0/Rw - 4.0/(Rw**2*(-2.0/Rw - 1.0/Rco)))/Cw]])

Tout ça fonctionne bien, je suis capable de créer des modèles RC qui sont des assemblages de graphes de modèles RCs pre-existants. Mais j’ai du mal à scaler car, pour le moment, calculer les propriétés sont recalculés à chaque appel qui est de plus en plus coûteux avec l’augmentation de la taille du graphe, surtout pour les propriétés qui comportent une inversion de matrice.

Je cherche une stratégie pour cacher ces appels. lru_cache est une option, mais ça fait tout de même un appel coûteux. Est-ce qu’il y aurait des stratégies pour pré-calculer ces propriétés, qui restent fixes pour une __definition__ de RCModel donné, dans une phase précédant l’éxécution du code ?

Merci bien :D

+0 -0

Salut,

Tu dois pouvoir utiliser quelque chose tel que cached_property, qui mettra la propriété en cache à la première utilisation.

Maintenant si j’en crois ce que je vois de ton code, pas mal de choses pourraient être stockées au niveau de la classe plutôt que de ses instances.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte