{-# LANGUAGE ViewPatterns #-}{- | Common functions and types for building networks
-}moduleBayes.Network(-- * Types MaybeNode(..),NetworkMonad(..)-- * Functions,factorVariable,(<--),getBayesianNode,setBayesianNode,initializeNodeWithValue,setVariableBoundWithSize,setVariableBound,addVariableIfNotFound,unamedVariable,variable,variableWithSize,unNamedVariableWithSize,runNetwork,execNetwork,evalNetwork,runGraph,execGraph,evalGraph,getCpt)whereimportBayes.PrivateTypesimportBayesimportControl.Monad.State.StrictimportBayes.ToolsimportData.Maybe(fromJust)importBayes.FactorimportData.Monoid-- | Bayesian variable : name,dimension, factor-- When initialized it is using a factor with bayesian variables.-- But the factor value are not yet setdataMaybeNodef=UninitializedNodeStringInt|InitializedNodeStringIntf-- | The Network monadtypeNetworkMonadgefa=GraphMonadge(MaybeNodef)a-- | Get the Bayesian Discrete Variable for a vertex.-- It works because we keep the variable dimension during creating of the graphfactorVariable::Graphg=>Vertex->NetworkMonadgef(MaybeDV)factorVariablev=dog<-getssndletvalue=vertexValuegvcasevalueofNothing->returnNothingJust(UninitializedNode_d)->return$Just$DVvdJust(InitializedNode_d_)->return$Just$DVvd-- | Create an edge between two vertex of the Bayesian network(<--)::(Graphg,BayesianDiscreteVariabledv,Monoide)=>dv->dv->NetworkMonadgef()(dv->DVva_)<--(dv->DVvb_)=newEdgevbvamemptywhenJustNothing_=return()whenJust(Justi)f=fi>>return()getCpt::(DirectedGraphg,Distributiond,Factorf)=>Vertex-- ^ Vertex containing the factor->d-- ^ Distribution to initialize the factor->NetworkMonadgea(Maybef)getCptvl=dog<-getssndcurrentVar<-factorVariablevletvertices=map(fromJust.startVertexg).fromJust.ingoingg$vfv<-mapMfactorVariableverticesletcpt=createFactor(mapfromJust(currentVar:fv))lreturncpt-- | Get the node of a bayesian network under creationgetBayesianNode::Graphg=>Vertex->NetworkMonadgef(Maybe(MaybeNodef))getBayesianNodev=dog<-getssndreturn$vertexValuegv-- | Set the node of a bayesian network under creationsetBayesianNode::Graphg=>Vertex->MaybeNodef->NetworkMonadgef()setBayesianNodevnewValue=do(aux,oldGraph)<-getletnewGraph=changeVertexValuevnewValueoldGraphwhenJustnewGraph$\nvm->doput$!(aux,nvm)-- | Set the value of uninitialized nodes. Initialized nodes are not changed.initializeNodeWithValue::Graphg=>Vertex-- ^ Vertex->MaybeNodea-- ^ Current uninitialized node->a-- ^ Value to set->NetworkMonadgea()initializeNodeWithValue_(InitializedNode___)_=return()initializeNodeWithValuev(UninitializedNodesdim)newValue=dog<-getssndsetBayesianNodev(InitializedNodesdimnewValue)-- | Set the bound of a bayesian variable (number of levels)setVariableBoundWithSize::Graphg=>Vertex-- ^ Vertex->Int-- ^ Inf limit (0 for instance)->Int-- ^ Sup limit (1 for instance for 2 elements)->NetworkMonadgef()setVariableBoundWithSizeabminbmax=dov<-getBayesianNodeawhenJustv$\(UninitializedNodes_)->dosetBayesianNodea(UninitializedNodes(bmax-bmin+1))setVariableBound::(Enuma,Boundeda,Graphg)=>Vertex-- ^ Vertex->a-- ^ Bounded variable (t :: type where t is undefined)->NetworkMonadgef()setVariableBoundae=letbmin=intValue$minBoundForEnumebmax=intValue$maxBoundForEnumeinsetVariableBoundWithSizeabminbmax-- | Create a new named Bayesian variable if not found.-- Otherwise, return the found one.addVariableIfNotFound::NamedGraphg=>String->NetworkMonadgefVertexaddVariableIfNotFoundvertexName=graphNodevertexName(UninitializedNodevertexName0)-- | Initialize a new variable_initializeVariableBounds::(Enuma,Boundeda,NamedGraphg)=>Vertex->a->NetworkMonadgef(TDVa)_initializeVariableBoundsvae=dosetVariableBoundvaemaybeValue<-getBayesianNodevacasefromJustmaybeValueofUninitializedNodesd->return(tdv$DVvad)InitializedNode_d_->return(tdv$DVvad)-- | Initialize a new variable with size_initializeVariableBoundsWithSize::NamedGraphg=>Vertex-- ^ Variable name->Int-- ^ Variable size->NetworkMonadgefDV_initializeVariableBoundsWithSizevae=dosetVariableBoundWithSizeva0(e-1)maybeValue<-getBayesianNodevasetBayesianNodeva(fromJustmaybeValue)casefromJustmaybeValueofUninitializedNodesd->return(DVvad)InitializedNode_d_->return(DVvad)-- | Create a new unamed variableunamedVariable::(Enuma,Boundeda,NamedGraphg)=>a-- ^ Variable bounds ->NetworkMonadgef(TDVa)unamedVariablee=dova<-getNewEmptyVariableNothing(UninitializedNode"unamed"0)_initializeVariableBoundsvae-- | Define a Bayesian variable (name and bounds)variable::(Enuma,Boundeda,NamedGraphg)=>String-- ^ Variable name->a-- ^ Variable bounds->NetworkMonadgef(TDVa)variablenamee=dova<-addVariableIfNotFoundname_initializeVariableBoundsvae-- | Define a Bayesian variable (name and bounds)variableWithSize::NamedGraphg=>String-- ^ Variable name->Int-- ^ Variable size->NetworkMonadgefDVvariableWithSizenamee=dova<-addVariableIfNotFoundname_initializeVariableBoundsWithSizevae-- | Define a Bayesian variable (name and bounds)unNamedVariableWithSize::NamedGraphg=>Int-- ^ Variable size->NetworkMonadgefDVunNamedVariableWithSizee=dova<-getNewEmptyVariableNothing(UninitializedNode"unamed"0)_initializeVariableBoundsWithSizevae-- | Create a network using the simple graph implementation-- The initialized nodes are replaced by the value.-- Returns the monad values and the built graph.runNetwork::NetworkMonadDirectedSGefa->(a,DirectedSGef)runNetworkx=let(r,g)=runGraphxconvertNodes(InitializedNodesdf)=fconvertNodes(UninitializedNodesd)=error$"All variables must be initialized with a factor: "++s++"("++showd++")"in(r,fmapconvertNodesg)-- | Create a network but only returns the monad value.-- Mainly used for testing.execNetwork::NetworkMonadDirectedSGefa->DirectedSGefexecNetworkx=letg=execGraphxconvertNodes(InitializedNodesdf)=fconvertNodes(UninitializedNodesd)=error$"All variables must be initialized with a factor: "++s++"("++showd++")"infmapconvertNodesg-- | Create a bayesian network but only returns the monad value.-- Mainly used for testing.evalNetwork::Graphg=>NetworkMonadgefa->aevalNetwork=evalGraph