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 |