summaryrefslogtreecommitdiff
path: root/source/Felix/Checking/Backend/Problem.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Felix/Checking/Backend/Problem.hs')
-rw-r--r--source/Felix/Checking/Backend/Problem.hs1301
1 files changed, 1301 insertions, 0 deletions
diff --git a/source/Felix/Checking/Backend/Problem.hs b/source/Felix/Checking/Backend/Problem.hs
new file mode 100644
index 0000000..0390020
--- /dev/null
+++ b/source/Felix/Checking/Backend/Problem.hs
@@ -0,0 +1,1301 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+-- | Complete-problem FOF/TH0 classification and construction.
+module Felix.Checking.Backend.Problem
+ ( SupportedProposition
+ , supportedProposition
+ , projectSupportedProposition
+ , supportedPropositionSupport
+ , supportedPropositionTerm
+ , weakenClosedSupportedProposition
+ , SupportedPropositionError(..)
+ , SupportedPropositionProjectionError(..)
+ , CheckedFofProjection
+ , checkedFofProjectionProposition
+ , FofCapability(..)
+ , BackendFofExclusion(..)
+ , BackendClassificationError(..)
+ , classifySupportedProposition
+ , TypedBackendFact
+ , typedBackendFact
+ , typedBackendFactReference
+ , typedBackendFactProposition
+ , typedBackendFactCapability
+ , LocalPremiseOrdinal
+ , localPremiseOrdinal
+ , localPremiseOrdinalValue
+ , TypedLocalPremise
+ , typedLocalPremise
+ , typedLocalPremiseOrdinal
+ , typedLocalPremiseOrigin
+ , typedLocalPremiseProposition
+ , typedLocalPremiseCapability
+ , TypedFoundationAuxiliaryInput
+ , typedFoundationAuxiliaryInput
+ , TypedProblemAuxiliary
+ , typedProblemAuxiliaryOrdinal
+ , typedProblemAuxiliaryTag
+ , typedProblemAuxiliaryProposition
+ , typedProblemAuxiliaryCapability
+ , LocalPremisePolicy(..)
+ , HigherOrderJustificationPolicy(..)
+ , selectTypedLocalPremises
+ , TypedProblemRoute(..)
+ , TypedProblem
+ , planTypedProblem
+ , typedProblemRoute
+ , typedProblemClaim
+ , typedProblemGlobalPremises
+ , typedProblemLocalPremises
+ , typedProblemAuxiliaries
+ , typedProblemGlobalTypes
+ , typedProblemLocalTypes
+ , TypedProblemError(..)
+ ) where
+
+import Base
+import Felix.Checking.Core
+import Felix.Checking.Foundation
+
+import Control.Monad (foldM, unless)
+import Data.Bifunctor (first)
+import Data.List qualified as List
+import Data.Map.Strict qualified as Map
+import Data.Set qualified as Set
+import Data.Vector (Vector)
+import Data.Vector qualified as Vector
+import Numeric.Natural (Natural)
+
+
+-- | A proposition under its exact nearest-first ambient-local support.
+data SupportedProposition local global =
+ SupportedProposition
+ !(Vector (local, CoreType))
+ !(ScopedCheckedCore global)
+ deriving stock (Eq)
+
+data SupportedPropositionError local
+ = SupportedPropositionIsNotProposition !CoreType
+ | SupportedPropositionContextMismatch
+ ![CoreType]
+ ![CoreType]
+ | DuplicateSupportedLocal !local
+ | UnusedSupportedLocal !local
+ deriving stock (Show, Eq)
+
+data SupportedPropositionProjectionError local
+ = SupportedProjectionContextMismatch
+ ![CoreType]
+ ![CoreType]
+ | SupportedProjectionDuplicateLocal !local
+ | SupportedProjectionIndexMissing !Natural
+ | SupportedProjectionCoreCheckFailed !CoreCheckError
+ | SupportedProjectionValidationFailed
+ !(SupportedPropositionError local)
+ deriving stock (Show, Eq)
+
+supportedProposition
+ :: Ord local
+ => Vector (local, CoreType)
+ -> ScopedCheckedCore global
+ -> Either
+ (SupportedPropositionError local)
+ (SupportedProposition local global)
+supportedProposition support statement = do
+ unless
+ (scopedCoreType statement == TyProp)
+ (Left
+ (SupportedPropositionIsNotProposition
+ (scopedCoreType statement)))
+ let expectedContext =
+ snd <$> Vector.toList support
+ actualContext =
+ scopedCoreContext statement
+ unless
+ (actualContext == expectedContext)
+ (Left
+ (SupportedPropositionContextMismatch
+ expectedContext
+ actualContext))
+ void
+ (foldM
+ (\seen (local, _coreType) ->
+ if local `Set.member` seen
+ then
+ Left
+ (DuplicateSupportedLocal local)
+ else
+ Right (Set.insert local seen))
+ Set.empty
+ support)
+ case
+ List.find
+ (\(ordinal, _entry) ->
+ fromIntegral ordinal
+ `Set.notMember`
+ ambientIndices
+ (scopedCoreTerm statement))
+ (Vector.toList
+ (Vector.indexed support)) of
+ Just (_ordinal, (local, _coreType)) ->
+ Left (UnusedSupportedLocal local)
+ Nothing ->
+ pure ()
+ pure
+ (SupportedProposition
+ support
+ statement)
+
+-- | Retain exactly the ambient locals used by a checked proposition and
+-- remap its indices to that dense nearest-first support.
+projectSupportedProposition
+ :: Ord local
+ => (global -> Maybe CoreType)
+ -> Vector (local, CoreType)
+ -> ScopedCheckedCore global
+ -> Either
+ (SupportedPropositionProjectionError local)
+ (SupportedProposition local global)
+projectSupportedProposition globalType available statement = do
+ let expectedContext = snd <$> Vector.toList available
+ actualContext = scopedCoreContext statement
+ unless (expectedContext == actualContext)
+ (Left
+ (SupportedProjectionContextMismatch
+ expectedContext
+ actualContext))
+ void
+ (foldM
+ (\seen (local, _coreType) ->
+ if local `Set.member` seen
+ then Left (SupportedProjectionDuplicateLocal local)
+ else Right (Set.insert local seen))
+ Set.empty
+ available)
+ let used =
+ Set.toAscList
+ (ambientIndices
+ (scopedCoreTerm statement))
+ selected <- traverse (lookupNatural available) used
+ let remapping =
+ Map.fromAscList
+ (zip used [0 ..])
+ remapped <- remapAmbientIndices remapping 0
+ (scopedCoreTerm statement)
+ checked <-
+ first SupportedProjectionCoreCheckFailed
+ (checkScopedCanonicalCore
+ globalType
+ (snd <$> selected)
+ remapped)
+ first SupportedProjectionValidationFailed
+ (supportedProposition
+ (Vector.fromList selected)
+ checked)
+ where
+ lookupNatural values index =
+ maybe
+ (Left (SupportedProjectionIndexMissing index))
+ Right
+ (go index (Vector.toList values))
+
+ go _index [] =
+ Nothing
+ go 0 (value : _rest) =
+ Just value
+ go index (_value : rest) =
+ go (index - 1) rest
+
+ remapAmbientIndices remapping depth = \case
+ CBound index
+ | index < depth ->
+ Right (CBound index)
+ | otherwise ->
+ maybe
+ (Left
+ (SupportedProjectionIndexMissing
+ (index - depth)))
+ (Right . CBound . (+ depth))
+ (Map.lookup (index - depth) remapping)
+ CGlobal global ->
+ Right (CGlobal global)
+ CIntrinsic intrinsic ->
+ Right (CIntrinsic intrinsic)
+ COpaqueInteger integer ->
+ Right (COpaqueInteger integer)
+ CApp function argument ->
+ CApp
+ <$> remapAmbientIndices remapping depth function
+ <*> remapAmbientIndices remapping depth argument
+ CLam binderType body ->
+ CLam binderType
+ <$> remapAmbientIndices remapping (depth + 1) body
+ CFalsum ->
+ Right CFalsum
+ CImp premise conclusion ->
+ CImp
+ <$> remapAmbientIndices remapping depth premise
+ <*> remapAmbientIndices remapping depth conclusion
+ CEq operandType left right ->
+ CEq operandType
+ <$> remapAmbientIndices remapping depth left
+ <*> remapAmbientIndices remapping depth right
+ CForall binderType body ->
+ CForall binderType
+ <$> remapAmbientIndices remapping (depth + 1) body
+
+ambientIndices
+ :: CanonicalTerm global
+ -> Set Natural
+ambientIndices =
+ go 0
+ where
+ go depth = \case
+ CBound index
+ | index < depth ->
+ mempty
+ | otherwise ->
+ Set.singleton (index - depth)
+ CGlobal{} ->
+ mempty
+ CIntrinsic{} ->
+ mempty
+ COpaqueInteger{} ->
+ mempty
+ CApp function argument ->
+ go depth function <> go depth argument
+ CLam _binderType body ->
+ go (depth + 1) body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ go depth premise <> go depth conclusion
+ CEq _operandType left right ->
+ go depth left <> go depth right
+ CForall _binderType body ->
+ go (depth + 1) body
+
+supportedPropositionSupport
+ :: SupportedProposition local global
+ -> Vector (local, CoreType)
+supportedPropositionSupport
+ (SupportedProposition support _statement) =
+ support
+
+supportedPropositionTerm
+ :: SupportedProposition local global
+ -> CanonicalTerm global
+supportedPropositionTerm
+ (SupportedProposition _support statement) =
+ scopedCoreTerm statement
+
+weakenClosedSupportedProposition
+ :: SupportedProposition Void global
+ -> SupportedProposition local global
+weakenClosedSupportedProposition
+ (SupportedProposition support statement) =
+ SupportedProposition
+ (fmap
+ (\(local, coreType) ->
+ (absurd local, coreType))
+ support)
+ statement
+
+
+newtype CheckedFofProjection local global =
+ CheckedFofProjection
+ (SupportedProposition local global)
+ deriving stock (Eq)
+
+checkedFofProjectionProposition
+ :: CheckedFofProjection local global
+ -> SupportedProposition local global
+checkedFofProjectionProposition
+ (CheckedFofProjection proposition) =
+ proposition
+
+data FofCapability projection
+ = FofProjectable !projection
+ | RequiresTh0 !(NonEmpty BackendFofExclusion)
+ deriving stock (Eq)
+
+data BackendFofExclusion
+ = StructuralFofExclusion !FofExclusion
+ | HigherOrderGlobalType !CoreType
+ | HigherOrderAmbientLocal !CoreType
+ deriving stock (Show, Eq, Ord)
+
+data BackendClassificationError global
+ = UnknownBackendGlobal !global
+ | BackendFofProjectionInvariantFailed
+ deriving stock (Show, Eq)
+
+classifySupportedProposition
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Either
+ (BackendClassificationError global)
+ (FofCapability
+ (CheckedFofProjection local global))
+classifySupportedProposition globalType proposition = do
+ globalExclusions <-
+ foldM
+ collectGlobal
+ Set.empty
+ (Set.toAscList
+ (canonicalGlobals
+ (supportedPropositionTerm proposition)))
+ let structuralExclusions =
+ case classifyScopedStructure proposition of
+ FoundationFofProjectable ->
+ Set.empty
+ FoundationRequiresTh0 structural ->
+ Set.fromList
+ (StructuralFofExclusion
+ <$> toList structural)
+ localExclusions =
+ Set.fromList
+ [ HigherOrderAmbientLocal coreType
+ | (_local, coreType) <-
+ Vector.toList
+ (supportedPropositionSupport
+ proposition)
+ , coreType /= TySet
+ ]
+ exclusions =
+ structuralExclusions
+ <> globalExclusions
+ <> localExclusions
+ case Set.toAscList exclusions of
+ [] ->
+ if isFirstOrderProposition
+ globalType
+ proposition
+ then
+ Right
+ (FofProjectable
+ (CheckedFofProjection
+ proposition))
+ else
+ Left BackendFofProjectionInvariantFailed
+ firstExclusion : remainingExclusions ->
+ Right
+ (RequiresTh0
+ (firstExclusion
+ :| remainingExclusions))
+ where
+ collectGlobal exclusions global =
+ case globalType global of
+ Nothing ->
+ Left (UnknownBackendGlobal global)
+ Just coreType ->
+ Right
+ (if isFirstOrderGlobalType coreType
+ then exclusions
+ else
+ Set.insert
+ (HigherOrderGlobalType
+ coreType)
+ exclusions)
+
+classifyScopedStructure
+ :: SupportedProposition local global
+ -> FoundationBackendClass
+classifyScopedStructure =
+ classifyCanonicalFofStructure
+ . supportedPropositionTerm
+
+isFirstOrderGlobalType :: CoreType -> Bool
+isFirstOrderGlobalType =
+ go
+ where
+ go = \case
+ TySet ->
+ True
+ TyProp ->
+ True
+ TyArrow TySet result ->
+ go result
+ TyArrow _argument _result ->
+ False
+
+-- The structural and type exclusions make this projection total. This final
+-- walk catches an accidentally unsaturated first-order head.
+isFirstOrderProposition
+ :: (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Bool
+isFirstOrderProposition globalType proposition =
+ isFormula initialContext
+ (supportedPropositionTerm proposition)
+ where
+ initialContext =
+ snd
+ <$> Vector.toList
+ (supportedPropositionSupport
+ proposition)
+
+ isFormula context = \case
+ CFalsum ->
+ True
+ CImp premise conclusion ->
+ isFormula context premise
+ && isFormula context conclusion
+ CEq TySet left right ->
+ isTerm context left
+ && isTerm context right
+ CEq TyProp left right ->
+ isFormula context left
+ && isFormula context right
+ CForall TySet body ->
+ isFormula (TySet : context) body
+ application ->
+ case applicationHead application of
+ (CGlobal global, arguments) ->
+ maybe
+ False
+ (\coreType ->
+ applicationResult
+ coreType
+ arguments
+ == Just TyProp
+ && all
+ (isTerm context)
+ arguments)
+ (globalType global)
+ (CIntrinsic intrinsic, arguments) ->
+ applicationResult
+ (coreIntrinsicType intrinsic)
+ arguments
+ == Just TyProp
+ && all
+ (isTerm context)
+ arguments
+ _ ->
+ False
+
+ isTerm context = \case
+ CBound index ->
+ contextAt index context
+ == Just TySet
+ CGlobal global ->
+ globalType global == Just TySet
+ CIntrinsic intrinsic ->
+ coreIntrinsicType intrinsic == TySet
+ COpaqueInteger{} ->
+ True
+ application ->
+ case applicationHead application of
+ (CGlobal global, arguments) ->
+ maybe
+ False
+ (\coreType ->
+ applicationResult
+ coreType
+ arguments
+ == Just TySet
+ && all
+ (isTerm context)
+ arguments)
+ (globalType global)
+ (CIntrinsic intrinsic, arguments) ->
+ applicationResult
+ (coreIntrinsicType intrinsic)
+ arguments
+ == Just TySet
+ && all
+ (isTerm context)
+ arguments
+ _ ->
+ False
+
+applicationHead
+ :: CanonicalTerm global
+ -> (CanonicalTerm global, [CanonicalTerm global])
+applicationHead =
+ go []
+ where
+ go arguments = \case
+ CApp function argument ->
+ go (argument : arguments) function
+ headTerm ->
+ (headTerm, arguments)
+
+applicationResult
+ :: CoreType
+ -> [CanonicalTerm global]
+ -> Maybe CoreType
+applicationResult =
+ foldM
+ (\coreType _argument ->
+ case coreType of
+ TyArrow TySet result ->
+ Just result
+ _ ->
+ Nothing)
+
+contextAt :: Natural -> [value] -> Maybe value
+contextAt _index [] =
+ Nothing
+contextAt 0 (value : _remaining) =
+ Just value
+contextAt index (_value : remaining) =
+ contextAt (index - 1) remaining
+
+canonicalGlobals
+ :: Ord global
+ => CanonicalTerm global
+ -> Set global
+canonicalGlobals = \case
+ CBound{} ->
+ mempty
+ CGlobal global ->
+ Set.singleton global
+ CIntrinsic{} ->
+ mempty
+ COpaqueInteger{} ->
+ mempty
+ CApp function argument ->
+ canonicalGlobals function
+ <> canonicalGlobals argument
+ CLam _binderType body ->
+ canonicalGlobals body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ canonicalGlobals premise
+ <> canonicalGlobals conclusion
+ CEq _operandType left right ->
+ canonicalGlobals left
+ <> canonicalGlobals right
+ CForall _binderType body ->
+ canonicalGlobals body
+
+
+data TypedBackendFact ref global =
+ TypedBackendFact
+ !ref
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+ deriving stock (Eq)
+
+typedBackendFact
+ :: ref
+ -> SupportedProposition Void global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+ -> TypedBackendFact ref global
+typedBackendFact =
+ TypedBackendFact
+
+typedBackendFactReference
+ :: TypedBackendFact ref global
+ -> ref
+typedBackendFactReference
+ (TypedBackendFact
+ reference
+ _proposition
+ _capability) =
+ reference
+
+typedBackendFactProposition
+ :: TypedBackendFact ref global
+ -> SupportedProposition Void global
+typedBackendFactProposition
+ (TypedBackendFact
+ _reference
+ proposition
+ _capability) =
+ proposition
+
+typedBackendFactCapability
+ :: TypedBackendFact ref global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+typedBackendFactCapability
+ (TypedBackendFact
+ _reference
+ _proposition
+ capability) =
+ capability
+
+
+newtype LocalPremiseOrdinal =
+ LocalPremiseOrdinal Natural
+ deriving stock (Show, Eq, Ord)
+
+localPremiseOrdinal :: Natural -> LocalPremiseOrdinal
+localPremiseOrdinal =
+ LocalPremiseOrdinal
+
+localPremiseOrdinalValue
+ :: LocalPremiseOrdinal
+ -> Natural
+localPremiseOrdinalValue
+ (LocalPremiseOrdinal ordinal) =
+ ordinal
+
+data TypedLocalPremise local origin global =
+ TypedLocalPremise
+ !LocalPremiseOrdinal
+ !origin
+ !(SupportedProposition local global)
+ !(FofCapability
+ (CheckedFofProjection local global))
+ deriving stock (Eq)
+
+typedLocalPremise
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> LocalPremiseOrdinal
+ -> origin
+ -> SupportedProposition local global
+ -> Either
+ (BackendClassificationError global)
+ (TypedLocalPremise local origin global)
+typedLocalPremise globalType ordinal premiseOrigin proposition =
+ TypedLocalPremise
+ ordinal
+ premiseOrigin
+ proposition
+ <$> classifySupportedProposition
+ globalType
+ proposition
+
+typedLocalPremiseOrdinal
+ :: TypedLocalPremise local origin global
+ -> LocalPremiseOrdinal
+typedLocalPremiseOrdinal
+ (TypedLocalPremise
+ ordinal
+ _origin
+ _proposition
+ _capability) =
+ ordinal
+
+typedLocalPremiseOrigin
+ :: TypedLocalPremise local origin global
+ -> origin
+typedLocalPremiseOrigin
+ (TypedLocalPremise
+ _ordinal
+ premiseOrigin
+ _proposition
+ _capability) =
+ premiseOrigin
+
+typedLocalPremiseProposition
+ :: TypedLocalPremise local origin global
+ -> SupportedProposition local global
+typedLocalPremiseProposition
+ (TypedLocalPremise
+ _ordinal
+ _origin
+ proposition
+ _capability) =
+ proposition
+
+typedLocalPremiseCapability
+ :: TypedLocalPremise local origin global
+ -> FofCapability
+ (CheckedFofProjection local global)
+typedLocalPremiseCapability
+ (TypedLocalPremise
+ _ordinal
+ _origin
+ _proposition
+ capability) =
+ capability
+
+
+data TypedFoundationAuxiliaryInput global =
+ TypedFoundationAuxiliaryInput
+ !FoundationAxiomTag
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+
+typedFoundationAuxiliaryInput
+ :: CheckedFoundation
+ -> FoundationAxiomTag
+ -> TypedFoundationAuxiliaryInput global
+typedFoundationAuxiliaryInput foundation tag =
+ TypedFoundationAuxiliaryInput
+ tag
+ proposition
+ capability
+ where
+ proposition =
+ SupportedProposition
+ Vector.empty
+ (embedClosedCore
+ []
+ (mapFrozenGlobals
+ absurd
+ (foundationAxiomFrozen
+ foundation
+ tag)))
+ capability =
+ case foundationAxiomBackendClass
+ foundation
+ tag of
+ FoundationFofProjectable ->
+ FofProjectable
+ (CheckedFofProjection
+ proposition)
+ FoundationRequiresTh0 exclusions ->
+ RequiresTh0
+ (StructuralFofExclusion
+ <$> exclusions)
+
+data TypedProblemAuxiliary global =
+ TypedProblemAuxiliary
+ !Natural
+ !FoundationAxiomTag
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+ deriving stock (Eq)
+
+typedProblemAuxiliaryOrdinal
+ :: TypedProblemAuxiliary global
+ -> Natural
+typedProblemAuxiliaryOrdinal
+ (TypedProblemAuxiliary
+ ordinal
+ _tag
+ _proposition
+ _capability) =
+ ordinal
+
+typedProblemAuxiliaryTag
+ :: TypedProblemAuxiliary global
+ -> FoundationAxiomTag
+typedProblemAuxiliaryTag
+ (TypedProblemAuxiliary
+ _ordinal
+ tag
+ _proposition
+ _capability) =
+ tag
+
+typedProblemAuxiliaryProposition
+ :: TypedProblemAuxiliary global
+ -> SupportedProposition Void global
+typedProblemAuxiliaryProposition
+ (TypedProblemAuxiliary
+ _ordinal
+ _tag
+ proposition
+ _capability) =
+ proposition
+
+typedProblemAuxiliaryCapability
+ :: TypedProblemAuxiliary global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+typedProblemAuxiliaryCapability
+ (TypedProblemAuxiliary
+ _ordinal
+ _tag
+ _proposition
+ capability) =
+ capability
+
+
+-- | Source justification policy for premise selection. Higher-order routing
+-- is validated separately after the complete selected problem is known.
+data LocalPremisePolicy
+ = FirstOrderLocals
+ | CompleteLocals
+ deriving stock (Show, Eq)
+
+-- | Whether selected higher-order components must be justified by one of the
+-- two approved inline construction forms. Premise selection has already
+-- happened when this policy is applied.
+data HigherOrderJustificationPolicy
+ = ImplicitConstructionJustification
+ | ExplicitHigherOrderJustification
+ deriving stock (Show, Eq)
+
+selectTypedLocalPremises
+ :: LocalPremisePolicy
+ -> [TypedLocalPremise local origin global]
+ -> Vector (TypedLocalPremise local origin global)
+selectTypedLocalPremises selection availableLocals =
+ Vector.fromList
+ (List.sortOn
+ typedLocalPremiseOrdinal
+ (case selection of
+ FirstOrderLocals ->
+ List.filter
+ (isFofCapability
+ . typedLocalPremiseCapability)
+ availableLocals
+ CompleteLocals ->
+ availableLocals))
+
+data ImplicitHigherOrderConstruction
+ = ImplicitSeparation
+ | ImplicitFunctionalReplacement
+ deriving stock (Show, Eq, Ord)
+
+data TypedProblemRoute
+ = RouteFof
+ | RouteTh0
+ deriving stock (Show, Eq)
+
+data TypedProblem ref local origin global =
+ TypedProblem
+ !TypedProblemRoute
+ !(SupportedProposition local global)
+ !(Vector (TypedBackendFact ref global))
+ !(Vector (TypedLocalPremise local origin global))
+ !(Vector (TypedProblemAuxiliary global))
+ !(Map global CoreType)
+ !(Map local CoreType)
+ deriving stock (Eq)
+
+data TypedProblemError local global
+ = TypedProblemClaimClassificationFailed
+ !(BackendClassificationError global)
+ | TypedProblemExplicitHigherOrderJustificationRequired
+ !(NonEmpty BackendFofExclusion)
+ | TypedProblemDuplicateLocalPremiseOrdinal
+ !LocalPremiseOrdinal
+ | TypedProblemLocalTypeMismatch
+ !local
+ !CoreType
+ !CoreType
+ deriving stock (Show, Eq)
+
+planTypedProblem
+ :: (Ord local, Ord global)
+ => (global -> Maybe CoreType)
+ -> Vector (TypedBackendFact ref global)
+ -> SupportedProposition local global
+ -> [TypedLocalPremise local origin global]
+ -> [TypedFoundationAuxiliaryInput global]
+ -> LocalPremisePolicy
+ -> HigherOrderJustificationPolicy
+ -> Either
+ (TypedProblemError local global)
+ (TypedProblem ref local origin global)
+planTypedProblem
+ globalType
+ selectedFacts
+ claim
+ availableLocals
+ auxiliaries
+ localPolicy
+ higherOrderPolicy = do
+ validateLocalPremiseOrdinals
+ availableLocals
+ claimCapability <-
+ first
+ TypedProblemClaimClassificationFailed
+ (classifySupportedProposition
+ globalType
+ claim)
+ let selectedLocals =
+ selectTypedLocalPremises
+ localPolicy
+ availableLocals
+ let preparedAuxiliaries =
+ zipWith
+ prepareAuxiliary
+ [0..]
+ auxiliaries
+ case higherOrderPolicy of
+ ImplicitConstructionJustification ->
+ validateImplicitHigherOrderAdmission
+ claim
+ claimCapability
+ selectedFacts
+ selectedLocals
+ preparedAuxiliaries
+ ExplicitHigherOrderJustification ->
+ pure ()
+ let selectedFofCapabilities =
+ isFofCapability claimCapability
+ : (isFofCapability
+ . typedBackendFactCapability
+ <$> Vector.toList selectedFacts)
+ <> (isFofCapability
+ . typedLocalPremiseCapability
+ <$> Vector.toList selectedLocals)
+ <> (isFofCapability
+ . typedProblemAuxiliaryCapability
+ <$> preparedAuxiliaries)
+ route =
+ if and selectedFofCapabilities
+ then RouteFof
+ else RouteTh0
+ globalTypes <-
+ collectProblemGlobals
+ globalType
+ claim
+ selectedFacts
+ selectedLocals
+ preparedAuxiliaries
+ localTypes <-
+ collectProblemLocals
+ claim
+ selectedLocals
+ pure
+ (TypedProblem
+ route
+ claim
+ selectedFacts
+ selectedLocals
+ (Vector.fromList preparedAuxiliaries)
+ globalTypes
+ localTypes)
+ where
+ prepareAuxiliary
+ ordinal
+ (TypedFoundationAuxiliaryInput
+ tag
+ proposition
+ capability) =
+ TypedProblemAuxiliary
+ ordinal
+ tag
+ proposition
+ capability
+
+-- | Implicit automation admits higher-order routing only for a checked
+-- proposition that itself contains one of the two approved set constructions.
+-- This classification selects no premise and grants no authority.
+implicitConstructionAdmission
+ :: SupportedProposition local global
+ -> FofCapability projection
+ -> Maybe (Set ImplicitHigherOrderConstruction)
+implicitConstructionAdmission proposition capability =
+ case capability of
+ FofProjectable{} ->
+ Nothing
+ RequiresTh0 exclusions
+ | Set.null constructions ->
+ Nothing
+ | all (admittedExclusion constructions) exclusions ->
+ Just constructions
+ | otherwise ->
+ Nothing
+ where
+ dependencies =
+ foundationAxiomDependencies
+ (supportedPropositionTerm proposition)
+ constructions =
+ Set.fromList
+ ( [ ImplicitSeparation
+ | SeparationCharacteristic `Set.member` dependencies
+ ]
+ <> [ ImplicitFunctionalReplacement
+ | ReplacementCharacteristic `Set.member` dependencies
+ ]
+ )
+
+ admittedExclusion allowed = \case
+ StructuralFofExclusion HigherOrderLambda ->
+ True
+ StructuralFofExclusion (HigherOrderIntrinsic Sep) ->
+ ImplicitSeparation `Set.member` allowed
+ StructuralFofExclusion (HigherOrderIntrinsic Repl) ->
+ ImplicitFunctionalReplacement `Set.member` allowed
+ -- The checked proposition is the deliberate granularity: its typed
+ -- global occurrences neither select another fact nor grant authority.
+ HigherOrderGlobalType{} ->
+ True
+ StructuralFofExclusion{} ->
+ False
+ HigherOrderAmbientLocal{} ->
+ False
+
+validateImplicitHigherOrderAdmission
+ :: SupportedProposition local global
+ -> FofCapability claimProjection
+ -> Vector (TypedBackendFact ref global)
+ -> Vector (TypedLocalPremise local origin global)
+ -> [TypedProblemAuxiliary global]
+ -> Either (TypedProblemError local global) ()
+validateImplicitHigherOrderAdmission
+ claim claimCapability selectedFacts selectedLocals auxiliaries = do
+ claimConstructions <-
+ admittedPropositionConstructions claim claimCapability
+ traverse_ requireFirstOrderGlobal selectedFacts
+ localConstructions <-
+ foldM
+ (\admitted premise ->
+ (admitted <>)
+ <$> admittedPropositionConstructions
+ (typedLocalPremiseProposition premise)
+ (typedLocalPremiseCapability premise))
+ Set.empty
+ (Vector.toList selectedLocals)
+ let admitted = claimConstructions <> localConstructions
+ traverse_ (requireAdmittedAuxiliary admitted) auxiliaries
+ where
+ admittedPropositionConstructions proposition = \case
+ FofProjectable{} ->
+ Right Set.empty
+ RequiresTh0 exclusions ->
+ maybe
+ (Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions))
+ Right
+ (implicitConstructionAdmission
+ proposition
+ (RequiresTh0 exclusions))
+
+ requireFirstOrderGlobal fact =
+ case typedBackendFactCapability fact of
+ FofProjectable{} ->
+ Right ()
+ RequiresTh0 exclusions ->
+ Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions)
+
+ requireAdmittedAuxiliary admitted auxiliary =
+ case typedProblemAuxiliaryCapability auxiliary of
+ FofProjectable{} ->
+ Right ()
+ RequiresTh0 exclusions
+ | auxiliaryAdmitted admitted
+ (typedProblemAuxiliaryTag auxiliary) ->
+ Right ()
+ | otherwise ->
+ Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions)
+
+ auxiliaryAdmitted admitted = \case
+ SeparationCharacteristic ->
+ ImplicitSeparation `Set.member` admitted
+ ReplacementCharacteristic ->
+ ImplicitFunctionalReplacement `Set.member` admitted
+ _ ->
+ False
+
+validateLocalPremiseOrdinals
+ :: [TypedLocalPremise local origin global]
+ -> Either
+ (TypedProblemError local global)
+ ()
+validateLocalPremiseOrdinals =
+ void
+ . foldM
+ (\seen premise ->
+ let ordinal =
+ typedLocalPremiseOrdinal premise
+ in
+ if ordinal `Set.member` seen
+ then
+ Left
+ (TypedProblemDuplicateLocalPremiseOrdinal
+ ordinal)
+ else
+ Right
+ (Set.insert
+ ordinal
+ seen))
+ Set.empty
+
+isFofCapability :: FofCapability projection -> Bool
+isFofCapability = \case
+ FofProjectable{} ->
+ True
+ RequiresTh0{} ->
+ False
+
+collectProblemGlobals
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Vector (TypedBackendFact ref global)
+ -> Vector (TypedLocalPremise local origin global)
+ -> [TypedProblemAuxiliary global]
+ -> Either
+ (TypedProblemError local global)
+ (Map global CoreType)
+collectProblemGlobals
+ globalType
+ claim
+ facts
+ locals
+ auxiliaries =
+ Map.fromAscList
+ <$> traverse
+ resolveGlobal
+ (Set.toAscList globals)
+ where
+ globals =
+ canonicalGlobals
+ (supportedPropositionTerm claim)
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedBackendFactProposition)
+ facts
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedLocalPremiseProposition)
+ locals
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedProblemAuxiliaryProposition)
+ auxiliaries
+
+ resolveGlobal global =
+ case globalType global of
+ Nothing ->
+ Left
+ (TypedProblemClaimClassificationFailed
+ (UnknownBackendGlobal global))
+ Just coreType ->
+ Right (global, coreType)
+
+collectProblemLocals
+ :: Ord local
+ => SupportedProposition local global
+ -> Vector (TypedLocalPremise local origin global)
+ -> Either
+ (TypedProblemError local global)
+ (Map local CoreType)
+collectProblemLocals claim locals =
+ foldM
+ insertSupport
+ Map.empty
+ supports
+ where
+ supports =
+ Vector.toList
+ (supportedPropositionSupport claim)
+ <> concatMap
+ (Vector.toList
+ . supportedPropositionSupport
+ . typedLocalPremiseProposition)
+ (Vector.toList locals)
+
+ insertSupport current (local, coreType) =
+ case Map.lookup local current of
+ Nothing ->
+ Right
+ (Map.insert
+ local
+ coreType
+ current)
+ Just previousType
+ | previousType == coreType ->
+ Right current
+ | otherwise ->
+ Left
+ (TypedProblemLocalTypeMismatch
+ local
+ previousType
+ coreType)
+
+typedProblemRoute
+ :: TypedProblem ref local origin global
+ -> TypedProblemRoute
+typedProblemRoute
+ (TypedProblem
+ route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ route
+
+typedProblemClaim
+ :: TypedProblem ref local origin global
+ -> SupportedProposition local global
+typedProblemClaim
+ (TypedProblem
+ _route
+ claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ claim
+
+typedProblemGlobalPremises
+ :: TypedProblem ref local origin global
+ -> Vector (TypedBackendFact ref global)
+typedProblemGlobalPremises
+ (TypedProblem
+ _route
+ _claim
+ facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ facts
+
+typedProblemLocalPremises
+ :: TypedProblem ref local origin global
+ -> Vector (TypedLocalPremise local origin global)
+typedProblemLocalPremises
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ locals
+
+typedProblemAuxiliaries
+ :: TypedProblem ref local origin global
+ -> Vector (TypedProblemAuxiliary global)
+typedProblemAuxiliaries
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ auxiliaries
+ _globals
+ _localTypes) =
+ auxiliaries
+
+typedProblemGlobalTypes
+ :: TypedProblem ref local origin global
+ -> Map global CoreType
+typedProblemGlobalTypes
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ globals
+ _localTypes) =
+ globals
+
+typedProblemLocalTypes
+ :: TypedProblem ref local origin global
+ -> Map local CoreType
+typedProblemLocalTypes
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ localTypes) =
+ localTypes