123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120(** {1:axiom Axioms}
we use a wrap type to denote extremes, ideally this is just a float
but the challenge is we don't know they final type ahead of time (int, float,
ast) so we
prefigure it as we need it for some algorithms e.g djikstra. We assume that
- {i `Inf} for positive infinity
- {i `NegInf} for negative infinity
- {i `Val x} for x which is a realised value
- {i `Nan} for not a number and a substitute for "null" or least element
*)(** {3:space Space}
this is an ast mainly used when doing path finding or flow algorithms in
the graph. It allows you to bring in your own implementation of the edge.
Example valid structure are `Float` or `Int`.*)moduletypeSpace=sigtypetincludeSet.OrderedTypewithtypet:=tvalzero:tvalone:tvaladd:t->t->tvalsub:t->t->tvalmin:t->t->tvalmax:t->t->tvalneg:t->tend(** wraps a value a for our internal use *)type+!'awrap=[`Inf|`NegInf|`Nan|`Valof'a](** compare 2 values, if both are external values the we apply your provided
compare function through f. example for a float value:
{@ocaml[
let x = Axiom.wcompare (Float.compare) (`Val 0.) (`Val 0.) = 0;;
let y = Axiom.wcompare (Float.compare) (`Inf) (`Val 0.) = 1;;
let z = Axiom.wcompare (Float.compare) (`Val 0.) (`Inf) = -1;;
]}
*)letwcompareflr=match(l,r)with|(`Vall',`Valr')->fl'r'|(`Inf,`Inf)->0|(`NegInf,`NegInf)->0|(`Nan,`Nan)->0|(`NegInf,`Inf)->-1|(`NegInf,`Val_)->-1|(`Val_,`Inf)->-1|(`Nan,`Inf)->-1|(`Nan,`NegInf)->-1|(`Nan,`Val_)->-1|(`Inf,`NegInf)->1|(`Val_,`NegInf)->1|(`Inf,`Val_)->1|(`Inf,`Nan)->1|(`NegInf,`Nan)->1|(`Val_,`Nan)->1;;(** Apply a function only to internal values, otherwise raise a not found
exception
{@ocaml[
let x = Axiom.wapply (Float.add) (`Val 1.) (`Val 1.) = 2.;;
let y = Axiom.wapply (Float.add) (`Inf) (`Val 0.) = exception Not_found;;
let z = Axiom.wapply (Float.add) (`Val 0.) (`Inf) = exception Not_found;;
]}
*)letwapplyfl=matchlwith|`Valx->fx|_->raiseNot_found;;(** Similar to `Axiom.wapply` but returns a left or right value if no value is
present
{@ocaml[
let x = Axiom.wbind (Float.add) (`Val 1.) (`Val 1.) = 2.;;
let y = Axiom.wbind (Float.add) (`Inf) (`Val 0.) = `Inf;;
let z = Axiom.wbind (Float.add) (`Val 0.) (`Inf) = `Inf;;
]}
*)letwbindflr=match(l,r)with|(`Vall',`Valr')->(`Val(fl'r'))|(x,`Val_)->x|(`Val_,y)->y|(x',_y')->x';;(** convert to string after apply (f x) for `Val x if `Val is present *)letstring_of_wrapfv=matchvwith|`Inf->"`Inf"|`NegInf->"`NegInf"|`Nan->"`Nan"|`Valx->Format.sprintf("`Val %s")(fx);;(** minimum value with compare function f *)letwminflr=if(wcompareflr)=-1thenlelser;;(** maximum value with compare function f *)letwmaxflr=if(wcompareflr)=1thenlelser;;(** negates a value *)letwnegfv=matchvwith|`Inf->`NegInf|`NegInf->`Inf|`Nan->`Nan|`Valx->`Val(fx);;