module QBF.Analysis
(
basicPropositionalAnalysis
, mkStatSymbItems
, mkStatSymbMapItem
, inducedFromMorphism
, inducedFromToMorphism
, signatureColimit
)
where
import Common.ExtSign
import Common.Lib.Graph
import Common.SetColimit
import Data.Graph.Inductive.Graph
import Propositional.Sign as Sign
import qualified Common.AS_Annotation as AS_Anno
import qualified Common.GlobalAnnotations as GlobalAnnos
import qualified Common.Id as Id
import qualified Common.Result as Result
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified QBF.AS_BASIC_QBF as AS_BASIC
import qualified QBF.Morphism as Morphism
import qualified QBF.Symbol as Symbol
import Control.Arrow
data DIAGFORM = DiagForm
{
formula :: AS_Anno.Named AS_BASIC.FORMULA,
diagnosis :: Result.Diagnosis
}
data NUMFORM = NumForm
{
nfformula :: AS_Anno.Annoted AS_BASIC.FORMULA
, nfnum :: Integer
}
data TESTSIG = TestSig
{
msign :: Sign.Sign
, occurence :: Int
, tdiagnosis :: [Result.Diagnosis]
}
makeSig ::
AS_BASIC.BASICSPEC
-> Sign.Sign
-> TESTSIG
makeSig (AS_BASIC.BasicSpec spec) sig = List.foldl retrieveBasicItem
TestSig { msign = sig
, occurence = 0
, tdiagnosis = []
}
spec
retrieveBasicItem ::
TESTSIG
-> AS_Anno.Annoted AS_BASIC.BASICITEMS
-> TESTSIG
retrieveBasicItem tsig x =
let
occ = occurence tsig
in
case AS_Anno.item x of
(AS_BASIC.PredDecl apred) ->
if occ == 0
then
List.foldl
(\ asig ax -> TestSig {
msign = Sign.addToSig (msign asig)
$ Id.simpleIdToId ax
, occurence = occ
, tdiagnosis = tdiagnosis tsig ++
[Result.Diag
{
Result.diagKind = Result.Hint
, Result.diagString = "All fine"
, Result.diagPos = AS_Anno.opt_pos x
}]
})
tsig $ (\ (AS_BASIC.PredItem xs _) -> xs) apred
else
List.foldl
(\ asig ax -> TestSig {
msign = Sign.addToSig (msign asig)
$ Id.simpleIdToId ax
, occurence = occ
, tdiagnosis = tdiagnosis tsig ++
[Result.Diag
{
Result.diagKind = Result.Error
, Result.diagString =
"Definition of proposition " ++
show (pretty ax) ++
" after first axiom"
, Result.diagPos = AS_Anno.opt_pos x
}]
})
tsig $ (\ (AS_BASIC.PredItem xs _) -> xs) apred
(AS_BASIC.AxiomItems _) -> TestSig { msign = msign tsig
, occurence = occ + 1
, tdiagnosis = tdiagnosis tsig ++
[Result.Diag
{
Result.diagKind = Result.Hint
, Result.diagString =
"First axiom"
, Result.diagPos =
AS_Anno.opt_pos x
}]
}
makeFormulas ::
AS_BASIC.BASICSPEC
-> Sign.Sign
-> [DIAGFORM]
makeFormulas (AS_BASIC.BasicSpec bspec) sig =
List.foldl (\ xs bs -> retrieveFormulaItem xs bs sig) [] bspec
retrieveFormulaItem ::
[DIAGFORM]
-> AS_Anno.Annoted AS_BASIC.BASICITEMS
-> Sign.Sign
-> [DIAGFORM]
retrieveFormulaItem axs x sig =
case AS_Anno.item x of
(AS_BASIC.PredDecl _) -> axs
(AS_BASIC.AxiomItems ax) ->
List.foldl (\ xs bs -> addFormula xs bs sig) axs $ numberFormulae ax 0
numberFormulae :: [AS_Anno.Annoted AS_BASIC.FORMULA] -> Integer -> [NUMFORM]
numberFormulae [] _ = []
numberFormulae (x : xs) i
| label == "" =
NumForm {nfformula = x, nfnum = i} : numberFormulae xs (i + 1)
| otherwise =
NumForm {nfformula = x, nfnum = 0} : numberFormulae xs i
where
label = AS_Anno.getRLabel x
addFormula :: [DIAGFORM]
-> NUMFORM
-> Sign.Sign
-> [DIAGFORM]
addFormula formulae nf sign
| isLegal = formulae ++
[DiagForm
{
formula = makeNamed f i
, diagnosis = Result.Diag
{
Result.diagKind = Result.Hint
, Result.diagString = "All fine"
, Result.diagPos = lnum
}
}]
| otherwise = formulae ++
[DiagForm
{
formula = makeNamed f i
, diagnosis = Result.Diag
{
Result.diagKind = Result.Error
, Result.diagString =
"Unknown propositions "
++ show (pretty difference)
++ " in formula "
++ show (pretty nakedFormula)
, Result.diagPos = lnum
}
}]
where
f = nfformula nf
i = nfnum nf
nakedFormula = AS_Anno.item f
varsOfFormula = propsOfFormula nakedFormula
isLegal = Sign.isSubSigOf varsOfFormula sign
difference = Sign.sigDiff varsOfFormula sign
lnum = AS_Anno.opt_pos f
makeNamed :: AS_Anno.Annoted AS_BASIC.FORMULA -> Integer
-> AS_Anno.Named AS_BASIC.FORMULA
makeNamed f i = (AS_Anno.makeNamed (if label == "" then "Ax_" ++ show i
else label) $ AS_Anno.item f)
{ AS_Anno.isAxiom = not isTheorem }
where
label = AS_Anno.getRLabel f
annos = AS_Anno.r_annos f
isImplies = foldl (\ y x -> AS_Anno.isImplies x || y) False annos
isImplied = foldl (\ y x -> AS_Anno.isImplied x || y) False annos
isTheorem = isImplies || isImplied
propsOfFormula :: AS_BASIC.FORMULA -> Sign.Sign
propsOfFormula (AS_BASIC.Negation form _) = propsOfFormula form
propsOfFormula (AS_BASIC.Implication form1 form2 _) = Sign.unite
(propsOfFormula form1)
(propsOfFormula form2)
propsOfFormula (AS_BASIC.Equivalence form1 form2 _) = Sign.unite
(propsOfFormula form1)
(propsOfFormula form2)
propsOfFormula (AS_BASIC.TrueAtom _) = Sign.emptySig
propsOfFormula (AS_BASIC.FalseAtom _) = Sign.emptySig
propsOfFormula (AS_BASIC.Predication x) = Sign.Sign
{Sign.items = Set.singleton $
Id.simpleIdToId x }
propsOfFormula (AS_BASIC.Conjunction xs _) = List.foldl
(\ sig frm -> Sign.unite sig $ propsOfFormula frm)
Sign.emptySig xs
propsOfFormula (AS_BASIC.Disjunction xs _) = List.foldl
(\ sig frm -> Sign.unite sig $ propsOfFormula frm)
Sign.emptySig xs
propsOfFormula (AS_BASIC.ForAll xs f _) = sigDiff
(propsOfFormula f)
(Sign.Sign (Set.fromList (map Id.simpleIdToId xs)))
propsOfFormula (AS_BASIC.Exists xs f _) = sigDiff
(propsOfFormula f)
(Sign.Sign (Set.fromList (map Id.simpleIdToId xs)))
basicPropositionalAnalysis
:: (AS_BASIC.BASICSPEC, Sign.Sign, GlobalAnnos.GlobalAnnos)
-> Result.Result (AS_BASIC.BASICSPEC,
ExtSign Sign.Sign Symbol.Symbol,
[AS_Anno.Named AS_BASIC.FORMULA])
basicPropositionalAnalysis (bs, sig, _) =
Result.Result diags $ if exErrs then Nothing else
Just (bs, ExtSign sigItems declaredSyms, formulae)
where
bsSig = makeSig bs sig
sigItems = msign bsSig
declaredSyms = Set.map Symbol.Symbol
$ Set.difference (items sigItems) $ items sig
bsForm = makeFormulas bs sigItems
formulae = map formula bsForm
diags = map diagnosis bsForm ++ tdiagnosis bsSig
exErrs = Result.hasErrors diags
mkStatSymbMapItem :: [AS_BASIC.SYMBMAPITEMS]
-> Result.Result (Map.Map Symbol.Symbol Symbol.Symbol)
mkStatSymbMapItem xs =
Result.Result
{
Result.diags = []
, Result.maybeResult = Just $
foldl
(
\ smap x ->
case x of
AS_BASIC.SymbMapItems sitem _ ->
Map.union smap $ statSymbMapItem sitem
)
Map.empty
xs
}
statSymbMapItem :: [AS_BASIC.SYMBORMAP]
-> Map.Map Symbol.Symbol Symbol.Symbol
statSymbMapItem =
foldl
(
\ mmap x ->
case x of
AS_BASIC.Symb sym -> Map.insert
(symbToSymbol sym)
(symbToSymbol sym) mmap
AS_BASIC.SymbMap s1 s2 _
-> Map.insert (symbToSymbol s1) (symbToSymbol s2) mmap
)
Map.empty
mkStatSymbItems :: [AS_BASIC.SYMBITEMS] -> Result.Result [Symbol.Symbol]
mkStatSymbItems a = Result.Result
{
Result.diags = []
, Result.maybeResult = Just $ statSymbItems a
}
statSymbItems :: [AS_BASIC.SYMBITEMS] -> [Symbol.Symbol]
statSymbItems = concatMap symbItemsToSymbol
symbItemsToSymbol :: AS_BASIC.SYMBITEMS -> [Symbol.Symbol]
symbItemsToSymbol (AS_BASIC.SymbItems syms _) = map symbToSymbol syms
symbToSymbol :: AS_BASIC.SYMB -> Symbol.Symbol
symbToSymbol (AS_BASIC.SymbId tok) =
Symbol.Symbol {Symbol.symName = Id.simpleIdToId tok}
pMap :: Map.Map Symbol.Symbol Symbol.Symbol -> Set.Set Id.Id
-> Map.Map Id.Id Id.Id
pMap imap =
Set.fold (
\ x ->
let
symOf = Symbol.Symbol
{ Symbol.symName = x }
y = Symbol.symName
$ Symbol.applySymMap imap symOf
in Map.insert x y
) Map.empty
inducedFromMorphism :: Map.Map Symbol.Symbol Symbol.Symbol
-> Sign.Sign
-> Result.Result Morphism.Morphism
inducedFromMorphism imap sig =
Result.Result
{
Result.diags = []
, Result.maybeResult =
let
sigItems = Sign.items sig
in
Just
Morphism.Morphism
{
Morphism.source = sig
, Morphism.propMap = pMap imap sigItems
, Morphism.target = Sign.Sign
{Sign.items =
Set.map (Morphism.applyMap
(pMap imap sigItems))
$ Sign.items sig
}
}
}
inducedFromToMorphism :: Map.Map Symbol.Symbol Symbol.Symbol
-> ExtSign Sign.Sign Symbol.Symbol
-> ExtSign Sign.Sign Symbol.Symbol
-> Result.Result Morphism.Morphism
inducedFromToMorphism imap (ExtSign sig _) (ExtSign tSig _) =
let
sigItems = Sign.items sig
targetSig = Sign.Sign
{Sign.items =
Set.map
(Morphism.applyMap
(pMap imap sigItems))
$ Sign.items sig
}
isSub = Sign.items targetSig
`Set.isSubsetOf`
Sign.items tSig
in
if isSub then
Result.Result {
Result.diags = []
, Result.maybeResult =
Just Morphism.Morphism
{
Morphism.source = sig
, Morphism.propMap = pMap imap sigItems
, Morphism.target = tSig
}
}
else
Result.Result {
Result.diags =
[
Result.Diag
{
Result.diagKind = Result.Error
, Result.diagString =
"Incompatible mapping"
, Result.diagPos = Id.nullRange
}
]
, Result.maybeResult = Nothing
}
signatureColimit :: Gr Sign.Sign (Int, Morphism.Morphism)
-> Result.Result (Sign.Sign, Map.Map Int Morphism.Morphism)
signatureColimit graph = do
let graph1 = nmap Sign.items $ emap (Control.Arrow.second Morphism.propMap)
graph
(set, maps) = addIntToSymbols $ computeColimitSet graph1
cSig = Sign.Sign {Sign.items = set}
return (cSig,
Map.fromList $ map (\ (i, n) ->
(i, Morphism.Morphism {
Morphism.source = n,
Morphism.target = cSig,
Morphism.propMap = maps Map.! i
})) $ labNodes graph)