diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2017-05-06 17:10:02 +0200 | 
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2017-05-06 17:10:02 +0200 | 
| commit | 8b5c35e41c5ea7fceec83a5134708ae02bcba395 (patch) | |
| tree | 7e7158b2383a57a15135261014ba7269853da5a8 | |
| parent | df6269ce248021e9705c716346751e3afa924ba0 (diff) | |
| download | uni-8b5c35e41c5ea7fceec83a5134708ae02bcba395.tar uni-8b5c35e41c5ea7fceec83a5134708ae02bcba395.tar.gz uni-8b5c35e41c5ea7fceec83a5134708ae02bcba395.tar.bz2 uni-8b5c35e41c5ea7fceec83a5134708ae02bcba395.tar.xz uni-8b5c35e41c5ea7fceec83a5134708ae02bcba395.zip | |
Finish indexing paper & demonstration haskell
| -rw-r--r-- | ss2017/stable_marriage_problem/ausarbeitung.lhs | 127 | ||||
| -rw-r--r-- | ss2017/stable_marriage_problem/structure.md | 10 | 
2 files changed, 135 insertions, 2 deletions
| diff --git a/ss2017/stable_marriage_problem/ausarbeitung.lhs b/ss2017/stable_marriage_problem/ausarbeitung.lhs new file mode 100644 index 0000000..ca03280 --- /dev/null +++ b/ss2017/stable_marriage_problem/ausarbeitung.lhs | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | Preliminaries | ||
| 2 | ============= | ||
| 3 | |||
| 4 | - Efficient finite maps | ||
| 5 | |||
| 6 | > import Data.Map (Map, (!)) | ||
| 7 | > import qualified Data.Map as Map | ||
| 8 | |||
| 9 | - Efficient finite sets | ||
| 10 | |||
| 11 | > import Data.Set (Set) | ||
| 12 | > import qualified Data.Set as Set | ||
| 13 | |||
| 14 | - Some convenience functions for manipulating lists and endomorphisms | ||
| 15 | |||
| 16 | > import Control.Monad (guard, when) | ||
| 17 | > import Data.Monoid (Endo(..)) | ||
| 18 | |||
| 19 | - An arbitrary representation of a person | ||
| 20 | |||
| 21 | > type Person = Integer | ||
| 22 | |||
| 23 | Utilities | ||
| 24 | --------- | ||
| 25 | |||
| 26 | > (&!) :: a -> [a -> a] -> a | ||
| 27 | > -- ^ Reverse application of a list of endomorphisms | ||
| 28 | > x &! fs = foldMap Endo fs `appEndo` x | ||
| 29 | > | ||
| 30 | > infix 3 ==> | ||
| 31 | > -- | Logical implication | ||
| 32 | > (==>) :: Bool -> Bool -> Bool | ||
| 33 | > False ==> _ = True | ||
| 34 | > True ==> True = True | ||
| 35 | > True ==> False = False | ||
| 36 | |||
| 37 | <!-- | ||
| 38 | |||
| 39 | > pPrint :: PreferenceTable -> IO () | ||
| 40 | > pPrint = putStr . unlines . map (\(k, prefs) -> show k ++ ": " ++ unwords (map show prefs)) . Map.toList | ||
| 41 | > | ||
| 42 | > stepPhase1 :: PreferenceTable -> IO (Maybe PreferenceTable) | ||
| 43 | > stepPhase1 = phase1Iter Set.empty | ||
| 44 | > where | ||
| 45 | > phase1Iter :: Set Person -> PreferenceTable -> IO (Maybe PreferenceTable) | ||
| 46 | > -- ^ Call `phase1'` until no person is free | ||
| 47 | > phase1Iter engaged table = do | ||
| 48 | > let r = phase1' engaged table | ||
| 49 | > case r of | ||
| 50 | > Just (engaged', table') -> do | ||
| 51 | > when (table' /= table) $ do | ||
| 52 | > pPrint table' | ||
| 53 | > () <$ getLine | ||
| 54 | > if engaged' == Map.keysSet table' | ||
| 55 | > then return (Just table') | ||
| 56 | > else phase1Iter engaged' table' | ||
| 57 | > Nothing -> return Nothing | ||
| 58 | |||
| 59 | |||
| 60 | --> | ||
| 61 | |||
| 62 | Definitions | ||
| 63 | =========== | ||
| 64 | |||
| 65 | \begin{def*} | ||
| 66 | A \emph{preference table} is a finite set of persons, each associated with a list of other persons, ordered by preference. | ||
| 67 | \end{def*} | ||
| 68 | |||
| 69 | > type PreferenceTable = Map Person [Person] | ||
| 70 | |||
| 71 | \begin{def*} | ||
| 72 | We call a pair ${a, b}$ \emph{embedded} in a preference table if $a$ occurs in $b$s preference list and vice versa. | ||
| 73 | \end{def*} | ||
| 74 | |||
| 75 | Deleting a pair from a table means removing each from the others preference list: | ||
| 76 | |||
| 77 | > delPair :: (Person, Person) -> (PreferenceTable -> PreferenceTable) | ||
| 78 | > delPair (p1, p2) = Map.mapWithKey delPair' | ||
| 79 | > where | ||
| 80 | > delPair' k v = do | ||
| 81 | > z <- v | ||
| 82 | > guard $ k == p1 ==> z /= p2 | ||
| 83 | > guard $ k == p2 ==> z /= p1 | ||
| 84 | > return z | ||
| 85 | |||
| 86 | \begin{def*} | ||
| 87 | An ordered pair $(a, b)$ is said to be \emph{semiengaged} if $a$ occurs last in $b$s preference table and $b$ occurs first in $a$s. | ||
| 88 | |||
| 89 | This means that, while $b$ is $a$s best choice of partner, $a$ has no worse choice in partner than $a$ | ||
| 90 | \end{def*} | ||
| 91 | |||
| 92 | > semiEngaged :: (Person, Person) -> PreferenceTable -> Bool | ||
| 93 | > -- ^ `semiEngaged (x, y)`; is `x` last in `y`s preference list? | ||
| 94 | > semiEngaged (x, y) table = x == (last $ table ! y) | ||
| 95 | |||
| 96 | Phase 1 | ||
| 97 | ======= | ||
| 98 | |||
| 99 | > phase1' :: Set Person -> PreferenceTable -> Maybe (Set Person, PreferenceTable) | ||
| 100 | > phase1' engaged table | ||
| 101 | > | any null (Map.elems table) | ||
| 102 | > = Nothing -- If a preference list became empty: fail | ||
| 103 | > | Set.null free | ||
| 104 | > = Just (engaged, table) -- If nobody is free, we have nobody left to engage | ||
| 105 | > | otherwise | ||
| 106 | > = let x = Set.findMin free -- Arbitrary choice of free person | ||
| 107 | > y = head $ table ! x -- Best choice of engagement for x | ||
| 108 | > adjTable = [ delPair (x', y) | x' <- dropWhile (/= x) (table ! y), x' /= x ] | ||
| 109 | > -- ^ For all worse (than x) choices x' for y; drop them from y's preference list | ||
| 110 | > adjEngaged = [ Set.insert x -- x is now engaged | ||
| 111 | > ] ++ [ Set.delete z | z <- Map.keys table, semiEngaged (z, y) table, z /= x ] -- Nobody else is engaged to y | ||
| 112 | > in Just (engaged &! adjEngaged, table &! adjTable) | ||
| 113 | > where | ||
| 114 | > free = Map.keysSet table `Set.difference` engaged | ||
| 115 | |||
| 116 | The algorithm is iterated until all participants are engaged | ||
| 117 | |||
| 118 | > phase1 :: PreferenceTable -> Maybe PreferenceTable | ||
| 119 | > phase1 = phase1Iter Set.empty | ||
| 120 | > where | ||
| 121 | > phase1Iter :: Set Person -> PreferenceTable -> Maybe PreferenceTable | ||
| 122 | > -- ^ Call `phase1'` until no person is free | ||
| 123 | > phase1Iter engaged table = do | ||
| 124 | > (engaged', table') <- phase1' engaged table | ||
| 125 | > if engaged' == Map.keysSet table' | ||
| 126 | > then return table' | ||
| 127 | > else phase1Iter engaged' table' | ||
| diff --git a/ss2017/stable_marriage_problem/structure.md b/ss2017/stable_marriage_problem/structure.md index 89f467c..fa9ac96 100644 --- a/ss2017/stable_marriage_problem/structure.md +++ b/ss2017/stable_marriage_problem/structure.md | |||
| @@ -7,10 +7,12 @@ | |||
| 7 | - Definition: Tables, embedded tables, embedded pairs, embedded matchings | 7 | - Definition: Tables, embedded tables, embedded pairs, embedded matchings | 
| 8 | - Definition: stable tables | 8 | - Definition: stable tables | 
| 9 | - Matchings embedded in stable tables are stable (4.2.4 ii) | 9 | - Matchings embedded in stable tables are stable (4.2.4 ii) | 
| 10 | - (Stable tables are determined by all first OR all last entries (4.2.4 iii)) | 10 | - Stable tables are determined by all first OR all last entries (4.2.4 iii) | 
| 11 | - No pair absent from a stable table can block any of it's embedded matchings (4.2.4 i) | 11 | - No pair absent from a stable table can block any of it's embedded matchings (4.2.4 i) | 
| 12 | 12 | ||
| 13 | # Phase 1 | 13 | # Phase 1 | 
| 14 | - Removal of pairs from tables | ||
| 15 | - Engagement | ||
| 14 | - Present algorithm and demonstrate | 16 | - Present algorithm and demonstrate | 
| 15 | - Phase 1 has no effect on the embeddedness of stable pairs (4.2.3 i) | 17 | - Phase 1 has no effect on the embeddedness of stable pairs (4.2.3 i) | 
| 16 | - Phase 1 stabilizes a table, when it doesn't fail (4.2.2 + 4.2.3 ii) | 18 | - Phase 1 stabilizes a table, when it doesn't fail (4.2.2 + 4.2.3 ii) | 
| @@ -18,7 +20,8 @@ | |||
| 18 | 20 | ||
| 19 | # Rotations | 21 | # Rotations | 
| 20 | - Definition: rotation, exposure of rotations in stable tables | 22 | - Definition: rotation, exposure of rotations in stable tables | 
| 21 | - Rotations exposed in a stable T are either identical or disjunct (4.2.5) | 23 | - Directed graphs & tails | 
| 24 | - (Rotations exposed in a stable T are either identical or disjunct (4.2.5)) | ||
| 22 | 25 | ||
| 23 | # Phase 2 | 26 | # Phase 2 | 
| 24 | - Stable tables that are not already matchings expose at least one rotation and how to find it (4.2.6) | 27 | - Stable tables that are not already matchings expose at least one rotation and how to find it (4.2.6) | 
| @@ -26,4 +29,7 @@ | |||
| 26 | - ignores non-elements of rotation (4.2.7 iii) | 29 | - ignores non-elements of rotation (4.2.7 iii) | 
| 27 | - results in table consistent with rotation (4.2.7 i, ii) | 30 | - results in table consistent with rotation (4.2.7 i, ii) | 
| 28 | - Thus: produce stable subtables (4.2.8) | 31 | - Thus: produce stable subtables (4.2.8) | 
| 32 | - Subtables that don't agree with an exposed rotation have at least that rotation removed entirely (4.2.9) | ||
| 33 | - Any subtable can be created by removing a series of exposed rotations (Cor 4.2.2) | ||
| 34 | - Removal of rotations preserve matchings (Thm 4.2.1) | ||
| 29 | - Present derived algorithm and demonstrate | 35 | - Present derived algorithm and demonstrate | 
