-- Use instead of amap when the array implementation needs to change.
-- E.g., mapping an unboxed array to an array whose elements must be boxed.
amap2 f arr = funcArray (bounds arr) (\i -> f (arr ! i))
+
+-- Like amap2 but the mapping function is also passed the index.
+aixmap f arr = funcArray (bounds arr) (\i -> f i (arr ! i))
--- /dev/null
+module Evaluation where
+import PMInstance
+import ProposalMatcher
+
+import Data.Array.IArray
+import Data.List
+import ArrayStuff
+
+type MatchingEvaluation = Array Int Wt
+
+evaluateMatching :: PMConfig -> PMInstance -> PMatching -> MatchingEvaluation
+evaluateMatching cfg inst@(PMInstance numRvrs numProps rloadA prefA) matching =
+ let reviewersByProposal = accumArray (flip (:)) []
+ (0, numProps-1) $ map (\(i,j) -> (j,i)) matching
+ :: Array Int [Int] in
+ aixmap (\j rl ->
+ -- Sort this proposal's reviews, best first.
+ let jPrefsInc = sort $ map (\i -> prefA ! (i,j)) rl in
+ -- Charge each review's assignmentCost.
+ sum $ zipWith (\wt prf -> (numAsWt wt) * assignmentCost cfg prf)
+ -- The assignment costs are weighted by
+ -- reviewsEachProposal, ..., 1 from best to worst.
+ -- (It's most important for the best to be good.)
+ (take (reviewsEachProposal cfg) $
+ iterate (subtract 1) (reviewsEachProposal cfg))
+ -- A missing review counts as a preference of 50 (really bad).
+ (jPrefsInc ++ repeat 50)
+ )
+ reviewersByProposal
+
+doEvaluateMatching :: PMConfig -> PMInstance -> MatchingEvaluation
+doEvaluateMatching cfg inst =
+ let matching = doMatching cfg inst in
+ evaluateMatching cfg inst matching
+
+-- Sorted from negative cost changes (better in e2)
+-- to positive cost changes (worse in e2).
+sortedDiffEvaluations :: MatchingEvaluation -> MatchingEvaluation -> [Wt]
+sortedDiffEvaluations e1 e2 =
+ sort $ zipWith (-) (elems e1) (elems e2)
-- Run randomized things.
module System.Random,
- module RandomizedMonad
+ module RandomizedMonad,
+
+ -- Evaluate.
+ module Evaluation
) where
import TestUtils
import PMInstance
import PMDefaults
import System.Random
import RandomizedMonad
+import Evaluation
-- Other imports we need
import BellmanFord
myMatching = doMatching pmDefaults myInst
iGraph = showInstanceAsGraph myInst myMatching -- Visualize me!
+
+-- Evaluation!
+eInst = runRandom myGen $ randomInstance 20 50
+eval1 = doEvaluateMatching pmDefaults eInst
+eval2 = doEvaluateMatching pmDefaults{loadTolerance = 2} eInst