hahp-0.1.0: src/HAHP/Algorithm.hs
module HAHP.Algorithm where
import Data.List
import Data.Maybe
import Data.Ord (comparing)
import HAHP.Algorithm.Consistency
import HAHP.Algorithm.PriorityVector
import HAHP.Algorithm.Ranking
import HAHP.Data
import HAHP.Validation.Alternatives
import HAHP.Validation.Tree
import Numeric.LinearAlgebra.HMatrix
-- |This function is a quick way to rank a set of alternatives with AHP algorithm.
-- This function call everithing required to configure an execute AHP process.
-- If something goes wrong, an error is raised.
simpleAHP :: AHPTree
-> [Alternative]
-> (AHPTree, [Alternative], [TreeError], [AlternativesError])
simpleAHP ahpTree alts =
if null inputTreeErrors && null altsErrors
then (completeTree, ranking, treeErrors, [])
else (ahpTree, alts, inputTreeErrors ++ treeErrors, altsErrors)
where initializedTree = initAHP ahpTree
(completeTree, ranking) = rankAlternatives initializedTree alts
---
inputTreeErrors = validateInputAHPTree ahpTree
altsErrors = validateAlternatives ahpTree alts
treeErrors = if null inputTreeErrors
then validateAHPTree initializedTree
else []
-- * Part 1 = static part
initAHP :: AHPTree
-> AHPTree
initAHP ahpTree = computeTreePriorityVectors . computeTreeConsistencies $ ahpTree
-- * Part 2 = dynamic part
rankAlternatives :: AHPTree
-> [Alternative]
-> (AHPTree, [Alternative])
rankAlternatives ahpTree alts = (rankedAhpTree, reverse sortedRankedAlternatives)
where ranks = concat . toLists . fromJust $ alternativesPriority rankedAhpTree
rankedAhpTree = computeTreeAlternativesPriorities alts ahpTree
sortedRankedAlternatives = map fst . sortOn' snd $ zip alts ranks
-- | Sort a list by comparing the results of a key function applied to each
-- element. @sortOn f@ is equivalent to @sortBy . comparing f@, but has the
-- performance advantage of only evaluating @f@ once for each element in the
-- input list. This is called the decorate-sort-undecorate paradigm, or
-- Schwartzian transform.
-- see https://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.OldList.html#sortOn
--
-- TODO : Remote this function and use default haskell sortOn.
-- Note: Compilation issues on mac. sortOn is not provided.
--
-- @since 4.8.0.0
sortOn' :: Ord b => (a -> b) -> [a] -> [a]
sortOn' f =
map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))