Monday, March 1, 2010

Here’s today’s installment. With this version, I am moving away from a declarative style in the code in favor of objects. This make it simpler to add things like intelligent ordering of proof tests, etc. I did manage to keep the case logic delcarative.

This simple beginning doesn’t yet add very much to previous versions. In fact, it's a temporary step back before hopefully moving forward again. I post it now in case the enhancements are delayed. A few of things that I should point out are:

1) This version adds the concept of proven certainty vs. estimated certainty. This will facilitate later enhancements using estimated results to order queries, etc.

2) I have temporarily removed the idea of short circuiting on anything less than the most extreme certainties (Impossible, Certain). This will be re-added later.

3) I have temporarily removed the ability to continue searching on a disjunction until the most certain hypothesis is proven; it now stops on the first hypothesis proven. This will be re-added later.

4) I added back the ability to query the user for a Boolean.

As always, there is no exhaustive quality control on this; use it at your own risk.

open System


///<summary>Query helper.</summary>
let internal GetBoolean q =
printf "%s " q
let key = Console.ReadKey().KeyChar
printfn ""
(key='y')||(key='t')|| (key='Y')||(key='T')


///<summary>Degree of certainty.</summary>
type Certainty =
| Impossible = 0
| Disproven = 1
| Unlikely = 2
| Possible = 3
| Likely = 4
| Proven = 5
| Certain = 6


///<summary>Minimum (Certainty).</summary>
let Min c0 c1 =
match (c0<c1) with
| true -> c0
| false -> c1


///<summary>Maximum (Certainty).</summary>
let Max c0 c1 =
match (c0>c1) with
| true -> c0
| false -> c1


///<summary>Nature of the proof.</summary>
type Proof =
| Estimated = 0
| Known = 1


///<summary>Evidence for an hypothesis.</summary>
type Evidence = {
Certainty : Certainty;
Proof : Proof; }


///<summary>Most certain evidence.</summary>
let MostCertain e0 e1 =
match (e0.Certainty>=e1.Certainty) with
| true -> e0
| false -> e1


///<summary>Returns the best of two evidences.</summary>
let Best e0 e1 =
match e0.Proof with
| Proof.Known ->
match e1.Proof with
| Proof.Known -> MostCertain e0 e1
| _ -> e0
| _ ->
match e1.Proof with
| Proof.Known -> e1
| _ -> MostCertain e0 e1


///<summary>Hypothesis base.</summary>
[<AbstractClass>]
type Hypothesis (name:string) =

let mutable evidence = {
Certainty=Certainty.Impossible;
Proof=Proof.Estimated }

member this.Name = name

member this.Evidence = evidence

member this.Certainty
with get() = evidence.Certainty
and set c = evidence <- { Certainty=c;
Proof=Proof.Known }

member this.Proof with get() = evidence.Proof

abstract Prove : unit->Evidence


///<summary>A constant fact.</summary>
type Fact (name:string,
certainty:Certainty) =
inherit Hypothesis (name)

do (base.Certainty<-certainty)

override this.Prove () = base.Evidence


///<summary>A boolean-queried fact.</summary>
type QueryBoolean (name:string,
query:string) =
inherit Hypothesis (name)

override this.Prove () =
match base.Evidence.Proof with
| Proof.Known -> base.Evidence
| _ ->
base.Certainty <-
match GetBoolean(query) with
| true -> Certainty.Certain
| false -> Certainty.Impossible
base.Evidence


///<summary>Compound hypothesis.</summary>
[<AbstractClass>]
type HypothesisCompound (name:string,
antecedents:Hypothesis list) =
inherit Hypothesis (name)


///<summary>Conjunctive hypothesis.</summary>
type Conjunction (name:string,
antecedents:Hypothesis list) =
inherit HypothesisCompound (name,
antecedents)

member private this.prove (l:Hypothesis list) =
match l with
| [] -> Certainty.Certain
| h::[] -> h.Prove().Certainty
| h::t ->
match h.Prove().Certainty with
| Certainty.Impossible -> Certainty.Impossible
| c -> Min c (this.prove(t))

override this.Prove () =
match base.Evidence.Proof with
| Proof.Known -> base.Evidence
| _ ->
base.Certainty <- this.prove antecedents
base.Evidence


///<summary>Disjunctive hypothesis.</summary>
type Disjunction (name:string,
antecedents:Hypothesis list) =
inherit HypothesisCompound (name,
antecedents)

member private this.prove (l:Hypothesis list) =
match l with
| [] -> Certainty.Certain
| h::[] -> h.Prove().Certainty
| h::t ->
match h.Prove().Certainty with
| Certainty.Certain -> Certainty.Certain
| c -> Max c (this.prove(t))

override this.Prove () =
match base.Evidence.Proof with
| Proof.Known -> base.Evidence
| _ ->
base.Certainty <- this.prove antecedents
base.Evidence


// Tests.

let f0 = Fact("f0", Certainty.Certain)
let f1 = Fact("f1", Certainty.Certain)
let f2 = Fact("f2", Certainty.Certain)

let q0 = QueryBoolean("q0", "Is it q0?")
let q1 = QueryBoolean("q1", "Is it q1?")
let q2 = QueryBoolean("q2", "Is it q2?")

let c0 = Conjunction("c0", [ f0; q0 ])
let c1 = Conjunction("c1", [ f1; q1 ])
let c2 = Conjunction("c2", [ f2; q2 ])

let c01 = Conjunction("c01", [ c0; c1 ])

let d0 = Disjunction("d0", [ c01; c2 ])

let x0 = d0.Prove()

printfn "%s %s"
(x0.Certainty.ToString())
(x0.Proof.ToString())

Console.ReadLine() |> ignore

No comments: