Segmentlab
实验背景
本实验研究了如何将星型收缩法应用至生成无向图的最小生成树的方法(Bor˚ uvka’s Algorithm),并在此基础上通过Python处理图像
实验细节
1 Bor˚ uvka’s Algorithm
1.1 MST
MST : edge seq * int -> edge seq
函数功能:
生成所给图的最小生成树,并以edge seq 的形式返回
函数思路:
以随机生成的0,1串模拟硬币的正反面,运用Bor˚ uvka’s Algorithm即可,注意修改各点信息的存储形式以使得时间复杂度得以在数据量大的时候能够胜任
函数代码:
type vertex = int
type weight = int
type edge = vertex * vertex * weight
fun cmp (x,y) = Int.compare (x,y)
fun pint n = print ((Int.toString n)^" ")
fun MST (E : edge seq, n : int) : edge seq =
let
fun joinerStarContract (V,E,s) =
let
val minE = filter (fn (_,(a,_,_)) => a>=0) (enum (inject E (tabulate (fn _ => (~1,~1,(~1,~1,~1))) n)))
val coins = Rand.flip s n
val P = filter (fn (u,(v,w,l)) => ((nth coins u) = 0 andalso (nth coins v) = 1) ) minE
val V' = inject (map (fn (u,(v,_,_)) => (u,v)) P) V
in
(V',P)
end
fun MST' ((V,E),S,seed) =
if length E = 0 then S
else
let
val _ = ()
val _ = pint (length E)
val (V',PT) = joinerStarContract (V,E,seed)
val _ = pint (length PT)
val E' = filter (fn (u,(v,w,l)) => u<>v) (map (fn (u,(v,w,l)) => (nth V' u,(nth V' v,w,l))) E)
val S' = map (fn (u,(v,w,l)) => l) PT
val _ = pint (length E')
val _ = print "\n"
val seed' = Rand.next seed
in
MST' ((V',E'),append (S,S'),seed')
end
val V = tabulate (fn i => i) n
val E' = map (fn (u,v,w) => (u,(v,w,(u,v,w)))) (rev (sort (fn ((_,_,w1),(_,_,w2)) => cmp (w1,w2)) E))
in
MST' ((V,E'),empty(),Rand.fromInt 2017)
end
渐进复杂度分析:
joinStarContract:
Work | Span | |
minE | O(m+n) | O(logm) |
coins | O(n) | O(logn) |
P | O(m) | O(logm) |
V' | O(m+n) | O(logm+logn) |
故 W=O(m+n) S=O(logn)
MST':
Work | Span | |
(V',PT) | O(m+n) | O(logn) |
E' | O(m) | O(logm) |
S' | O(m) | O(logm) |
seed' | O(1) | O(1) |
故有迭代式:
前提:可以证明,每一轮收缩至少会收缩1/4的点
W(m,n)=W(m,3/4n)+O(m+n)
累加有:
W=O(mlogn+n)
S(m,n)=S(m,3/4n)+O(logn)
累加有:
S=O(log^2n)
2. Image segmentation
findSegment: (edge Seq.seq * int) -> int -> vertex Seq.seq
函数功能:
在给定每一个点的 initial credits条件下返回一张图片中能够生成的森林,以每个点的对应的祖先而构成的串的形式返回
函数思路:
引入 initial credits情况下,先使用之前的生成MST的算法生成一片森林,然后通过filter找出森林之中作为祖先,即一棵树的顶点的点,对这些点进行广度优先搜索以使其映射到其子孙,最后inject到点构成的串即可
函数代码:
type vertex = int
type weight = int
type edge = vertex * vertex * weight
type point = vertex * vertex
fun cmp (x,y) = Int.compare (x,y)
fun pint n = print ((Int.toString n)^" ")
fun findSegments (E, n) initial_credit =
let
fun joinerStarContract (V,E,I,s) =
let
val minE = filter (fn (_,(a,_)) => a>=0) (enum (inject E (tabulate (fn _ => (~1,~1)) n)))
val coins = Rand.flip s n
fun isContracted u v = ((nth coins u) = 0 andalso (nth coins v) = 1)
val P = filter (fn (u,(v,w)) => isContracted u v) minE
fun mask ((Iu,w),(Iu',w')) = (Int.min (Iu,Iu'),w+w')
val P' = map (fn (v,n) => (v,reduce mask (1000000,0) n)) (collect cmp (map (fn (u,(v,w)) => (v,(nth I u,w))) P))
val I' = inject (map (fn (v,(Iu,w)) => (v,Int.min (nth I v,Iu)-w)) P') I
(*val I' = inject (map (fn (u,(v,w)) => (u,nth I v - w)) P) I*)
val V' = inject (map (fn (u,(v,_)) => (u,v)) P) V
in
(V',P,I')
end
fun MST' ((V,E),seed,I) =
if length E = 0 then V
else
let
val _ = ()
fun isValid (u,(v,w)) = Int.min (nth I u,nth I v) >= w
val (V',PT,I') = joinerStarContract (V,E,I,seed)
val _ = pint (length PT)
val preE = filter (fn x => isValid x) E
val E' = filter (fn (u,(v,w)) => u<>v) (map (fn (u,(v,w)) => (nth V' u,(nth V' v,w))) preE)
val _ = pint (length E')
val _ = print "\n"
val seed' = Rand.next seed
in
MST' ((V',E'),seed',I')
end
val V = tabulate (fn i => i) n
val E' = map (fn (u,v,w) => (u,(v,w))) (rev (sort (fn ((_,_,w1),(_,_,w2)) => cmp (w1,w2)) E))
val I = tabulate (fn _ => initial_credit) n
val V' = MST' ((V,E'),Rand.fromInt 2017,I)
val preE = filter (fn (x,y) => x<>y) (mapIdx (fn (i,x) => (x,i)) V')
val G = inject (collect cmp preE) (tabulate (fn _ => empty()) n)
val S = filterIdx (fn (i,x) => i=x) V'
fun BFS (X,F,s) =
case (length F) of
0 => X
| _ =>
let
val X' = append (X,map (fn x => (x,s)) F)
val F' = flatten (map (fn x => nth G x) F)
in
BFS (X',F',s)
end
val injection = flatten (map (fn x => BFS (empty (),nth G x,x)) S)
in
inject injection V
end
3 Written Problems
3.1 Second-best is good enough for my MST. Let G = (V,E) be a simple, connected,
undirected graph G = (V,E) with |E| ≥ 2 and distinct edge weights. We know for a fact that the smallest
(i.e., least heavy) edge of G must be in the minimum spanning tree (MST) of G. Prove that the 2 nd
smallest edge of G must also be in the minimum spanning tree of G.
假设可以找到一颗不含权值第二小的边的MST,那么将权值第二小的边加入到MST中生成带环的图,而该环路中必然含有比这条边大的边,则把这条边去掉就得到更小的一颗MST,这与假设矛盾,故得证。
3.2 I Prefer Chalk. There is a very unusual street in your neighborhood. This street
forms a perfect circle, and there are n ≥ 3 houses on this street. As the unusual mayor of this unusual
neighborhood, you decide to hold an unusual lottery. Each house is assigned a random number r ∈ R
[0,1] (drawn uniformly at random). Any house that receives a larger number than both of its two
neighbors wins a prize package consisting of a whiteboard marker and two pieces of chalk in celebration
of education. What is the expected number of prize packages given? Justify your answer.
对一座房子进行分析:
该座房子可以在0~1取值
而对于某个值x,其相邻得两座房子得值应在0~x之间,则概率为x^2
故该座房子得讲的概率为对x^2得积分,P=1/3
所以期望应为n/3
3.3 It’s Probably Linear.