diff --git a/src/lib/CoAlgLogics.ml b/src/lib/CoAlgLogics.ml index 6474c4526532a6b9653321661be90ae70dfac1fc..1b89a2b3975bc1a775a52aa4c2dd6408bcdbffec 100644 --- a/src/lib/CoAlgLogics.ml +++ b/src/lib/CoAlgLogics.ml @@ -59,20 +59,20 @@ let mkRuleList_MultiModalK sort bs sl = *) bsetFold getRules bs [] -let mkRule_MultiModalK sort bs sl = +let mkRule_MultiModalK sort bs sl : stateExpander = let rules = mkRuleList_MultiModalK sort bs sl in let res = ref (Some rules) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; - AllInOne rules + AllInOne rules) (* TODO: test it with: make && ./coalg sat <<< $'<R> False \n [R] False \n [R] True' *) -let mkRule_MultiModalKD sort bs sl = +let mkRule_MultiModalKD sort bs sl : stateExpander = assert (List.length sl = 1); (* TODO: Why? *) let s1 = List.hd sl in (* [s1] = List.hd sl *) let roles = S.makeBS () in @@ -131,11 +131,12 @@ let mkRule_MultiModalKD sort bs sl = (* TODO: replace cannonical wrapper by helper function *) let res = ref (Some rules) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; AllInOne rules + ) (* CoalitionLogic: helper functions *) @@ -196,7 +197,7 @@ let compatible sort (a: bset) formula1 = / \i=1 a_i /\ b / \j=1 c_j *) -let mkRule_CL sort bs sl = +let mkRule_CL sort bs sl : stateExpander = assert (List.length sl = 1); (* TODO: Why? *) let s1 = List.hd sl in (* [s1] = List.hd sl *) let boxes = bsetFilter bs (fun f -> lfGetType sort f = EnforcesF) in @@ -263,13 +264,13 @@ let mkRule_CL sort bs sl = (* standard return procedure *) let res = ref (Some rules) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; - AllInOne rules + AllInOne rules) -let mkRule_GML sort bs sl = +let mkRule_GML sort bs sl : stateExpander = assert (List.length sl = 1); let s1 = List.hd sl in (* [s1] = List.hd sl *) let diamonds = bsetFilter bs (fun f -> lfGetType sort f = MoreThanF) in @@ -316,13 +317,13 @@ let mkRule_GML sort bs sl = (* standard return procedure *) let res = ref (Some rules) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; - AllInOne rules + AllInOne rules) -let mkRule_Choice sort bs sl = +let mkRule_Choice sort bs sl : stateExpander = assert (List.length sl = 2); let dep bsl = assert (List.length bsl = 2); @@ -351,14 +352,14 @@ let mkRule_Choice sort bs sl = let s2 = List.nth sl 1 in let res = ref (Some [(dep, [(s1, bs1); (s2, bs2)])]) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; - AllInOne rules + AllInOne rules) -let mkRule_Fusion sort bs sl = +let mkRule_Fusion sort bs sl : stateExpander = assert (List.length sl = 2); let dep proj bsl = assert (List.length bsl = 1); @@ -386,11 +387,11 @@ let mkRule_Fusion sort bs sl = let s2 = List.nth sl 1 in let res = ref (Some [(dep 0, [(s1, bs1)]); (dep 1, [(s2, bs2)])]) in fun () -> - match !res with + Conjunctive (match !res with | None -> NoMoreRules | Some rules -> res := None; - AllInOne rules + AllInOne rules) (* Maps a logic represented by the type "functors" to the corresponding diff --git a/src/lib/CoAlgMisc.ml b/src/lib/CoAlgMisc.ml index 3d9c9643dbc58d277c94368c4f3ef473fdf21024..995698d40ebca456c24b0035e7982cb6e9088373 100644 --- a/src/lib/CoAlgMisc.ml +++ b/src/lib/CoAlgMisc.ml @@ -121,7 +121,10 @@ and setCnstr = unit GHt.t (* Types that are hard coded into the algorithm *) (*****************************************************************************) -and stateExpander = unit -> ruleEnumeration +and 'a junction = | Disjunctive of 'a (*specifies that any of the 'a needs to be satifsfied *) + | Conjunctive of 'a (*specifies that all of the 'a need to be satifsfied *) + +and stateExpander = unit -> ruleEnumeration junction and sort = C.sort @@ -132,9 +135,12 @@ and nodeStatus = | Unsat and dependencies = bset list -> bset + +and rule = (dependencies * (sort * bset) list) + and ruleEnumeration = - | AllInOne of (dependencies * (sort * bset) list) list - | NextRule of dependencies * (sort * bset) list + | AllInOne of rule list + | NextRule of rule | NoMoreRules type nominal = sort * localFormula @@ -167,6 +173,35 @@ exception CoAlg_finished of bool let sortTable = ref (Array.make 0 (MultiModalK, [1])) +let junctionEvalBool : (bool list junction) -> bool = function + | Disjunctive l -> List.fold_right (||) l false + | Conjunctive l -> List.fold_right (&&) l true + +let junctionEval (f: 'a -> bool) : 'a list junction -> bool = function + | Disjunctive l -> List.fold_right (fun x y -> (f x) || y) l false + | Conjunctive l -> List.fold_right (fun x y -> (f x) && y) l true + +let optionalizeOperator (f: 'a -> 'b -> 'c) (x: 'a option) (y: 'b option) : 'c option = + match x with + | None -> None + | Some x -> (match y with + | None -> None + | Some y -> Some (f x y)) + +let junctionEvalBoolOption : bool option list junction -> bool option = + let f extreme op x y = (* ensure that: (Some True) || None = Some True *) + if x = extreme || y = extreme + then extreme + else optionalizeOperator op x y + in function + | Disjunctive l -> + List.fold_right (f (Some true) (||)) l (Some false) + | Conjunctive l -> + List.fold_right (f (Some false) (&&)) l (Some true) + +let junctionExtract : 'a junction -> ('a * ('b -> 'b junction)) = function + | Disjunctive l -> (l, fun x -> Disjunctive x) + | Conjunctive l -> (l, fun x -> Conjunctive x) (*****************************************************************************) (* "Module type" and a specific implementation of the main queue *) diff --git a/src/lib/CoAlgMisc.mli b/src/lib/CoAlgMisc.mli index 2c80349a9d14ac63b7e789051b54ef18c8703c93..15fdb34c9effa31a597f4a55ed17f52aaf4dab12 100644 --- a/src/lib/CoAlgMisc.mli +++ b/src/lib/CoAlgMisc.mli @@ -55,12 +55,14 @@ type setCore type setCnstr - (*****************************************************************************) (* Types that are hard coded into the algorithm *) (*****************************************************************************) -and stateExpander = unit -> ruleEnumeration +and 'a junction = | Disjunctive of 'a (*specifies that any of the 'a needs to be satifsfied *) + | Conjunctive of 'a (*specifies that all of the 'a need to be satifsfied *) + +and stateExpander = unit -> ruleEnumeration junction and sort = CoAlgFormula.sort @@ -71,9 +73,12 @@ and nodeStatus = | Unsat and dependencies = bset list -> bset + +and rule = (dependencies * (sort * bset) list) + and ruleEnumeration = - | AllInOne of (dependencies * (sort * bset) list) list - | NextRule of dependencies * (sort * bset) list + | AllInOne of rule list + | NextRule of rule | NoMoreRules type nominal = sort * localFormula @@ -88,7 +93,7 @@ type constrnt = | OpenC of node list | UnexpandedC of node list -type propagateElement = +type propagateElement = (* TODO: What does the prefix "U" mean? unsat? *) | UState of state * int option | UCore of core * bool | UCnstr of cset @@ -106,6 +111,17 @@ exception CoAlg_finished of bool val sortTable : sortTable ref +(* evaluate a junction in the obvious way *) +val junctionEvalBool : bool list junction -> bool +val junctionEval: ('a -> bool) -> 'a list junction -> bool +val optionalizeOperator: ('a -> 'b -> 'c) -> ('a option -> 'b option -> 'c option) +val junctionEvalBoolOption : bool option list junction -> bool option + +(* decompose a junction in it's content and its constructor, + such that: eval∘junctionExtract = id + (with eval: X × (X -> Y) -> Y) + *) +val junctionExtract: 'a junction -> ('a * ('b -> 'b junction)) (*****************************************************************************) (* "Module type" and a specific implementation of the main queue *) @@ -176,7 +192,7 @@ val stateGetRules : state -> (dependencies * core list) list val stateAddRule : state -> dependencies -> core list -> int val stateGetConstraints : state -> csetSet val stateSetConstraints : state -> csetSet -> unit -val stateNextRule : state -> ruleEnumeration +val stateNextRule : state -> ruleEnumeration junction (*****************************************************************************) diff --git a/src/lib/CoAlgReasoner.ml b/src/lib/CoAlgReasoner.ml index 58caaa08a50f6b5a830f97005f50c2801b36b341..81eb2ffee7fb10a0a0dd2a2528ecb5d85a223958 100644 --- a/src/lib/CoAlgReasoner.ml +++ b/src/lib/CoAlgReasoner.ml @@ -515,35 +515,68 @@ let insertCore sort bs = c | Some c -> c -let insertRule state dep chldrn = - let insert (isUns, acc) (sort, bs) = + (* tells whether inserting the rule makes it satisfiable: + Some true -> surely satisfiable + Some false -> surely unsat + None -> Not known yet + *) +let insertRule state dep (chldrn: (sort * bset) list junction) : bool option = + let (chldrn, junc) = junctionExtract chldrn in + let insert (sort, bs) = (* checks if the given child node has some sat-state *) let bs1 = bsetAddTBox sort bs in - let core = insertCore sort bs1 in - let isUns1 = if coreGetStatus core = Unsat then isUns else false in - (isUns1, core::acc) + insertCore sort bs1 in - let (isUnsat, children) = List.fold_left insert (true, []) chldrn in + let children : core list = List.map insert chldrn in + (* get the sat-states of all the children, throw it back into a junction + (i.e. disjunction or conjunction) and then evaluate it *) + let satStateChildren = + let child2satState core = match (coreGetStatus core) with + | Unsat -> Some false + | Sat -> Some true + | Expandable -> None (* unknown state *) + | Open -> None (* unknown state *) + in + junctionEvalBoolOption (junc (List.map child2satState children)) + in + let isUnsat = (satStateChildren = Some false) in + (* find out satisfiability *) let idx = stateAddRule state dep (List.rev children) in List.iter (fun c -> coreAddParent c state idx) children; if isUnsat then begin propagateUnsat [UState (state, Some idx)]; - false - end else true - -let rec insertAllRules state = function - | [] -> true - | (dep, chldrn)::tl -> - let notUnsat = insertRule state dep chldrn in - if notUnsat then insertAllRules state tl else false + Some false + end else None + + (* tells whether it is satisfiable: + Some true -> surely satisfiable + Some false -> surely unsat + None -> Not known yet + *) +let rec insertAllRules state : rule list junction -> bool option = function + | Conjunctive [] -> Some true + | Disjunctive [] -> Some false + | Conjunctive ((dep, chldrn)::tl) -> + let satState = insertRule state dep (Conjunctive chldrn) in + if satState <> Some false (* if notUnsat*) + then insertAllRules state (Conjunctive tl) + else Some false + | Disjunctive ((dep, chldrn)::tl) -> + let satState = insertRule state dep (Disjunctive chldrn) in + if satState <> Some true (* if not Sat *) + then insertAllRules state (Disjunctive tl) + else Some true let expandState state = - match stateNextRule state with + let (rules, _) = junctionExtract (stateNextRule state) in + match rules with | AllInOne rules -> - let notUnsat = insertAllRules state rules in - if notUnsat then stateSetStatus state Open + let (_, junction) = junctionExtract (stateNextRule state) in + let satState = insertAllRules state (junction rules) in + if satState <> Some false (* i.e. if not Unsat *) then stateSetStatus state Open | NextRule (dep, chldrn) -> - let notUnsat = insertRule state dep chldrn in - if notUnsat then queueInsertState state else () + let (_, junction) = junctionExtract (stateNextRule state) in + let satState = insertRule state dep (junction chldrn) in + if satState <> Some false (* if notUnsat *) then queueInsertState state else () | NoMoreRules -> stateSetStatus state Open