Je veux calculer la fermeture transitive en Python. Actuellement, j'utilise des matrices creuses de scipy.
La puissance de la matrice (`12` dans mon cas) fonctionne bien sur des matrices très clairsemées, peu importe leur taille, mais pour des cas dirigés pas très clairsemés, j'aimerais utiliser un algorithme plus intelligent.
J'ai trouvé l'_algorithme de Floyd-Warshall_ (la page allemande a un meilleur pseudo-code) dans scipy.sparse.csgraph
, qui fait un peu plus que ce qu'il devrait: il n'y a pas de fonction uniquement pour l'algorithme de Warshall - c'est une chose.
Le problème principal est que je peux passer une matrice creuse à la fonction, mais cela n'a aucun sens car la fonction retournera toujours une matrice dense, car ce qui devrait être 0 dans la fermeture transitive est maintenant un chemin de longueur inf
et quelqu'un a pensé que cela devait être stocké explicitement.
Ma question est donc : Y a-t-il un module python qui permet de calculer la fermeture transitive d'une matrice creuse et de la garder clairsemée?
Je ne suis pas sûr à 100% qu'il travaille avec les mêmes matrices, mais Gerald Penn montre des accélérations impressionnantes dans son article de comparaison, ce qui suggère qu'il est possible de résoudre le problème.
EDIT: Comme il y a eu un certain nombre de confusions, je vais expliquer le contexte théorique:
Je cherche la fermeture transitive (pas réflexive ou symétrique).
Je m'assurerai que ma relation encodée dans une matrice booléenne a les propriétés requises, c'est-à-dire la symétrie ou la réflexivité.
J'ai deux cas de relation:
- réflexive
- réflexive et symétrique
Je veux appliquer la fermeture transitive sur ces deux relations. Cela fonctionne parfaitement bien avec la puissance de la matrice (seulement que dans certains cas cela est trop coûteux):
>>> réflexive
matrix([[ True, True, False, True],
[False, True, True, False],
[False, False, True, False],
[False, False, False, True]])
>>> reflexive**4
matrix([[ True, True, True, True],
[False, True, True, False],
[False, False, True, False],
[False, False, False, True]])
>>> reflexive_symmetric
matrix([[ True, True, False, True],
[ True, True, True, False],
[False, True, True, False],
[ True, False, False, True]])
>>> reflexive_symmetric**4
matrix([[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True]])
Ainsi, dans le premier cas, nous obtenons tous les descendants d'un nœud (y compris lui-même) et dans le deuxième cas, nous obtenons tous les composants, c'est-à-dire tous les nœuds qui sont dans le même composant.