module ProductMixAuction.BudgetConstraints.CandidateRates where
import Control.Lens
import Data.List
import Data.Ord
import qualified Data.Set as Set
import qualified Data.Vector as V
import ProductMixAuction.BudgetConstraints.Types
import Prelude hiding (sequence)
candidateRates :: [Bid b] -> Set.Set PriceVector
candidateRates [] = Set.empty
candidateRates bids@(bid:_) = foldl' f Set.empty [ (interaction, sequence)
| interaction <- interactions dims bids
, sequence <- sequences dims
]
where
dims = V.length (_bid_prices bid)
f candidates (interaction, sequence) =
case getCandidate interaction sequence of
Just candidate -> Set.insert candidate candidates
_ -> candidates
type Interaction b = [Bid b]
interactions :: Dimension -> [Bid b] -> [Interaction b]
interactions 0 _ = []
interactions 1 bids = map return bids
interactions n bids = do bid <- bids
int <- interactions (n-1) bids
return (bid:int)
type Sequence = [Good]
sequences :: Dimension -> [[Good]]
sequences dims = permutations [0..dims-1]
getCandidate :: Interaction b -> Sequence -> Maybe PriceVector
getCandidate bids goods = help [] [] (zip goods bids)
where
help :: [(Good, Price)]
-> [(Good, Bid b)]
-> [(Good, Bid b)]
-> Maybe PriceVector
help ps _old_bids [] = Just (toPriceVector ps)
help ps old_bids ((good, bid):xs)
| valid = help ((good, p') : ps) ((good,bid):rebase good p' old_bids)
(rebase good p' xs)
| otherwise = Nothing
where
p' = bidPrice good bid
valid = all ((<= p') . bidPrice good . snd) old_bids
rebase good p = map (fmap (rebaseBid good p))
toPriceVector :: [(Good, Price)] -> PriceVector
toPriceVector ps = V.fromList (map snd (sortBy (comparing fst) ps))
rebaseBid :: Good -> Price -> Bid b -> Bid b
rebaseBid good fixed_p bid
| bid_p > fixed_p = iover (bid_prices.imapped) r bid
| otherwise = bid
where
bid_p = bidPrice good bid
r good' p
| good == good' = p
| otherwise = p * (fixed_p / bid_p)