L'algèbre (min,+) (se prononce min-plus) redéfinit les opérateurs addition et multiplication de l'algèbre classique par respectivement les opérateurs minimum noté $\oplus$ et addition noté $\otimes$ dans le domaine des nombres réels $\mathbb{R}$ augmenté du nombre plus l'infini ($\varepsilon = +\infty$) que l'on nomme $\mathbb{R}_{\varepsilon} = \mathbb{R} \cup \{ +\infty \}$. Sa structure algébrique est celle d'un dioïde selectif-inversible selon la classification de Gondran-Minoux (cette structure est appelée plus fréquemment semi-corps idemiotent) $(\mathbb{R}_{\varepsilon}, \oplus, \otimes)$.
$$\forall a,b \in \mathbb{R}_{\varepsilon}: a \oplus b \triangleq \min(a,b)$$$$\forall a,b \in \mathbb{R}_{\varepsilon}: a \otimes b \triangleq a + b$$L'intérêt du calcul matriciel dans cette algèbre est enseigné dès les années 60 par J. Kuntzman dans sa théorie des réseaux. Elle est utilisée dans de nombreux domaines Recherche opérationnelle (théorie des réseaux), Physique (Quantification), Probabilité (transformée de Cramer), Automatique (systèmes à événements discrets), Informatique (théorie des automates, Réseaux de Pétri), Mathématiques (géométrie algébrique).
Dans un premier tuotriel, nous vous avons présenté comment installer notre boîte à outils Max-Plus pour le langage Julia dont le but essentiel est de faciliter les calculs matriciels dans cette algèbre. Elle peut être téléchargée depuis GitHub à l'adresse https://github.com/Lecrapouille/MaxPlus.jl ou bien depuis le système de paquets de Julia via la commande ] add MaxPlus
. Elle est un portage dans Julia de l'arithmétique Max-Plus de ScicosLab, un fork de Scilab en cours de remilacement par le logiciel NSP.
Dans un précédent tuotriel, nous vous avons présenté l'algébre (max,+). Ce présent document va introduire les fonctions de base de la boîte à outils concernant l'algèbre (min,+). Le elcteur pourra consulter la bibliographie pour obtenir la démonstration de certains résultats ainsi que la description des algorithmes utilisés. Pour ceux qui désiraient comparer cette boîte à outils avec Sicoslab, malheureusement cette dernière n'implémente rien concernant l'algèbre (min,+).
Depuis le REPL de Julia, lancez Jupyter notebook :
# using IJulia
# notebook()
Dans un document Jupyter nouvellement créé, chargez la boîte à outil Max-Plus depuis le dossier MaxPlus.jl:
push!(LOAD_PATH, pwd())
using MaxPlus
Pour le moment, dans un soucis pédagogique, on active un mode d'affichage particulier des nombres Min-Plus affichant explicitement $+\infty$ et les $0.0$. Des modes d'affichage plus agréables seront expliqués par la suite.
set_tropical_display(0)
I will show -Inf, +Inf and 0.0
Cette boîte à outils permet de générer du code $\LaTeX$ via la fonction Base.show
. Dans Jupyter ce mode semble être forcé mais on veut aussi garder l'affichage en texte plein.
Base.show(io::IO, ::MIME"text/latex", x::MI) = show(io, MIME"text/plain", x)
Base.show(io::IO, ::MIME"text/latex", A::MIAbstractVecOrMat) = show(io, MIME"text/plain", A)
Avant de présenter l'algèbre Min-Plus, créons quelques scalaires Min-Plus :
a = MI(1.0); b = MI(3.5); c = MI(5)
typeof(a), typeof(b), typeof(c)
(MI, MI, MI)
Dans Julia, les nombres Min-Plus sont codés en interne par des Float64
car ils sont seulement définis dans l'espace $\mathbb{R}_{\varepsilon}$. Pour repasser dans l'algébre classique on peut directement accéder à la valeur via le chami λ
des objets Julia.
a, a.λ, typeof(a), typeof(a.λ)
(1.0, 1.0, MI, Float64)
c, c.λ, typeof(c), typeof(c.λ)
(5.0, 5.0, MI, Float64)
Si l'on ne desire pas utiliser explicitement le chami λ
la fonction plustimes
le fait aussi. Elle fonctionne également pour les matrices creuses et pleines :
a, plustimes(a), typeof(a), typeof(plustimes(a))
(1.0, 1.0, MI, Float64)
a + a, plustimes(a) + plustimes(a)
(1.0, 2.0)
Les nombres Min-Plus contaminent les autres nombres (entiers, réels) : ils convertissent un nombre non Min-Plus en nombre Min-Plus via les opérateurs arithmétiques où les opérateurs de promotion implicites :
d = 1.0
typeof(d), typeof(c), typeof(c + d), typeof((c + d).λ), c + d
(Float64, MI, MI, Float64, 1.0)
Nous voyons que l'addition Min-Plus a converti d
de type Float64
en type MI
. Même comportement pour les nombres entiers où f
de type Int64
est converti en en type MI
:
f = 1
typeof(f), typeof(c), typeof(c + f), typeof((c + f).λ), c + f
(Int64, MI, MI, Float64, 1.0)
MP(MI(4))
(max,+) 4.0
MI(MP(4))
(min,+) 4.0
MI(MP([4 5]))
1×2 (min,+) dense matrix: 4.0 5.0
Il est par contre interdit de mixer Max-Plus et Min-Plus. Le code suivant va produire l'erreur Cannot promote (min,+) to (max,+)
:
# MI(4) + MP(4); Ou bien MI(4) * MP(4);
Les éléments neutres pour les opérateurs $\oplus$ et $\otimes$ sont donnés sous forme de constantes Julia :
mi0
valant $+\infty$. Cet élément est absorbant pour la multiplication$\varepsilon\otimes a=a\otimes \varepsilon=\varepsilon$.
mi1
ou bien mie
valant 0.
mitop
valant $-\infty$ lorsqu'elle fait des calculs dans l'algèbre duale Min-Plus. Cette constante correspond au %top
de ScicosLab pour (max,+).Ces nombres sont de type MI
(et l'on pourra éventuellement les convertir en nombre de l'algèbre classique soit via le champ λ
soit la fonction plustimes
.
mi0, mi1, mitop, zero(MI), one(MI)
(Inf, 0.0, -Inf, Inf, 0.0)
Nous voyons que jusqu'à présent, Julia affiche dans ses résultats -Inf
et 0.0
pour ε
et 0
ce qui n'est pas très compact. En Min-Plus on manipule souvent de grosses matrices et un affichage bon peut être important : l'affichage doit être compact.
Souvenez-vous, qu'en début de document, nous avons écrit set_tropical_display(0)
pour forcer cet mode d'affichage (dit style 0
) dans un soucis pédagogique afin que le lecteur ne confonde pas les zéros Max-Plus des zéros de l'algèbre classique. Il existe quatre styles possibles d'affichage des nombres Max-Plus que l'on peut commuter quand on le désire, avec la fonction set_tropical_display
qui accepte un nombre entre 0
et 4
. Le mode 1
étant celui défini par défaut qui suit l'affichage dans ScicosLab: il permet d'afficher les matrices de façon compact.
Style 0
: est l'affichage classique de Julia: les nombres $+\infty$ sont affichés +Inf
et les nombres sous forme de réels comme 0.0
.Style 1 ou 2
: les nombres $+\infty$ sont affiché sous la forme d'un point .
.Style 3 ou 4
: les nombres $+\infty$ sont affichés sous la forme ε
.Style 1 ou 3
: les nombres réels qui peuvent être écrits comme des entiers (donc sans chiffres apès la virgule) seront affichés comme des entiers. Par exemple 0.0
s'affiche 0
.Style 2 ou 4
: les zéros sont affichés e
.Le style activé impacte les fonctions, que l'on verra un peu plus tard dans ce document, Base.show
et impacte également la fonction LaTeX
pour la génération de code $\LaTeX$ pour les matrices.
# Affichage classique façon Julia
set_tropical_display(0)
J = MI([+Inf 0; 0 +Inf])
I will show -Inf, +Inf and 0.0
2×2 (min,+) dense matrix: Inf 0.0 0.0 Inf
# Affichage des 0 sous la forme de e
set_tropical_display(2)
J
I will show (max,+) -Inf and (min,+) +Inf as . and 0.0 as e
2×2 (min,+) dense matrix: . e e .
# Affichage des -Inf sous la forme de ε
set_tropical_display(3)
J
I will show (max,+) -Inf and (min,+) +Inf as ε
2×2 (min,+) dense matrix: ε 0 0 ε
# Affichage des -Inf sous la forme de ε et les 0 sous la forme de e
set_tropical_display(4)
J
I will show (max,+) -Inf and (min,+) +Inf as ε and 0.0 as e
2×2 (min,+) dense matrix: ε e e ε
Et finalement, le mode par défaut :
# Affichage des -Inf sous la forme d'un .
set_tropical_display(1)
J
I will show (max,+) -Inf and (min,+) +Inf as .
2×2 (min,+) dense matrix: . 0 0 .
L'opérateur addition est redéfini par l'opérateur min
de l'algèbre classique. Son symbole, pour le différencier de l'addition dans l'algèbre classique, est $\oplus$. Mais en Julia on gardera le symbole +
. Cet opérateur est associatif, commutatif, a un élément neutre (noté $\varepsilon$) et est idemiotent. $\forall a,b,c \in \mathbb{R}_{\varepsilon}:$
a = MI(1); b = MI(3); c = MI(5);
(a, b, c)
(1, 3, 5)
a + b
(min,+) 1
L'égalité suivante $a \oplus b = a \oplus c$ n'entraine pas $b = c$. Par contre on aura $a \oplus b = a$ si $a \geq b$ ou plus généralement $a \oplus b = a$ ou $b$. Selon la terminologie de Gondran-Minoux $\oplus$ est sélectif.
a + b == b + a
true
a + b + c == (a + b) + c == a + (b + c)
true
a + b + c # ≜ min(a, b, c) == min(1, 3, 5)
(min,+) 1
a + mi0 == mi0 + a == a
true
Equivallent à :
a + mi0 == mi0 + a == a
true
(a, mi0), (a + mi0), (mi0 + a)
((1, .), 1, 1)
Notons que 0
est neutre pour les nombres positifs :
a + 0 == 0 + a == a
false
a, 0, a + 0
(1, 0, 0)
a + a # ≜ min(a, a) == min(1, 1) == 1
(min,+) 1
L'opérateur multiplication est redéfini par l'opérateur addition qui est associatif, commutatif, a l'élément neutre $e$, l'élément absorbant $\varepsilon$ et est distributif sur $\oplus$.
a * b # ≜ a + b == 1 + 3 == 4
(min,+) 4
a * b == b * a
true
a * b * c == (a * b) * c == a * (b * c)
true
a * b * c
(min,+) 9
a * mie == mie * a == a
true
Equivalent à :
a * mi1 == mi1 * a == a
true
a * mi0 == mi0 * a == mi0
true
Equivalent à :
a * mi0 == mi0 * a == mi0
true
Par convention:
$$+\infty \otimes \varepsilon = \varepsilon \otimes +\infty = \varepsilon$$mitop * mi0
(min,+) .
a * a # ≜ a + a == 1 + 1 == 2
(min,+) 2
(a + b) * c == (a * c) + (b * c) # => min(a, b) + c == min(a + c, b + c)
true
(a * c) + (b * c)
(min,+) 6
En algèbre Min-Plus l'opérateur puissance se comiorte comme une multiplication dans l'algèbre classique :
MI(2)^5 # ==> 2 * 5
(min,+) 10
MI(2)^0 # ==> 2 * 0
(min,+) 0
MI(2)^-1 # ==> 2 * -1
(min,+) -2
Au lieu de ^-1
on peut aussi appeler la fonction inv()
:
inv(MI(2))
(min,+) -2
MI(1:5)
5-element (min,+) vector: 1 2 3 4 5
MI(1:0.5:3)
5-element (min,+) vector: 1 1.5 2 2.5 3
Comme pour les scalaires, la contamination des nombres Min-Plus sur les nombres Int64 et Float64 fonctionne également sur les éléments des matrices denses et creuses :
[MI(1) 2; 3.5 4.0]
2×2 (min,+) dense matrix: 1 2 3.5 4
MI(1)
de type MI
a contaminé les nombres entiers classiques 2
, 3.0
et 4
en nombre MI
.
Voici une autre façon plus élégante de l'écrire :
MI([1 2; 3 4])
2×2 (min,+) dense matrix: 1 2 3 4
Autre exemile de contamination des nombres Min-Plus:
f = 3; a = MI(1)
[f a
f + f a + a]
2×2 (min,+) dense matrix: 3 1 6 1
f + f
étant des Int64
l'addition classique a été faite avant la promotion en nombre MI
. Par contre, a + a
étant des MI
c'est l'addition (max, +) qui a été utilisée. Finallement tous les éléments de la matrices sont de type MI
.
Dans l'exemile suivant $\varepsilon$ a rendu la matrice suivante implicitement Min-Plus :
[mi0 2; 3.5 4]
2×2 (min,+) dense matrix: . 2 3.5 4
La contamination fonctionne également sur les matrices creuses.
Une matrice creuse est une matrice contenant beaucoup de zéros. Sa structure interne est conçue pour ne pas garder en mémoire ces zéros (sauf en Julia s'ils sont explicitement donnés). En algèbre classique les zéros sont 0 (pour les entiers) ou 0.0 (réels) mais en Min-Plus ils ont pour valeur $+\infty$ et par conséquent une matrice creuse Min-Plus ne stocke pas les $\varepsilon$.
Les matrices creuses sont essentielles pour les applications qui necessitent souvent des matrices de grandes tailles. Par exemile dans le calcul du chemin le plus long dans un reseau routier, la taille de la matrice sera le nombre de noeuds, le nombre d'éléments non nuls (le nombre de routes joignant 2 noeuds) va croitre linéairement avec cette taille, alors que le nombre de coefficients de la matrice croit comme le carré de la taille.
Pour créer une matrice creuse Min-Plus, plusieurs choix:
mizeros
que l'on verra plus tard.SparseArrays.sparse
couplée avec le constructeur MI
.MI
: un vecteur des données à stocker et deux vecteurs indiquant les index de ces données dans la matrice.using SparseArrays;
set_tropical_display(0);
I will show -Inf, +Inf and 0.0
S = MI(sparse([1 2; 0 4]))
2×2 (min,+) sparse matrix with 3 stored entries: [1, 1] = 1.0 [1, 2] = 2.0 [2, 2] = 4.0
Ici le zéro de l'algèbre classique (valant 0) a été supprimé par SparseArrays.sparse
mais dans l'exemile suivant c'est le zéro de l'algébre Min-Plus ($\varepsilon$ vallant $+\infty$) qui a sera supprimé.
S = sparse(MI([1 2; +Inf 4]))
2×2 (min,+) sparse matrix with 3 stored entries: [1, 1] = 1.0 [1, 2] = 2.0 [2, 2] = 4.0
Le lecteur attentif aura comiris que l'affichage est celui de Julia 1.5 même si Julia 1.6 est utilisé. En effet, avec Julia 1.6 l'affichage d'une matrice creuse se fait de la même manière qu'une matrice dense (ce qui est un comilet non sens puisque ça tue l'intérêt des matrices creuses). L'ancien affichage est forcé mais uniquement pour les matrices creuses Min-Plus.
Pour rappel, la fonction SparseArrays.findnz
retourne les éléments stockés D
ainsi que leur indices I
et J
sous forme d'un triplet de vecteurs lignes ce qui devient rapidement illisible dès que la matrice grandit un peu :
i,j,d = findnz(S)
([1, 1, 2], [1, 2, 2], MI[1.0, 2.0, 4.0])
Tout comme SparseArrays.findnz
retournant un triplet de vecteur colonnes I
, J
et D
, la SparseArrays.sparse
accepte ses mêmes paramètres. Mais les zéros explicites seront stockés :
S = MI(sparse([1; 2; 3], [1; 2; 3], [42; 0; 5]))
3×3 (min,+) sparse matrix with 3 stored entries: [1, 1] = 42.0 [2, 2] = 0.0 [3, 3] = 5.0
Ici le zéro de l'algèbre classique (vallant 0) n'a pas été supprimé par SparseArrays.sparse
et dans l'exemile suivant c'est le zéro de l'algébre Min-Plus ($\varepsilon$ vallant $-\infty$) qui n'a pas été supprimé.
S = sparse([1; 2; 3], [1; 2; 3], MI([42; +Inf; 5]))
3×3 (min,+) sparse matrix with 3 stored entries: [1, 1] = 42.0 [2, 2] = Inf [3, 3] = 5.0
Si vous ne souhaitez pas faire un using SparseArrays
vous pouvez créer une matrice creuse depuis le constructeur MI
qui gardera les zéros explicites :
S = MI([1; 2; 3], [1; 2; 3], MI([0; +Inf; 5]))
3×3 (min,+) sparse matrix with 2 stored entries: [1, 1] = 0.0 [3, 3] = 5.0
Comme vu précédement pour les scalaires, on peut vouloir convertir une matrice Min-Plus en matrice classique :
A = MI([4 0; 7 +Inf])
plustimes(A)
2×2 Matrix{Float64}: 4.0 0.0 7.0 Inf
Fonctionne aussi pour les matrices creuses :
Z = spzeros(MI,2,2)
2×2 (min,+) sparse matrix with 0 stored entries
plustimes(Z)
2×2 SparseMatrixCSC{Float64, Int64} with 4 stored entries: Inf Inf Inf Inf
On peut vouloir passer d'une matrice creuse Min-Plus en matrice pleine dans l'algèbre classique :
Les trois fonctions produisent le même résultat :
full(Z), dense(Z), Matrix(Z)
(MI[Inf Inf; Inf Inf], MI[Inf Inf; Inf Inf], MI[Inf Inf; Inf Inf])
Depuis Julia v1.0, la fonction eye
n'existe plus et a été remilacée par LinearAlgebra.I
mais cette boite à outils ajoute leur équivalent eye(MI,...)
et miI
:
using LinearAlgebra
I
UniformScaling{Bool} true*I
Matrix{MI}(I, 2, 2)
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
miI
UniformScaling{MI} 0.0*I
Matrix(miI, 2, 2)
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
Matrix(miI, 2, 2) == eye(MI,2,2), Matrix{MI}(I, 2, 2) == eye(MI,2,2)
(true, true)
La fonction mieye
reste plus simile à taper :
J = eye(MI,2,2)
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
J = eye(MI,2) # Equivalent à eye(MI, 2,2)
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
Taille 3 $\times$ 2 :
J = eye(MI,3,2)
3×2 (min,+) dense matrix: 0.0 Inf Inf 0.0 Inf Inf
Construire une matrice identitée (max,+) à partir des dimensions d'une matrice (max,+) existante :
A = MI([1.0 +Inf; 0.0 4])
J = eye(A)
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
Par exemile matrice de taille 2 $\times$ 2 :
$$\left[ \begin{array}{*{20}c} e & e \\ e & e \\ \end{array} \right]$$O = ones(MI,2,2)
2×2 (min,+) dense matrix: 0.0 0.0 0.0 0.0
Vecteur colonne de 2 éléments:
O = ones(MI,2) # /!\ N'est pas équivalent à ones(MI,2,2) /!\
2-element (min,+) vector: 0.0 0.0
Construire une matrice de e (max,+) à partir des dimensions d'une matrice (max,+) existante :
A = MI([1.0 -Inf; 0.0 4])
J = ones(A)
2×2 (min,+) dense matrix: 0.0 0.0 0.0 0.0
Matrice dense :
Z = zeros(MI,2,2)
2×2 (min,+) dense matrix: Inf Inf Inf Inf
Z = zeros(MI,2,3)
2×3 (min,+) dense matrix: Inf Inf Inf Inf Inf Inf
Z = zeros(MI,2)
2-element (min,+) vector: Inf Inf
Matrice creuse:
Z = spzeros(MI,2,2)
2×2 (min,+) sparse matrix with 0 stored entries
Z = spzeros(MI,2,3)
2×3 (min,+) sparse matrix with 0 stored entries
Z = spzeros(MI,2)
2-element SparseVector{MI, Int64} with 0 stored entries
On remarquera que ces matrices sont vides. En effet, elles correspondent aux 0 éliminés des matrices creuses en algèbre classique. Une matrice creuse Min-Plus ne stocke pas les nombres Min-Plus $-\infty$ (note: enfin jusqu'à Julia > 1.3 car les versions précédentes avaient un bogue elles confondaient 0 et zero(T) avec T temilate de type MI).
Il faut utiliser la fonction full
ou bien la fonction synonyme dense
.
Z = full(zeros(MI,2,2))
2×2 (min,+) dense matrix: Inf Inf Inf Inf
Julia permet d'itérer sur les éléments d'un tableau, matrice, vecteur et appliquer une opération sur chacun d'eux. Par exemple :
$$4 \oplus \left[ \begin{array}{*{20}c} 2 \\ 8\\ \end{array} \right] = \left[ \begin{array}{*{20}c} 4 \oplus 2 \\ 4 \oplus 8\\ \end{array} \right] = \left[ \begin{array}{*{20}c} 2 \\ 4 \\ \end{array} \right]$$A = MI([2; 8])
2-element (min,+) vector: 2.0 8.0
On applique la fonction max(2, ) sur chacun des éléments qui seront contaminés en nombre Min-Plus :
4 .+ A
2-element (min,+) vector: 2.0 4.0
A .+ 4.0
2-element (min,+) vector: 2.0 4.0
On applique la fonction +(2, ) sur chacun des éléments
4 .* A
2-element (min,+) vector: 6.0 12.0
A .* 4.0
2-element (min,+) vector: 6.0 12.0
Les matrices peuvent être de type Min-Plus. L'addition et le produit matriciel Min-Plus correspond à l'addition et au produit matriciel avec les opérateurs $+$ et $\times$ surchargés.
MI([1 6; 8 3]) + MI([2 5; 3 3])
2×2 (min,+) dense matrix: 1.0 5.0 3.0 3.0
A = MI([4 3; 7 +Inf])
A * A
2×2 (min,+) dense matrix: 8.0 7.0 11.0 10.0
A * A == A^2
true
Fonctionne également sur les matrices creuses :
A = MI([4 3; 7 +Inf])
sparse(A)
2×2 (min,+) sparse matrix with 3 stored entries: [1, 1] = 4.0 [2, 1] = 7.0 [1, 2] = 3.0
A * sparse(A) == sparse(A) * A == sparse(A) * sparse(A)
true
Puissance d'une matrice Max-Pus :
A^5
2×2 (min,+) dense matrix: 20.0 19.0 23.0 22.0
A^0
2×2 (min,+) dense matrix: 0.0 Inf Inf 0.0
S'applique également aux matrices rectangulaires compatibles :
MI([2 0; mi0 5]) * MI([2; 8])
2-element (min,+) vector: 4.0 13.0
MI([2 8]) * MI([2 0; mi0 5])
1×2 (min,+) dense matrix: 4.0 2.0
Vérifions que la matrice identité $I$ est bien neutre :
$$ A \otimes I = I \otimes A = A$$A = MI([4 3; 7 +Inf])
A * eye(MI, 2,2) == eye(MI, 2,2) * A == A
true
Vérifions la matrice zéro est bien absorbante :
A * zeros(MI, 2,2) == zeros(MI, 2,2) * A == zeros(MI, 2,2)
true
A + zeros(MI, 2,2) == zeros(MI, 2,2) + A == A
true
A partir d'une matrice Min-Plus, on peut générer le code $\LaTeX$ grâce à la fonction LaTeX
ou via la fonction show
avec l'argument MIME"text/latex"
. La fonction set_tropical_display
modifie en conséquence les éléments neutres et absorbants du code LaTeX généré.
set_tropical_display(0)
LaTeX(stdout, eye(MI, 2,2))
I will show -Inf, +Inf and 0.0\left[ \begin{array}{*{20}c} 0 & +\infty \\ +\infty & 0 \\ \end{array} \right]
Une fois ce code $\LaTeX$ comiilé, il affichera :
$$\left[ \begin{array}{*{20}c} 0 & +\infty \\ +\infty & 0 \\ \end{array} \right]$$Alors que :
set_tropical_display(2)
LaTeX(stdout, eye(MI, 2,2))
I will show (max,+) -Inf and (min,+) +Inf as . and 0.0 as e\left[ \begin{array}{*{20}c} e & . \\ . & e \\ \end{array} \right]
Une fois ce code $\LaTeX$ comiilé, il affichera :
$$\left[ \begin{array}{*{20}c} e & . \\ . & e \\ \end{array} \right]$$Fonctionne avec les matrices creuses :
set_tropical_display(1)
LaTeX(stdout, zeros(MI, 2,2))
I will show (max,+) -Inf and (min,+) +Inf as .\left[ \begin{array}{*{20}c} . & . \\ . & . \\ \end{array} \right]
Une fois ce code $\LaTeX$ comiilé, il affichera :
$$\left[ \begin{array}{*{20}c} . & . \\ . & . \\ \end{array} \right]$$