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:
Post a Comment