Kaikkihan tietätävät että graafin solmujen välillä olevien -kävelyjen lukumäärät saadaan korottamalla graafin vierekkäisyysmatriisi potenssiin
. Mutta entä jos matriisissa käytetään kaarien painotuksia ja matriisitulossa rivin ja sarakkeen pistetulon paikalla alkioiden summien minimiä? Tämä on Hedetniemen matriisisumma.
Määritelmä
Matriisien (kokoa
) ja
(kokoa
) Hedetniemen summa
on
-matriisi
, jonka
-alkio on
Huom. Sallimme matriisin alkioksi myös plus äärettömän . Määrittelemme
ja
kaikille luvuille
ja myös tapauksessa
.
Esimerkki

Mihin tätä summaa sitten käytetään? Sen avulla voidaan selvittää lyhyimmät reitit kaikkien solmuparien välillä graafissa, jonka kaarille on annettu ei-negatiiviset painokertoimet (etäisyydet). Muodostetaan graafille kaarien painomatriisi
, jossa alkio
,
on
:n ja
:n välisen kaaren paino tai
, jos solmujen välillä ei ole kaarta. Diagonaalialkiot
asetetaan nollaksi, sillä solmusta itseensä on nollan askeleen reitti, jonka pituus (=sen käyttämien kaarien painojen summa) on nolla. Oletamme että graafi on yksinkertainen eli sillä ei ole kaaria solmusta itseensä eikä useampia kaaria kahden solmun välillä. Tämä on luonnollinen oletus kun haluamme selvittää lyhyimpiä reittejä, sillä luuppia solmusta itseensä ei kannata reitissä ikinä käyttää ja useammasta kaaresta solmujen välillä kannattaa aina valita se, jolla on pienin paino.
Kaaret ajatellaan suunnaatuiksi, mutta suuntaamattomassa tapauksessa ajatellaan, että kaari on kumpaankin suuntaan olemassa (samalla painolla). Suuntaamattomassa tapauksessa matriisi on siis symmetrinen.

Lasketaan matriisin iteroituja Hedetniemen summia
. Merkitsemme siis
(tämä ei sotkeutune tavalliseen matriisituloon, jota ei tässä postauksessa esiinny). Iteraation
alkio
kertoo lyhyimmän
:n askeleen reitin pituuden solmusta
solmuun
. Koska graafi on äärellinen, käy jostakin
:n arvosta
lähtien niin, että
eli jono stabiloituu. Ylläolevalle esimerkille

Reitin selvitys
Lyhyimmän reitin pituus on luettavissa matriisin alkiosta, mutta kuinka saamme tiedon mikä tuo reitti on? Se voidaan selvittää solmu kerrallaan lähtemällä päätepisteestä ja ratkaisemalla mikä sitä täytyy reitillä edeltää. Otetaan esimerkiksi edellä olleen graafin solmut
ja
. Matriisista
nähdään, että lyhyimmän reitin pituus on
. Tutkitaan nyt päätepisteen eli solmun
naapureita (
). Se kummasta kutoseen on tultu, täytyy toteuttaa yhtälö, että lyhyin reitti nollasta siihen on
. Koska solmusta
tulee 2:n painoinen kaari ja lyhyin reitti nollasta solmuun
on
:n mukaan pituudeltaan 4, niin valitaan solmu
. Jatketaan nyt solmusta
ja etsitään sen edeltäjä. Näin jatketaan kunnes päästään alkupisteeseen ja reitti on selvitetty.

Huomioita
- Jos matriisin jää äärettömyyksiä jonon stabiloiduttua, tarkoittaa se että graafi on epäyhtenäinen: jostain solmusta ei ole mitään reittiä johonkin toiseen solmuun.
- Stabiloituminen vie korkeintaan
askelta, sillä lyhyin reitti ei vieraile missään solmussa kuin korkeintaan kerran.
- Pienempiä (ennen stabiloitumista) iterantteja voi käyttää askelten määrän ollessa rajoitettu, sillä ne tosiaan kertovat sen hetkisen lyhyimmän etäisyyden kun käytetään korkeintaan
askelta. (Jos haluaisi käyttää tasan
askelta sen voisi varmaan toteuttaa asettamalla diagonaalialkiot äärettömiksi, jolloin solmussa ei ole luvallista pysyä. ???)
- Algoritmin kehittäjä on Stephen Hedetniemi. Lisätietoa historiasta Seuran artikkelissa. Hedetniemen nimissä on myös graafien tensoritulon väritykseen liittyvä konjektuuri, joka ratkesi aivan tässä viime aikoina kielteisesti eli siihen löytyi vastaesimerkki: Yaroslav Shitov, Counterexamples to Hedetniemi’s conjecture.
Ohjelmakoodit (Python)
INFTY = 2**56 #number larger than any other occuring one
def hedetniemiMatrixSum(a, b):
m = len(a)
n = len(b)
p = len(b[0])
return [[min(a[i][k] + b[k][j] for k in range(n))
for j in range(p)]
for i in range(m)]
def findStableHedetniemiSum(a):
n = len(a)
prev = a
b = a
counter = 0
while counter<n:
b = hedetniemiMatrixSum(b, a)
if b == prev: break
prev = b
return b
def findPath(start, end, minDMat, a):
"""
start: index of the start node
end: index of the target node
minDMat: the stabilized matrix
containing the minimum paths lenghts
a: the weighted adjacency matrix
"""
n = len(a)
path = [end]
dist = minDMat[start][end]
if dist>=INFTY: return None #no path exists
curr = end
def findPrev():
for i in range(n):
if i==curr: continue
if dist-a[i][curr] == minDMat[start][i]: return i
counter = 0
while curr != start and counter<n:
prev = findPrev()
dist -= a[prev][curr]
curr = prev
path.append(curr)
return path[::-1]
#the example matrix
a = [
[0,1,2,INFTY,INFTY,8,INFTY],
[1,0,4,2,INFTY,INFTY,INFTY],
[2,4,0,INFTY,7,INFTY,INFTY],
[INFTY,2,INFTY,0,1,INFTY,INFTY],
[INFTY,INFTY,7,1,0,INFTY,2],
[8,INFTY,INFTY,INFTY,INFTY,0,1],
[INFTY,INFTY,INFTY,INFTY,2,1,0]
]
b = findStableHedetniemiSum(a)
print b
print findPath(0, 6, b, a)
