Skip to content

Commit ffe0c1f

Browse files
ch7 updated
1 parent 4adb580 commit ffe0c1f

File tree

2 files changed

+153
-4
lines changed

2 files changed

+153
-4
lines changed

Diff for: ch7-efficiency.ipynb

+144-4
Original file line numberDiff line numberDiff line change
@@ -274,29 +274,165 @@
274274
"아래 cp''는 cp'와 동일한 성능을 가진다.\n",
275275
"\n",
276276
" cp'' [] = [[]]\n",
277-
" cp'' (x:xss) = [x:ys | x <- xs, ys <- yss]\n",
277+
" cp'' (xs:xss) = [x:ys | x <- xs, ys <- yss]\n",
278278
" where yss = cp xss"
279279
]
280280
},
281281
{
282282
"cell_type": "markdown",
283283
"metadata": {},
284284
"source": [
285-
"# 7.4 Analysing time"
285+
"# 7.4 Analysing time\n",
286+
"\n",
287+
"* 시간 복잡도는 expression의 속성이지 value의 속성은 아니다.\n",
288+
"* GHCi에서는 reduction step이 아닌 소요시간만을 측정한다. reduction 단계는 소요 시간과 반드시 일치하지는 않는다.\n",
289+
"* 상황에 따라서 다른 측정 방법이 필요하다. 예를 들면 concat xss의 경우 n보다는 (m,n)이 적합하다.\n",
290+
"* 시간 복잡도 측정은 eager evaluation으로 행한다. lazy evaluation은 측정이 어려우며 일반적으로 eager evaluation의 time이 lazy evaluation의 time 보다 tight boundary를 가진다.\n",
291+
"\n",
292+
"## Concat\n",
293+
"\n",
294+
" concat xss = foldr (++) [] xss\n",
295+
" concat' xss = foldl (++) [] xss\n",
296+
"\n",
297+
"T(++)(n,m) = $Ө(n)$임\n",
298+
"\n",
299+
"* concat: 길이 n의 리스트를 m회 (++) 함 $\\Theta (mn)$\n",
300+
"* concat': mn으로 증가하는 accumulator를 n회 (++) 함. $\\Theta (m^2 n$)\n",
301+
"\n",
302+
"concat은 foldr로 구현하는 것이 더 효율적임. foldl/foldr/foldl'이 적합한 경우가 다르다.\n",
303+
"\n",
304+
"## subseq\n",
305+
"\n",
306+
" subseqs (x:xs) = subseqs xs ++ map (x:) (subseqs xs)\n",
307+
" subseqs' (x:xs) = xss ++ map (x:) xss\n",
308+
" where xss = subseqs' xs\n",
309+
"\n",
310+
"map (x:)는 $\\Theta (2^n)$이므로 \n",
311+
"\n",
312+
"* $T(subseqs)(n+1) = 2T(subseqs)(n) + \\Theta (2^n) \\rightarrow T(subseqs)(n) = \\Theta (n 2^n)$\n",
313+
"* $T(subseqs')(n+1) = T(subseqs')(n) + \\Theta (2^n) \\rightarrow T(subseqs')(n) = \\Theta (2^n)$\n",
314+
"\n",
315+
"subseqs'가 logarithmic factor로 더 빠르다. 속도가 중요한 경우 common subexpression elimination을 잘 활용하자.\n",
316+
"\n",
317+
"## cartesian product\n",
318+
"\n",
319+
" cp [] = [[]]\n",
320+
" cp (xs:xss) = [x:ys | x <- xs, ys <- cp xss]\n",
321+
" cp' = foldr op [[]]\n",
322+
" where op xs yss = [x:ys | x <- xs, ys <- yss]\n",
323+
"\n",
324+
"cp에서 cp xss가 $\\Theta (n^m)$ 이고 m회만큼 반복하게 된다.\n",
325+
"\n",
326+
"* $T(cp)(m,n) = \\Theta (m n^m)$\n",
327+
"* $T(cp')(m,n) = \\Theta (n^m)$\n",
328+
"\n",
329+
"cp'가 logarithmic factor로 더 빠르다."
286330
]
287331
},
288332
{
289333
"cell_type": "markdown",
290334
"metadata": {},
291335
"source": [
292-
"# 7.5 Accumulating Parameter"
336+
"# 7.5 Accumulating Parameter\n",
337+
"\n",
338+
"argument를 추가로 사용하여 속도를 향상시키는 것을 accumulating parameter라고 한다.\n",
339+
"\n",
340+
"## reverse\n",
341+
"\n",
342+
" reverse [] = []\n",
343+
" reverse (x:xs) = reverse xs ++ [x]\n",
344+
"\n",
345+
"++가 $\\Theta (n)$이고 n번 재귀를 하므로 T(reverse)(n)은 $\\theta (n^2)$ 이다.\n",
346+
"\n",
347+
" revcat :: [a] -> [a] -> [a]\n",
348+
" revcat xs ys = reverse xs ++ ys\n",
349+
"\n",
350+
"revcat은 accumulator를 사용해서 (++) 대신 (:) 을 사용한 것과 동일해짐. 따라서 $\\theta (n)$ 임\n",
351+
"\n",
352+
" [x] ++ xs = x:xs\n",
353+
"\n",
354+
"## length\n",
355+
"\n",
356+
" length :: [a] -> Int\n",
357+
" length [] = 0\n",
358+
" length (x:xs) = length xs + 1\n",
359+
" \n",
360+
" lenplus :: [a] -> Int -> Int\n",
361+
" lenplus [] n = n\n",
362+
" lenplus (x:xs) n = lenplus xs (1+n)\n",
363+
"\n",
364+
"time은 $\\Theta (n)$으로 동일하다. length는 space가 $\\Theta (n)$으로 증가하나 lenplus는 $\\Theta (1)$ 이다. (haskell의 length는 lenplus처럼 구현됨.)\n",
365+
"\n",
366+
"## tree\n",
367+
"\n",
368+
" data GenTree a = Node a [GenTree a]\n",
369+
" \n",
370+
" labels :: GenTree a -> [a]\n",
371+
" labels (Node x ts) = x:concat (map labels ts)\n",
372+
" \n",
373+
" 1\n",
374+
" / \\\n",
375+
" 2 3 labels = \"123\"\n",
376+
"\n",
377+
"> $T(labels)(1,k) = \\Theta(1)$\n",
378+
"> $T(labels)(h+1,k) = \\Theta(1) + T(concat)(k,s) + T(map labels)(h,k)$\n",
379+
"\n",
380+
"각 높이에서 k개의 subtree에 대해서 map labels가 수행되고 이것들을 concat해야됨. \n",
381+
"\n",
382+
"$$T(labels)(h+1,k) = \\Theta(k^{h+1}) + k T(labels)(h,k)$$\n",
383+
"\n",
384+
"따라서 $s = k^h$일때 $\\Theta (s \\log s)$ 임.\n",
385+
"\n",
386+
" labcat :: [GenTree a] -> [a] -> [a]\n",
387+
" labcat ts xs = concat (map labels ts) ++ xs\n",
388+
"\n",
389+
" labcat (Node x us:vs) xs\n",
390+
" = {definition}\n",
391+
" concat (map labels (Node x us:vs)) ++ xs\n",
392+
" = {definitions}\n",
393+
" labels (Node x us) ++ concat (map labels vs) ++ xs\n",
394+
" = {definiton}\n",
395+
" x:concat (map labels us) ++ concat (map labels vs) ++ xs\n",
396+
" = {definition of labcat}\n",
397+
" x:concat (map labels us) ++ labcat vs xs\n",
398+
" = {definition of labcat (again)}\n",
399+
" x:labcat us (labcat vs xs)\n",
400+
"\n",
401+
" labels' t = labcat [t] []\n",
402+
" labcat' [] xs = xs\n",
403+
" labcat' (Node x us:vs) = x:labcat' us (labcat' vs xs)\n",
404+
"\n",
405+
"* $T(labcat)(1,k,n) = \\Theta (n)$\n",
406+
"* $T(labcat)(h,k,n) = \\Theta (k^h n)$\n",
407+
"* tree size $s = k^h$\n",
408+
"\n",
409+
"따라서 $T(labels)(h,k) = T(labcat)(h,k,1) = \\Theta (s)$"
293410
]
294411
},
295412
{
296413
"cell_type": "markdown",
297414
"metadata": {},
298415
"source": [
299-
"# 7.6 Tupling"
416+
"# 7.6 Tupling\n",
417+
"\n",
418+
"# fibonacci\n",
419+
"\n",
420+
" fib :: Int -> Integer\n",
421+
" fib 0 = 0\n",
422+
" fib 1 = 1\n",
423+
" fib n = fib (n-1) + fib (n-2)\n",
424+
"\n",
425+
"$T(fib)(n) = \\Theta (\\phi ^ n)$ 이며 golden ratio $\\phi = (1 + \\sqrt{5}) / 2$\n",
426+
"\n",
427+
" fib' 0 = (0,1)\n",
428+
" fib' n = (b,a+b) where (a,b) = fib' (n-1)\n",
429+
"\n",
430+
"fib는 exponential time이나 fib'는 linear time임.\n",
431+
"\n",
432+
"## general law for tupling\n",
433+
"\n",
434+
" (foldr f a xs, foldr g b xs) = foldr h (a,b) xs\n",
435+
" h x (y,z) = (f x y, g x z)"
300436
]
301437
},
302438
{
@@ -312,6 +448,10 @@
312448
"collapsed": false
313449
},
314450
"source": [
451+
"# Conclusion\n",
452+
"\n",
453+
"functional programming에서 performance와 efficiency에 그 동안 궁금했던 것들을 조금은 해결할 수 있었다. 그러나 알면 알수록 functional programming으로 좋은 코드를 작성하는 것이 쉽지 않다는 생각이 든다.\n",
454+
"\n",
315455
"\n",
316456
"# Reference\n",
317457
"\n",

Diff for: src/ch7-cp.hs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cp [] = [[]]
2+
cp (xs:xss) = [x:ys | x <- xs, ys <- cp xss]
3+
4+
cp' = foldr op [[]]
5+
where op xs yss = [x:ys | x <- xs, ys <- yss]
6+
7+
cp'' [] = [[]]
8+
cp'' (xs:xss) = [x:ys | x <- xs, ys <- yss]
9+
where yss = cp xss

0 commit comments

Comments
 (0)