File: members-factors.fs

package info (click to toggle)
fsharp 4.0.0.4%2Bdfsg2-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 58,824 kB
  • ctags: 1,395
  • sloc: cs: 2,983; ml: 1,098; makefile: 410; sh: 409; xml: 113
file content (288 lines) | stat: -rw-r--r-- 9,791 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// #Regression #Conformance #MemberDefinitions #ObjectOrientedTypes #Classes 
//---------------------------------------------------------------
// lists.fs     F# source file of generic data types
//
// 2006 written by Ralf Herbrich
// Microsoft Research Ltd.
//---------------------------------------------------------------

#if ALL_IN_ONE
module Core_members_factors
#endif

let failures = ref []

let report_failure (s : string) = 
    stderr.Write" NO: "
    stderr.WriteLine s
    failures := !failures @ [s]

let test (s : string) b = 
    stderr.Write(s)
    if b then stderr.WriteLine " OK"
    else report_failure (s)

let check s b1 b2 = test s (b1 = b2)

open System.Collections.Generic

type Matrix = M of int
  with 
   member x.NoRows = 0 
   member x.NoColumns = 0 
   member x.Item with get((i:int),(j:int)) = 0.0
  end
  
module Types = begin
  /// Shorthand notation for .NET 2.0 Lists
  type ResizeArray<'a> = List<'a>
end

open Types
module ResizeArray = begin
  /// Maps a ResizeArray to another ResizeArray by application of the function f to every element.
  let map f (r:ResizeArray<_>) : ResizeArray<_> = r.ConvertAll (fun x -> f x)

  /// Iterates the function f for every element of the ResizeArray.
  let iter f (r:ResizeArray<_>) = r.ForEach (fun x -> f x)

  /// Creates a ResizeArray from a List.
  let of_list l :ResizeArray<_> = new ResizeArray<_>(List.toArray l)
end

//---------------------------------------------------------------
// distribution.fs      F# source file of the abstract distribution class
//
// 2006 written by Ralf Herbrich
// Microsoft Research Ltd.
//---------------------------------------------------------------


//***************************************************
// Abstract distribution base class 
//***************************************************

/// An abstract class for probability distributions in the exponential family.
type IDistribution = 
  interface 
        /// Gets a sample from the distribution.
        abstract member Sample : int -> System.Random -> Matrix
        /// Computes the probability density value at a particular point.
        abstract member Density : Matrix -> float
        /// Computes the absolute change between two distributions.
        abstract member AbsoluteDifference : IDistribution -> float
  end
  
//***************************************************
// Abstract distribution operation class 
//***************************************************

/// The list of distribution operations (at the moment, this is just the constant distribution).
type DistributionOps<'Distribution> =
  interface
    /// The constant function distribution.
    abstract One : 'Distribution
  end

//---------------------------------------------------------------
// distributions.fs     F# source file of the distributions library
//
// 2006 written by Ralf Herbrich
// Microsoft Research Ltd.
//---------------------------------------------------------------

   
//***************************************************
// 1D Gaussian
//***************************************************

/// The 1D Gaussian class for probability distribtion.
type Gaussian1D =
  class 
    /// The precision mean of the Gaussian
    val tau : float
    /// The precision of the Gaussian
    val pi : float
    
    /// The standard constructor.
    new () = 
      { tau = 0.0; pi = 0.0; }
    /// The parameterised constructor.
    new (precisionMean, precision) = 
      { tau = precisionMean; pi = precision; }
    
    /// Precision of the Gaussian.
    member x.Precision with get() = x.pi
    /// Precision times mean of the Gaussian.
    member x.PrecisionMean with get() = x.tau
    /// Mean of the Gaussian (Mu).
    member x.Mean with get () = x.tau / x.pi
    /// Variance of the Gaussian (Sigma^2).
    member x.Variance with get () = 1.0 / x.pi

    member x.Density (point:Matrix) = 
        if (point.NoRows > 1 || point.NoColumns > 1) then
          failwith "This is a 1D distribution which cannot have a density of multidimensional points."
        else
          let diff = point.Item(1,1) - x.Mean in 
          sqrt (x.Precision / (2.0 * System.Math.PI)) * exp (-diff * x.Precision * diff / 2.0)
          
      /// Absolute difference between two Gaussians 
    member x.AbsoluteDifference (y: Gaussian1D) = 
      max (abs (x.PrecisionMean - y.PrecisionMean)) (abs (x.Precision - y.Precision)) 
        
      /// Samples a 1D Gaussian
    member x.Sample (numberOfSamples:int) random = M 1
    
    interface IDistribution with 
      override x.Density point =  x.Density (point)
      override x.AbsoluteDifference distribution = 
          match distribution with
          | :? Gaussian1D as gaussian1D -> x.AbsoluteDifference (gaussian1D)
          | _ -> failwith "Wrong distribution"

      override x.Sample numberOfSamples random = x.Sample numberOfSamples random
    end
    
    /// String representation of a 1D Gaussian
    override x.ToString() = "[" + x.Mean.ToString () + "," + (sqrt (x.Variance)).ToString () + "]"
  end

