As in the previous post, let be a weighted digraph having
vertices and let
denote its
adjacency matrix. We identify the vertices with the set
.
The previous post discussed the following result, due to Sturmfels et al.
Theorem: The entry of the matrix A n-1 in row i and column j equals the length of a shortest path from vertex i to vertex j in G. (Here A
n-1 denotes the n-1-st tropical power of A.)
This post discusses an implementation in Python/Sage.
Consider the following class definition.
class TropicalNumbers: """ Implements the tropical semiring. EXAMPLES: sage: T = TropicalNumbers() sage: print T Tropical Semiring """ def __init__(self): self.identity = Infinity def __repr__(self): """ Called to compute the "official" string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value. EXAMPLES: sage: TropicalNumbers() TropicalNumbers() """ return "TropicalNumbers()" def __str__(self): """ Called to compute the "informal" string description of an object. EXAMPLES: sage: T = TropicalNumbers() sage: print T Tropical Semiring """ return "Tropical Semiring" def __call__(self, a): """ Coerces a into the tropical semiring. EXAMPLES: sage: T(10) TropicalNumber(10) sage: print T(10) Tropical element 10 in Tropical Semiring """ return TropicalNumber(a) def __contains__(self, a): """ Implements "in". EXAMPLES: sage: T = TropicalNumbers() sage: a = T(10) sage: a in T True """ if a in RR or a == Infinity: return a==Infinity or (RR(a) in RR) else: return a==Infinity or (RR(a.element) in RR) class TropicalNumber: def __init__(self, a): self.element = a self.base_ring = TropicalNumbers() def __repr__(self): """ Called to compute the "official" string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value. EXAMPLES: """ return "TropicalNumber(%s)"%self.element def __str__(self): """ Called to compute the "informal" string description of an object. EXAMPLES: sage: T = TropicalNumbers() sage: print T(10) Tropical element 10 in Tropical Semiring """ return "%s"%(self.number()) def number(self): return self.element def __add__(self, other): """ Implements +. Assumes both self and other are instances of TropicalNumber class. EXAMPLES: sage: T = TropicalNumbers() sage: a = T(10) sage: a in T True sage: b = T(15) sage: a+b 10 """ T = TropicalNumbers() return T(min(self.element,other.element)) def __mul__(self, other): """ Implements multiplication *. EXAMPLES: sage: T = TropicalNumbers() sage: a = T(10) sage: a in T True sage: b = T(15) sage: a*b 25 """ T = TropicalNumbers() return T(self.element+other.element) class TropicalMatrix: def __init__(self, A): T = TropicalNumbers() self.base_ring = T self.row_dimen = len(A) self.column_dimen = len(A[0]) # now we coerce the entries into T A0 = A m = self.row_dimen n = self.column_dimen for i in range(m): for j in range(n): A0[i][j] = T(A[i][j]) self.array = A0 def matrix(self): """ Returns the entries (as ordinary numbers). EXAMPLES: sage: A = [[0,1,3,7],[2,0,1,3],[4,5,0,1],[6,3,1,0]] sage: AT = TropicalMatrix(A) sage: AT.matrix() [[0, 1, 3, 7], [2, 0, 1, 3], [4, 5, 0, 1], [6, 3, 1, 0]] """ m = self.row_dim() n = self.column_dim() A0 = [[0 for i in range(n)] for j in range(m)] for i in range(m): for j in range(n): A0[i][j] = (self.array[i][j]).number() return A0 def row_dim(self): return self.row_dimen def column_dim(self): return self.column_dimen def __repr__(self): """ Called to compute the "official" string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value. EXAMPLES: """ return "TropicalMatrix(%s)"%self.array def __str__(self): """ Called to compute the "informal" string description of an object. EXAMPLES: """ return "Tropical matrix %s"%(self.matrix()) def __add__(self, other): """ Implements +. Assumes both self and other are instances of TropicalMatrix class. EXAMPLES: sage: A = [[1,2,Infinity],[3,Infinity,0]] sage: B = [[2,Infinity,1],[3,-1,1]] sage: AT = TropicalMatrix(A) sage: BT = TropicalMatrix(B) sage: AT TropicalMatrix([[TropicalNumber(1), TropicalNumber(2), TropicalNumber(+Infinity)], [TropicalNumber(3), TropicalNumber(+Infinity), TropicalNumber(0)]]) sage: AT+BT [[TropicalNumber(1), TropicalNumber(2), TropicalNumber(1)], [TropicalNumber(3), TropicalNumber(-1), TropicalNumber(0)]] """ A = self.array B = other.array C = [] m = self.row_dim() n = self.column_dim() if m != other.row_dim: raise ValueError, "Row dimensions must be equal." if n != other.column_dim: raise ValueError, "Column dimensions must be equal." for i in range(m): row = [A[i][j]+B[i][j] for j in range(n)] # + as tropical numbers C.append(row) return C def __mul__(self, other): """ Implements multiplication *. EXAMPLES: sage: A = [[1,2,Infinity],[3,Infinity,0]] sage: AT = TropicalMatrix(A) sage: B = [[2,Infinity],[-1,1],[Infinity,0]] sage: BT = TropicalMatrix(B) sage: AT*BT [[TropicalNumber(1), TropicalNumber(3)], [TropicalNumber(5), TropicalNumber(0)]] sage: A = [[0,1,3,7],[2,0,1,3],[4,5,0,1],[6,3,1,0]] sage: AT = TropicalMatrix(A) sage: A = [[0,1,3,7],[2,0,1,3],[4,5,0,1],[6,3,1,0]] sage: AT = TropicalMatrix(A) sage: print AT*AT*AT Tropical matrix [[0, 1, 2, 3], [2, 0, 1, 2], [4, 4, 0, 1], [5, 3, 1, 0]] """ T = TropicalNumbers() A = self.matrix() B = other.matrix() C = [] mA = self.row_dim() nA = self.column_dim() mB = other.row_dim() nB = other.column_dim() if nA != mB: raise ValueError, "Column dimension of A and row dimension of B must be equal." for i in range(mA): row = [] for j in range(nB): c = T(Infinity) for k in range(nA): c = c+T(A[i][k])*T(B[k][j]) row.append(c.number()) C.append(row) return TropicalMatrix(C)
This shows that the shortest distances of digraph with adjacency matrix is equal to A
3, which is equal to
This verifies an example given in chapter 1 of the book by Maclagan and Sturmfels, Introduction to Tropical Geometry .