joint
  :: MLN -- ^ The Markov logic network.
  -> [Term] -- ^ List of constants to ground the Markov logic network.
  -> Set (Predicate, Bool) -- ^ An set of assignments. The reason...
  -> Double -- ^ A probability in [0.0, 1.0]
joint mln ts query = vq / z
  where
    vq = sum $ map evalNet toEval
    vo = sum $ map evalNet others
    z = vq + vo
    -- All possible assignments
    allass = allAss ts fs
    -- Assignments to evaluate:
    (toEval, others) = partitionAss query allass
    -- The formula (the factors) to evaluate
    fs = allWGroundings ts mln
    -- Value of the network for a given assignment.
    evalNet ass' = exp $ Map.foldrWithKey (\f w a -> val f w ass' + a) 0.0 (network fs)
    -- Values of a factor
    val f w ass' = let v = FOL.eval ass' f in
      if v == FOL.top then w
      else if v == FOL.bot then 0.0
      else error ("Eval failed for " ++ show v ++ " given " ++ show ass')

-- | Direct method of computing marginal probabilities for Markov logic (does
-- not scale!).
joint
  :: MLN -- ^ The Markov logic network.
  -> [Term] -- ^ List of constants to ground the Markov logic network.
  -> Set (Predicate, Bool) -- ^ An set of assignments. The reason...
  -> Double
joint mln ts query = vq / z
  where
    vq = sum $ map evalNet toEval
    vo = sum $ map evalNet others
    z = vq + vo
    -- All possible assignments
    allass = allAss ts fs
    -- Assignments to evaluate:
    (toEval, others) = partitionAss query allass
    -- The formula (the factors) to evaluate
    fs = allWGroundings ts mln
    -- Value of the network for a given assignment.
    evalNet ass' = exp $ Map.foldrWithKey (\f w a -> val f w ass' + a) 0.0 (network fs)
    -- Values of a factor
    val f w ass' = let v = FOL.eval ass' f in
      if v == FOL.top then w
      else if v == FOL.bot then 0.0
      else error ("Eval failed for " ++ show v ++ " given " ++ show ass')

-- | Direct method of computing marginal probabilities for Markov logic (does
-- not scale!).
joint mln ts query = vq / z
  where
    vq = sum $ map evalNet toEval
    vo = sum $ map evalNet others
    z = vq + vo
    -- All possible assignments
    allass = allAss ts fs
    -- Assignments to evaluate:
    (toEval, others) = partitionAss query allass
    -- The formula (the factors) to evaluate
    fs = allWGroundings ts mln
    -- Value of the network for a given assignment.
    evalNet ass' = exp $ Map.foldrWithKey (\f w a -> val f w ass' + a) 0.0 (network fs)
    -- Values of a factor
    val f w ass' = let v = FOL.eval ass' f in
      if v == FOL.top then w
      else if v == FOL.bot then 0.0
      else error ("Eval failed for " ++ show v ++ " given " ++ show ass')

-- | Direct method of computing marginal probabilities for Markov logic (does
-- not scale!).