//***************************************************
// The distribution operations of a 1D Gaussian
//***************************************************

let GaussianDistributionOps = { new DistributionOps<Gaussian1D>  with
                                    member __.One = new Gaussian1D (0.0 , 0.0) }



//---------------------------------------------------------------
// factorgraph.fs   F# source file of the factor graph library
//
// 2006 written by Ralf Herbrich
// Microsoft Research Ltd.
//---------------------------------------------------------------

open System.Collections.Generic

//***************************************************
// The variable node interface
//***************************************************

/// A single variable node in a factor graph. This is the non-mutable interface.
type IVariableNode =
  interface
    /// The marginal distribution of the variable.
    abstract Distribution : IDistribution
  end

//***************************************************
// The specific variable node class
//***************************************************

/// A single variable in a factor graph.
type VariableNode<'Distribution> when 'Distribution :> IDistribution =
  class
    interface IVariableNode with
      /// Just return the distribution
      member x.Distribution = x.distribution :> IDistribution
    end
    
    /// The marginal distribution of the variable.
    val mutable distribution : 'Distribution
    
    /// Sets up a new variable node
    new (dOps : DistributionOps<_>) = { distribution = dOps.One; }
  end

//***************************************************
// The factor node interface
//***************************************************

/// The computation nodes (i.e. factor nodes) of a factor graph.
type IFactorNode =
  interface
    /// The list of all variables that this factor "talks" to.
    abstract VariableNodes : IEnumerable< IVariableNode >
    /// The list of messages from the factor to all its variables.
    abstract Messages : IEnumerable< IDistribution >
    /// Abstract update (computation) mechansim
    abstract UpdateMessage : int -> float 
  end

(*
/// A factor graph node.
type FactorGraphNode = 
  {
    /// The internal ID of a factor graphs node.
    ID      : int;
    /// The X coordinate of the factor graph node.
    X       : float;
    /// The Y coordinate of the factor graph node.
    Y       : float;
    /// The name of the node.
    Name    : string;
  }*)

//---------------------------------------------------------------
// factornodes.fs   F# source file of several factor nodes
//
// 2006 written by Ralf Herbrich
// Microsoft Research Ltd.
//---------------------------------------------------------------

open System

(*
let Gaussian1DPriorFactorNode ((var: VariableNode<Gaussian1D>), mean, variance) =
  //let message = ref  GaussianDistributionOps.One in 
  { new IFactorNode 
  with UpdateMessage i =
      if i > 0 then 
        raise (new ArgumentOutOfRangeException ("iVariableIndex", "This factor only points to one variable."));
      let oldMarginal = var.distribution in
      let newMarginal = new Gaussian1D (mean / variance + oldMarginal.PrecisionMean, 1.0 / variance + oldMarginal.Precision) in
      var.distribution <- newMarginal;
      oldMarginal.AbsoluteDifference (newMarginal)
  and get_Messages() = Seq.ofList [ ] //(!message :> IDistribution) ]
  and get_VariableNodes() = Seq.ofList [ (var :> IVariableNode) ] }
*)

let OneVariableNode((var: VariableNode<_>),f) =
 // let message = ref  (new Gaussian1D(0.0,0.0) ) in 
  { new IFactorNode  with
      member __.UpdateMessage i =
          if i > 0 then 
            raise (new ArgumentOutOfRangeException ("iVariableIndex", "This factor only points to one variable."));
          let oldMarginal = var.distribution in
          let newMarginal = f oldMarginal in
          var.distribution <- newMarginal;
          (oldMarginal :> IDistribution).AbsoluteDifference (newMarginal)
      member __.Messages = Seq.ofList [ (* (!message :> IDistribution) *) ]
      member __.VariableNodes = Seq.ofList [ (var :> IVariableNode) ] }

let Gaussian1DPriorFactorNode((var: VariableNode<Gaussian1D>), mean, variance) =
  let update (oldMarginal : Gaussian1D) = new Gaussian1D (mean / variance + oldMarginal.PrecisionMean, 1.0 / variance + oldMarginal.Precision) in
  OneVariableNode(var, update)
  

//---------------------------------------------------------------------
// Finish up



#if ALL_IN_ONE
let RUN() = !failures
#else
let aa =
  match !failures with 
  | [] -> 
      stdout.WriteLine "Test Passed"
      System.IO.File.WriteAllText("test.ok","ok")
      exit 0
  | _ -> 
      stdout.WriteLine "Test Failed"
      exit 1
#endif