2017-03-25 8 views
1

Ich beginne gerade mit Haskell, ich habe den Abschnitt zum Definieren von Datentypen von LYAH gelesen und versuche den Sum-Product-Algorithmus für die Belief Propagation zu implementieren. Eine der rudimentären Aufgaben besteht darin, das probabilistische grafische Modell zu definieren.Haskell-Datentyp für Hmatrix Vektor und Matrix

Wie unten gezeigt, habe ich versucht, einen Graphen zu erstellen, indem ich den Knoten verknotete, um den Graphen darzustellen, wo jeder Knoten eine Gaußsche Verteilung darstellt und (vorläufig) konstante Gewichtsverknüpfungen zu seinen Nachbarn hat. Beim Versuch, die Mittelwerte und Kovarianztypen zu definieren, habe ich jedoch Schwierigkeiten, die Typen der Matrix- und Vektortypen anzugeben, d. H. Float oder Double.

module Graph(Graph) where 

import Numeric.LinearAlgebra 

data Mean = Mean Vector 
data Covariance = Covariance Matrix 
data Gaussian = Gaussian Mean Covariance 

data Node = Node [Node] Gaussian 
data Graph = Graph [Node] 

In diesem einfachen Beispiel, was ist die Syntax Doppel Mittelwert als Vektor vom Typ Double und Kovarianz als Matrix des Typs zu definieren. Außerdem, wie würde man verallgemeinern, so dass Mean und Covariance vom Typ Float oder Double sein können?

ich derzeit folgende von GHCi

Graph.hs:5:18: error: 
    • Expecting one more argument to ‘Vector’ 
     Expected a type, but ‘Vector’ has kind ‘* -> *’ 
    • In the type ‘Vector’ 
     In the definition of data constructor ‘Mean’ 
     In the data declaration for ‘Mean’ 
Failed, modules loaded: none. 

ich das hmatrix Paket verwende als here beschrieben

Antwort

2

Vector und Matrix auf dem skalaren Typ parametriert (so können Sie nicht nur Matrizen haben schwimmender -Punkt "reelle Zahlen", aber auch Matrizen von ganzen Zahlen, komplexen Zahlen usw.). Dies ist, was GHC Ihnen von ‘Vector’ has kind ‘* -> *’ sagt: von selbst Vector ist kein Typ (Typen haben Art *, auch bekannt als Type). Eher ist es eine Art Funktion Zuordnung Typen von Art * zu Arten von Art *. Skalare wie Double sind bereits einfache Typen, Sie können also einfach Vector auf sie anwenden.

GHCi> :kind Vector 
Vector :: * -> * 
GHCi> :k Double 
Double :: * 
GHCi> :k Vector Double 
Vector Double :: * 

So müssen Sie

newtype Mean = Mean (Vector Double) 
newtype Covariance = Covariance (Matrix Double) 

(newtype macht das Gleiche wie data hier, aber es ist ein bisschen effizienter, da keine zusätzliche Box/Zeiger benötigt wird).

Alternativ können Sie sinnvollere Vektorräume verwenden, z.

import Math.LinearMap.Category 

newtype Mean v = Mean v 
newtype Covariance v = Covariance (v +> DualVector v) 

Der Vorteil hierbei ist, dass die Abmessungen bei der Kompilierung geprüft werden, welche Fehler böse Laufzeit verhindert (und im Prinzip auch die Leistung verbessern, wenn auch offen die linearmap-category Bibliothek überhaupt noch nicht optimiert ist).

Sie würden dann auch die anderen Typen über den Vektorraum parametrisieren:

data Gaußian v = Gaußian (Mean v) (Covariance v) 
data Node v = Node [Node v] (Gaussian v) 
data Graph v = Graph [Node v] 

Etwas ohne Bezug auf Ihre Frage: dieser Knoten-Bindung sicher fühlt elegant, aber es ist nicht wirklich ein geeignetes Mittel, um eine Grafik zu repräsentieren , weil Knoten nicht identitätsüberprüft werden können. Alle Zyklen in dem Graph führen zu allen unterscheidbaren Mitteln zu einer unendlichen Struktur. In der Praxis kommen Sie nicht herum und geben Ihren Knoten z. Int Etiketten und halten eine separate Struktur für die Kanten.

+0

Was für eine fantastische Antwort; Danke! Das hat ein paar Dinge für mich geklärt. Ich hatte einige Zweifel an der Knotenbindung und schuf unbeabsichtigt eine unendliche Struktur.Der andere Weg (Adjazenzmatrizen usw.) schien einfach unelegant zu sein. –

Verwandte Themen