diff --git a/7e1810-algo_hw/hw1.typ b/7e1810-algo_hw/hw1.typ index dae0d5e..f2d3325 100644 --- a/7e1810-algo_hw/hw1.typ +++ b/7e1810-algo_hw/hw1.typ @@ -1,13 +1,19 @@ - == HW 1 (Week 2) Due: 2024.03.17 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 2.3-5 You can also think of insertion sort as a recursive algorithm. In order to sort $A[1 : n]$, recursively sort the subarray $A[1 : n – 1]$ and then insert $A[n]$ into the sorted subarray $A[1 : n – 1]$. Write pseudocode for this recursive version of insertion sort. Give a recurrence for its worst-case running time. -#text(fill: blue)[ - === Solution 2.3-5 - +#ans[ The pseudocode for this recursive version of insertion sort is as follows: ```txt @@ -38,40 +44,36 @@ You can also think of insertion sort as a recursive algorithm. In order to sort Although merge sort runs in $Theta(n lg n)$ worst-case time and insertion sort runs in $Theta(n^2)$ worst-case time, the constant factors in insertion sort can make it faster in practice for small problem sizes on many machines. Thus it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when subproblems become suffificiently small. Consider a modifification to merge sort in which $n\/k$ sublists of length $k$ are sorted using insertion sort and then merged using the standard merging mechanism, where $k$ is a value to be determined. -- a. Show that insertion sort can sort the $n\/k$ sublists, each of length $k$, in $Theta(n k)$ worst-case time. -- b. Show how to merge the sublists in $Theta(n lg(n\/k))$ worst-case time. -- c. Given that the modifified algorithm runs in $Theta(n k + n lg(n\/k))$ worst-case time, what is the largest value of $k$ as a function of $n$ for which the modifified algorithm has the same running time as standard merge sort, in terms of $Theta$-notation? -- d. How should you choose $k$ in practice? - -#text(fill: blue)[ - === Solution 2-1 - - - a. For each sublist, the insertion sort can sort the $k$ elements in $Theta(k^2)$ worst-case time. Thus, the insertion sort can sort the $n\/k$ sublists, each of length $k$, in $Theta(n k)$ worst-case time. - - b. Given $n\/k$ sorted sublists, each of length $k$, the recurrence for merging the sublists is - $ - T(n) = cases(2 dot.c T(n\/2) + Theta(n) space.quad & n>k, 0 & n=k) - $ - The solution to the recurrence is $Theta(n lg(n\/k))$ worst-case time. - - *This could also be viewed as a tree with $lg(n\/k)$ levels with $n$ element in each level. Worst case would be $Theta(n lg (n\/k))$* - - - c. Take $Theta(n k + n lg(n \/ k)) = Theta(n lg n)$, consider $k = Theta(lg n)$: - $ - Theta(n k + n lg(n \/ k)) - &= Theta (n k + n lg n - n lg k) \ - &= Theta (n lg n + n lg n - n lg (lg n)) \ - &= Theta (n lg n) - $ - - d. Choose $k$ to be the largest length of sublist for which insertion sort is faster than merge sort. Use a small constant such as $5$ or $10$. ++ Show that insertion sort can sort the $n\/k$ sublists, each of length $k$, in $Theta(n k)$ worst-case time. ++ Show how to merge the sublists in $Theta(n lg(n\/k))$ worst-case time. ++ Given that the modifified algorithm runs in $Theta(n k + n lg(n\/k))$ worst-case time, what is the largest value of $k$ as a function of $n$ for which the modifified algorithm has the same running time as standard merge sort, in terms of $Theta$-notation? ++ How should you choose $k$ in practice? + +#ans[ + + For each sublist, the insertion sort can sort the $k$ elements in $Theta(k^2)$ worst-case time. Thus, the insertion sort can sort the $n\/k$ sublists, each of length $k$, in $Theta(n k)$ worst-case time. + + Given $n\/k$ sorted sublists, each of length $k$, the recurrence for merging the sublists is + $ + T(n) = cases(2 dot.c T(n\/2) + Theta(n) space.quad & n>k, 0 & n=k) + $ + The solution to the recurrence is $Theta(n lg(n\/k))$ worst-case time. + + *This could also be viewed as a tree with $lg(n\/k)$ levels with $n$ element in each level. Worst case would be $Theta(n lg (n\/k))$* + + + Take $Theta(n k + n lg(n \/ k)) = Theta(n lg n)$, consider $k = Theta(lg n)$: + $ + Theta(n k + n lg(n \/ k)) + &= Theta (n k + n lg n - n lg k) \ + &= Theta (n lg n + n lg n - n lg (lg n)) \ + &= Theta (n lg n) + $ + + Choose $k$ to be the largest length of sublist for which insertion sort is faster than merge sort. Use a small constant such as $5$ or $10$. ] === Question 4.2-3 What is the largest $k$ such that if you can multiply $3 times 3$ matrices using $k$ multiplications (not assuming commutativity of multiplication), then you can multiply $n times n$ matrices in $o(n lg 7)$ time? What is the running time of this algorithm? -#text(fill: blue)[ - ==== Solution 4.2-3 - +#ans[ Assuming $n = 3^m$. Use block matrix multiplication, the recursive running time is $T(n) = k T(n\/3) + O(1)$. When $log_3 k > 2 $, using master theorem, the largest $k$ to satisfy $log_3 k < lg 7$ is $k=21$. diff --git a/7e1810-algo_hw/hw2.typ b/7e1810-algo_hw/hw2.typ index 8ee030a..89c8e5a 100644 --- a/7e1810-algo_hw/hw2.typ +++ b/7e1810-algo_hw/hw2.typ @@ -1,11 +1,17 @@ == HW 2 (Week 3) Due: 2024.03.24 -=== Question 6.2-6 -The code for MAX-HEAPIFY is quite efficient in terms of constant factors, except possibly for the recursive call in line 10, for which some compilers might produce inefficient code. Write an efficient MAX-HEAPIFY that uses an iterative control construct (a loop) instead of recursion. -#text(fill: blue)[ - ==== Solution 6.2-6 +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] +=== Question 6.2-6 +The code for MAX-HEAPIFY is quite efficient in terms of constant factors, except possibly for the recursive call in line 10, for which some compilers might produce inefficient code. Write an efficient MAX-HEAPIFY that uses an iterative control construct (a loop) instead of recursion. +#ans[ Consider the following pseudocode code: ```txt MAX-HEAPIFY(A, i) @@ -30,57 +36,49 @@ The code for MAX-HEAPIFY is quite efficient in terms of constant factors, except === Question 6.5-9 Show how to implement a first-in, first-out queue with a priority queue. Show how to implement a stack with a priority queue. (Queues and stacks are defined in Section 10.1.3.) -#text(fill: blue)[ - ==== Solution 6.5-9 - +#ans[ - For stack, add element with increasing priority, and pop the element with the highest priority, pseudocode: - // ```txt - // PUSH(S, x) - // S.top = S.top + 1 - // S[S.top] = x - // POP(S) - // if S.top < 1 - // error "underflow" - // else - // S.top = S.top - 1 - // return S[S.top + 1] - // ``` + ```txt + PUSH(S, x) + S.top = S.top + 1 + S[S.top] = x + POP(S) + if S.top < 1 + error "underflow" + else + S.top = S.top - 1 + return S[S.top + 1] + ``` - For queue, add element with decreasing priority, and pop the element with the highest priority, pseudocode: - // ```txt - // ENQUEUE(Q, x) - // Q.tail = Q.tail + 1 - // Q[Q.tail] = x - // DEQUEUE(Q) - // if Q.head > Q.tail - // error "underflow" - // else - // return Q[Q.head] - // ``` + ```txt + ENQUEUE(Q, x) + Q.tail = Q.tail + 1 + Q[Q.tail] = x + DEQUEUE(Q) + if Q.head > Q.tail + error "underflow" + else + return Q[Q.head] + ``` ] === Question 7.4-6 Consider modifying the PARTITION procedure by randomly picking three elements from subarray $A[p : r]$ and partitioning about their median (the middle value of the three elements). Approximate the probability of getting worse than an $alpha$-to-$(1 - alpha)$ split, as a function of $alpha$ in the range $0 < alpha < 1/2$. - -#text(fill: blue)[ - ==== Solution 7.4-6 - +#ans[ *Assuming the same element could be picked more than once*(which should be the case in real world). The probability of getting worse than an $alpha$-to-$(1 - alpha)$ split is the probability of picking the smallest or the largest element as the median. $ - P = 2 * [binom(2,3) times alpha^2(1 - alpha) + alpha^3] = 6 alpha^2 - 4 alpha^3 + P = 2 * [binom(2,3) times alpha^2(1 - alpha) + alpha^3] = 6 alpha^2 - 4 alpha^3 $ ] === Question 8.2-7 Counting sort can also work efficiently if the input values have fractional parts, but the number of digits in the fractional part is small. Suppose that you are given n numbers in the range $0$ to $k$, each with at most $d$ decimal (base $10$) digits to the right of the decimal point. Modify counting sort to run in $Theta(n + 10^d k)$ time. - -#text(fill: blue)[ - ==== Solution 8.2-7 - +#ans[ To achieve $Theta(n + 10^d k)$ time, we first use $Theta(n)$ time to multiply each number by $10^d$, then change the $C[0, k]$ to $C[0, 10^d k]$, and finally use $Theta(10^d k)$ time to sort the numbers. With other part of the counting sort unchanged, the pseudocode is as follows: @@ -104,10 +102,7 @@ Counting sort can also work efficiently if the input values have fractional part === Question 8.3-5 Show how to sort $n$ integers in the range $0$ to $n^3 - 1$ in $O(n)$ time. - -#text(fill: blue)[ - ==== Solution 8.3-5 - +#ans[ First convert each number to base $n$, then use counting sort to sort the numbers. Since each number would now have at most $log_n n^3 = 3$ digits, 3 passes of counting sort would be enough to sort the numbers, during which each pass would take $O(n)$ time since there's only $n$ numbers. @@ -116,15 +111,11 @@ Show how to sort $n$ integers in the range $0$ to $n^3 - 1$ in $O(n)$ time. === Question 9.3.9 Describe an $O(n)$-time algorithm that, given a set $S$ of $n$ distinct numbers and a positive integer $k <= n$, determines the $k$ numbers in $S$ that are closest to the median of $S$. - -#text(fill: blue)[ - ==== Solution 9.3.9 - +#ans[ + $O(n)$: Using SELECT, we can find $x$ to be the median of $S$. + $O(n)$: Subtract $x$ from each element in $S$. + $O(n)$: Use COUNTING-SORT to sort the absolute values of the differences. + $O(k)$: Return the first $k$ elements in the sorted array. This is the required $O(n)$-time algorithm. - ] \ No newline at end of file diff --git a/7e1810-algo_hw/hw3.typ b/7e1810-algo_hw/hw3.typ index 24dd00e..6a20ce8 100644 --- a/7e1810-algo_hw/hw3.typ +++ b/7e1810-algo_hw/hw3.typ @@ -1,12 +1,18 @@ == HW 3 (Week 4) Due: 2024.03.31 +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 12.2-3 Write the `TREE-PREDECESSOR` procedure(which is symmetric to `TREE-SUCCESSOR`). -#text(fill: blue)[ - === Solution 12.2-3 - +#ans[ ```txt TREE-PREDECESSOR(x) if x.left != nil @@ -22,9 +28,7 @@ Write the `TREE-PREDECESSOR` procedure(which is symmetric to `TREE-SUCCESSOR`). === Question 13.1-5 Show that the longest simple path from a node $x$ in red-black tree to a descendant leaf at most twice that of the shortest simple path from node $x$ to a descendant leaf. -#text(fill: blue)[ - === Solution 13.1-5 - +#ans[ Consider the longest simple path $(a_1, ... ,a_s)$ & the shortest simple path $(b_1, ... ,b_t)$, they have equal number of black nodes (Property 5). Neither of the paths can have repeated red node (Property 4). Thus at most $floor((s - 1) / 2)$ of the nodes in the longest path are red, so $ t >= ceil((s+1)/2) $ If by way of contradiction, we had $s > t dot 2$, then $ t >= ceil((s+1) / 2) >= ceil(t+1) = t+1 $ which is a contradiction. @@ -33,17 +37,13 @@ Show that the longest simple path from a node $x$ in red-black tree to a descend === Question 17.1-7 Show how to use an order-statistic tree to count the number of inversions in an array of $n$ distinct elements in $O(n lg n)$ time. -#text(fill: blue)[ - === Solution 17.1-7 - +#ans[ $O(n lg(n))$ time is required to build a red-black treem so everytime we insert a node, we can calculate the number of inversion using $"OS-RANK"$ (which is the rank of the node, thus calculating inversions). ] === Question 17.3-2 Describe an efficient algorithm that, given an interval $i$, returns an interval overlapping $i$ that has the minimum low endpoint, or $T."nil"$ if no such interval exists. -#text(fill: blue)[ - === Solution 17.3-2 - +#ans[ Modify the usual interval search not to break out the loop when a overlap is found, but to keep track of the minimum low endpoint. Return the interval with the minimum low endpoint if found, otherwise return $T."nil"$. ] \ No newline at end of file diff --git a/7e1810-algo_hw/hw4.typ b/7e1810-algo_hw/hw4.typ index c56d2c6..389c58b 100644 --- a/7e1810-algo_hw/hw4.typ +++ b/7e1810-algo_hw/hw4.typ @@ -1,11 +1,18 @@ == HW4 (Week 5) Due: 2024.04.07 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 14.4-2 Give pseudocode to reconstruct an LCS from te completed c table (See Theorem 14.1 Optimal substructure of an LCS) and the original sequences $X = angle.l x_1, x_2, dots.c, x_m angle.r$ and $Y = angle.l y_1, y_2, dots.c y_n angle.r$ in $O(m+n)$ time, without using the b table. -#text(fill: blue)[ - === Solution 14.4-2 - +#ans[ Consider the following pseudocode: ```txt @@ -25,9 +32,7 @@ Give pseudocode to reconstruct an LCS from te completed c table (See Theorem 14. === Question 14.4-5 Give an $O(n^2)$-time algorithm to find the longest monotonically increasing subsequence of a sequence of $n$ numbers. -#text(fill: blue)[ - === Solution 14.4-5 - +#ans[ Given a sequence of numbers $L$, make a copy and sort it, let the $L^'$ be the sorted array: $o(n^2)$ time to sort $L$ diff --git a/7e1810-algo_hw/hw5.typ b/7e1810-algo_hw/hw5.typ index 3c77667..97639fd 100644 --- a/7e1810-algo_hw/hw5.typ +++ b/7e1810-algo_hw/hw5.typ @@ -1,8 +1,16 @@ -#import "@preview/cetz:0.2.2": canvas, draw, tree +#import "@preview/cetz:0.2.2": * == HW5 (Week 6) Due: 2024.04.14 +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 14.5-2 Determine the cost and structure of an optimal binary serach tree for a set of $n=7$ keys with the following probabilities: @@ -44,9 +52,7 @@ Determine the cost and structure of an optimal binary serach tree for a set of $ ) ] -#text(fill: blue)[ - === Solution 14.5-2 - +#ans[ Running the code provided in appendix, we get the following result (cost, preorder traversal of the optimal BST): ```text (3.17, [5, 2, 1, 3, 4, 7, 6]) @@ -127,8 +133,7 @@ What is an optimal Huffman code for the following set of frequencies, based on t Can you generalize your answer to find the optimal code when the frequencies are the first $n$ Fibonacci numbers? -#text(fill: blue)[ - === Solution 15.3-3 +#ans[ #align(center)[ #table( stroke: none, @@ -175,8 +180,8 @@ Can you generalize your answer to find the optimal code when the frequencies are Proof is also trivial, let's discuss sums of Fibonacci first: $ - f_n = f_(n-1) + f_(n-2) => f_(n) = f_(n+2) - f_(n-1)\ - sum_(i=0)^n f_i = f_(n+2) - 1 => sum_(i=0)^n f_i < f_(n+2) + f_n = f_(n-1) + f_(n-2) => f_(n) = f_(n+2) - f_(n-1)\ + sum_(i=0)^n f_i = f_(n+2) - 1 => sum_(i=0)^n f_i < f_(n+2) $ so after merging the first $k$ elements, we're left with $((sum_(i=0)^k f_i), f_(k+1), dots.c, f_n)$, amoung which $((sum_(i=k)^n f_i), f_(k+1))$ are the smallest two, so they should be merged first, and so on, using induction it's easy to prove Huffman generates such tree, thus giving the optimal code. diff --git a/7e1810-algo_hw/hw6.typ b/7e1810-algo_hw/hw6.typ index feb2f43..292fdb6 100644 --- a/7e1810-algo_hw/hw6.typ +++ b/7e1810-algo_hw/hw6.typ @@ -1,15 +1,21 @@ -#import "@preview/cetz:0.2.2": canvas, draw, tree +#import "@preview/cetz:0.2.2": * == HW6 (Week 7) Due: 2024.04.21 +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 20.1-3 The transpose of a directed graph $G=(V,E)$ is the graph $G^T = (V, E^T)$ where $ E^T = {(v,u) in V times V:(u,v) in E} $ That is, $G^T$ is $G$ with all its edges reversed. *Describe efficient algorithms for computing $G^T$ from $G$, for both the adjacency-list and adjacency-matrix representation of $G$, Analyze the running times of your algorithms.* -#text(fill: blue)[ - === Solution 20.1-3 - +#ans[ - adjacency-list: ```txt @@ -62,9 +68,7 @@ Under the assumption of uniform independent hashing, if all edge lookups are equ Give an example of a directed graph $G=(V,E)$, a source vertex $s in V$, and a set of tree edges $E_pi subset.eq E$ such that for each vertex $v in V$, the unique simple path in the graph $(V, E_pi)$ from $s$ to $v$ is a shortest path in $G$, yet the set of edges $E_pi$ cannot be produced by running BFS on $G$, no matter how the vertices are ordered in each adjacency list. -#text(fill: blue)[ - === Solution 20.2-6 - +#ans[ Consider the following graph $G$: #let data = ( @@ -119,7 +123,7 @@ Give an example of a directed graph $G=(V,E)$, a source vertex $s in V$, and a s [ #let data = ( [$1$], - ([$2$], [$4$],[$5$]), + ([$2$], [$4$], [$5$]), ([$3$]), ) @@ -153,10 +157,11 @@ Give an example of a directed graph $G=(V,E)$, a source vertex $s in V$, and a s ) }, ) - ],[ + ], + [ #let data = ( [$1$], - ([$3$], [$4$],[$5$]), + ([$3$], [$4$], [$5$]), ([$2$]), ) @@ -190,7 +195,7 @@ Give an example of a directed graph $G=(V,E)$, a source vertex $s in V$, and a s ) }, ) - ] + ], ) ] @@ -241,9 +246,7 @@ Give an example of a directed graph $G=(V,E)$, a source vertex $s in V$, and a s Another way to topologically sort a directed acyclic graph $G=(V,E)$ is to repeatedly find a vertex of in-degree $0$, output it, and remove it and all of its outgoing edges from the graph. *Explain how to implement this idea so that is runs in time $O(V + E)$. What happens to this algorithm if $G$ has cycles?* -#text(fill: blue)[ - === Solution 20.4-5 - +#ans[ - Implementation: ```txt @@ -277,9 +280,7 @@ Another way to topologically sort a directed acyclic graph $G=(V,E)$ is to repea Prove that for any directed graph $G$, the transpose of the component graph $G^T$ is the same as the component graph of $G$. That is $((G^T)^(S C C))^T = G^(S C C)$ -#text(fill: blue)[ - === Solution 20.5-4 - +#ans[ Let $C$ be a component of $G$. - If $C$ is a single vertex, then $C$ is also a component of $G^T$. diff --git a/7e1810-algo_hw/hw7.typ b/7e1810-algo_hw/hw7.typ index 76b59ca..4955ab5 100644 --- a/7e1810-algo_hw/hw7.typ +++ b/7e1810-algo_hw/hw7.typ @@ -1,13 +1,13 @@ == HW7 (Week 8) Due: 2024.04.28 -#let ans(it) = { - box(inset: 1em, width: 100%)[ +#let ans(it) = [ + #pad(1em)[ #text(fill: blue)[ #it ] ] -} +] === Question 21.1-1 diff --git a/7e1810-algo_hw/hw8.typ b/7e1810-algo_hw/hw8.typ index 410f496..701dfce 100644 --- a/7e1810-algo_hw/hw8.typ +++ b/7e1810-algo_hw/hw8.typ @@ -1,13 +1,13 @@ == HW8 (Week 9) Due: 2024.05.05 -#let ans(it) = { - box(inset: 1em, width: 100%)[ +#let ans(it) = [ + #pad(1em)[ #text(fill: blue)[ #it ] ] -} +] === Exerciese 1 Proof that Bellman-Ford maximizes $x_1+x_2+dots.c+x_n$ subject to the constraints $x_j - x_i <= w_(i j)$ for all edges $(i,j)$ and $x <= 0$, and also minmizes $max_i {x_i}-min_i {x_i}$. diff --git a/7e1810-algo_hw/hw9.typ b/7e1810-algo_hw/hw9.typ index e1cf43d..b34a6e3 100644 --- a/7e1810-algo_hw/hw9.typ +++ b/7e1810-algo_hw/hw9.typ @@ -1,13 +1,13 @@ == HW9 (Week 11) Due: 2024.05.19 -#let ans(it) = { - box(inset: 1em, width: 100%)[ +#let ans(it) = [ + #pad(1em)[ #text(fill: blue)[ #it ] ] -} +] === Question 32.4-1 Compute the prefix function $pi$ for the pattern `ababbabbabbababbabb`. @@ -28,8 +28,4 @@ Explain why the modified algorithm is correct, and explain in what sense this ch #ans[ If $P[q+1]!=T[i] "and" P[pi[q]+1]=P[q+1]!=T[i]$, there's no need to compare $P[pi[q]+1]$ with $T[i]$, because $P[pi[q]+1]$ is the same as $P[q+1]$, so we can directly compare $P[q+1]$ with $T[i]$. This change improves the efficiency of the algorithm. -] - -#align(center)[ - #image("imgs/sticker_2.jpg", width: 50%) ] \ No newline at end of file diff --git a/7e1810-algo_hw/imgs/sticker_2.jpg b/7e1810-algo_hw/imgs/sticker_2.jpg deleted file mode 100644 index d2a9c7f..0000000 Binary files a/7e1810-algo_hw/imgs/sticker_2.jpg and /dev/null differ diff --git a/7e1810-algo_hw/main.typ b/7e1810-algo_hw/main.typ index d795f71..07ce9b0 100644 --- a/7e1810-algo_hw/main.typ +++ b/7e1810-algo_hw/main.typ @@ -1,3 +1,6 @@ +#import "@preview/cetz:0.2.2": * +#import "@preview/diagraph:0.2.1": * + #set text( font: ("linux libertine", "Source Han Serif SC", "Source Han Serif"), size: 10pt, @@ -24,6 +27,10 @@ #pagebreak(weak: true) +#show math.equation: it => math.display(it) +#show image: it => align(center, it) +#show raw.where(block: true): it => rect(stroke: 0.02em, width: 100%, inset: 1em, it) + #include "hw1.typ" #pagebreak(weak: true) #include "hw2.typ" diff --git a/ea2724-ai_hw/hw1.typ b/ea2724-ai_hw/hw1.typ index 04c82fa..7f2de0c 100644 --- a/ea2724-ai_hw/hw1.typ +++ b/ea2724-ai_hw/hw1.typ @@ -1,33 +1,40 @@ == HW 1 Due: 2024.03.17 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 3.7 3.7 给出下列问题的初始状态、目标测试、后继函数和耗散函数. 选择精确得足以实现的形式化. -- a. 只用四种颜色对平面地图染色, 要求每两个相邻的地区不能染成相同的颜色. -- b. 一间屋子里有一只 3 英尺高的猴子, 屋子的房顶上挂着一串香蕉, 离地面 8 英尺. 屋子里有两个可叠放起来、可移动、可攀登的 3 英尺高的箱子. 猴子很想得到香蕉. -- c. 有一个程序, 当送入一个特定文件的输入记录时会输出“不合法的输入记录”. 已知每个记录的处理独立于其它记录. 要求找出哪个记录不合法. -- d. 有三个水壶, 容量分别为 12 加仑、8 加仑和 3 加仑, 还有一个水龙头. 可以把壶装满或者倒空, 从一个壶倒进另一个壶或者倒在地上. 要求量出刚好 1 加仑水. - -#text(fill: blue)[ - === Solution 3.7 ++ 只用四种颜色对平面地图染色, 要求每两个相邻的地区不能染成相同的颜色. ++ 一间屋子里有一只 3 英尺高的猴子, 屋子的房顶上挂着一串香蕉, 离地面 8 英尺. 屋子里有两个可叠放起来、可移动、可攀登的 3 英尺高的箱子. 猴子很想得到香蕉. ++ 有一个程序, 当送入一个特定文件的输入记录时会输出“不合法的输入记录”. 已知每个记录的处理独立于其它记录. 要求找出哪个记录不合法. ++ 有三个水壶, 容量分别为 12 加仑、8 加仑和 3 加仑, 还有一个水龙头. 可以把壶装满或者倒空, 从一个壶倒进另一个壶或者倒在地上. 要求量出刚好 1 加仑水. - - a: +#ans[ + + - Initial State: 所有区域未染色 - Goal Test: 所有区域都染色 - Successor Function: 选择一个未染色的区域, 为其染上一种颜色 - Cost Function: 涂色的次数 - - b: + + - Initial State: 猴子在屋子的地面, 箱子在屋子的地面, 香蕉距离地面 8 英尺 - Goal Test: 猴子站在箱子上, 可以够到香蕉 - Successor Function: 猴子搬动、放下箱子、爬上箱子、爬下箱子、拿起香蕉 - Cost Function: 猴子总用时 - - c: + + - Initial State: 一个输入记录 - Goal Test: 输入记录合法 - Successor Function: 修改输入记录的某一部分 - Cost Function: 修改的次数 - - d: + + - Initial State: 三个水壶都是空的 - Goal Test: 一个水壶里有 1 加仑水 - Successor Function: 装满水壶、倒空水壶、从一个壶倒进另一个壶 @@ -39,44 +46,35 @@ Due: 2024.03.17 3.9 传教士和野人问题通常描述如下:三个传教士和三个野人在河的一边, 还有一条能载一个人或者两个人的船. 找到一个办法让所有的人都渡到河的另一岸, 要求在任何地方野人数都不能多于传教士的人数 (可以只有野人没有传教士). 这个问题在 AI 领域中很著名, 因为它是第一篇从分析的观点探讨问题形式化的论文的主题(Amarel, 1968) -- a. 精确地形式化该问题, 只描述确保该问题有解所必需的特性. 画出该问题的完全状态空间图. -- b. 用一个合适的搜索算法实现和最优地求解该问题. 检查重复状态是个好主意吗? -- c. 这个问题的状态空间如此简单, 你认为为什么人们求解它却很困难? - -#text(fill: blue)[ - === Solution 3.9 - - ==== a: - - - 状态:$(a,b,c)$, $a$:传教士在此岸的人数, $b$:野人在此岸的人数, $c$:船是否在此岸 (0/1) - - Initial State: $(3,3,1)$ - - Goal Test: $(0,0,0)$ - - Successor Function: - $ - (x,y,1) -> cases((x-1,y,0), (x,y-1,0), (x-1,y-1,0), (x-2,y,0), (x,y-2,0)) - \ - (x,y,0) -> cases((x+1,y,1), (x,y+1,1), (x+1,y+1,1), (x+2,y,1), (x,y+2,1)) - $ - 同时所有$(x,y,c),(x',y',z')$满足$0<=x<=3, 0<=y<=3$, 并且: - $ - (x=0 or x>=y) and (x=3 or x<=y) - $ - - Cost Function: 操作次数 - - ==== b: - - 使用 BFS 对状态进行搜索, 维护一个 $3 times 1$ 的数组记录已经访问过的状态: - - $ - (3,3,1) -> (3,1,0) -> (3,2,1) -> (3,0,0) -> (3,1,1) -> (1,1,0)\ -> (2,2,1) -> (0,2,0) -> (0,3,1) -> (0,1,0) -> ( - 1,1,1 - ) -> (0,0,0) - $ - - 问题中限制很多, 可以不考虑重复状态 (全部枚举即可). 如果问题中 $3 -> 100$, 检查重复状态是个好主意. - - ==== c: - - 虽然每一步的限制都足够多而且空间足够简单, 但图的深度很大, 每一步所需要做的判断过于复杂. ++ 精确地形式化该问题, 只描述确保该问题有解所必需的特性. 画出该问题的完全状态空间图. ++ 用一个合适的搜索算法实现和最优地求解该问题. 检查重复状态是个好主意吗? ++ 这个问题的状态空间如此简单, 你认为为什么人们求解它却很困难? + +#ans[ + + + - 状态:$(a,b,c)$, $a$:传教士在此岸的人数, $b$:野人在此岸的人数, $c$:船是否在此岸 (0/1) + - Initial State: $(3,3,1)$ + - Goal Test: $(0,0,0)$ + - Successor Function: + $ + (x,y,1) -> cases((x-1,y,0), (x,y-1,0), (x-1,y-1,0), (x-2,y,0), (x,y-2,0)) + \ + (x,y,0) -> cases((x+1,y,1), (x,y+1,1), (x+1,y+1,1), (x+2,y,1), (x,y+2,1)) + $ + 同时所有$(x,y,c),(x',y',z')$满足$0<=x<=3, 0<=y<=3$, 并且: + $ + (x=0 or x>=y) and (x=3 or x<=y) + $ + - Cost Function: 操作次数 + + 使用 BFS 对状态进行搜索, 维护一个 $3 times 1$ 的数组记录已经访问过的状态: + + $ + (3,3,1) -> (3,1,0) -> (3,2,1) -> (3,0,0) -> (3,1,1) -> (1,1,0)\ -> (2,2,1) -> (0,2,0) -> (0,3,1) -> (0,1,0) -> ( + 1,1,1 + ) -> (0,0,0) + $ + + 问题中限制很多, 可以不考虑重复状态 (全部枚举即可). 如果问题中 $3 -> 100$, 检查重复状态是个好主意. + + 虽然每一步的限制都足够多而且空间足够简单, 但图的深度很大, 每一步所需要做的判断过于复杂. ] diff --git a/ea2724-ai_hw/hw2.typ b/ea2724-ai_hw/hw2.typ index 9cf9100..7f8c59b 100644 --- a/ea2724-ai_hw/hw2.typ +++ b/ea2724-ai_hw/hw2.typ @@ -2,13 +2,20 @@ == HW 2 Due 2024.03.24 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 4.1 4.1 追踪 $A^*$ 搜索算法用直线距离启发式求解从 Lugoj 到 Bucharest 问题的过程. 按照顺序列出算法扩展的节点和每个节点的 $f, g, h$ 值 -#text(fill: blue)[ - === Solution 3.7 - +#ans[ #let data_41 = ( [Luogoj(244, 0, 244)], ([Timisora(440, 111, 329)]), @@ -81,9 +88,7 @@ Due 2024.03.24 4.2 启发式路径算法是一个最佳有限搜索, 它的目标函数是 $f(n) = (2-omega) g(n) + w h(n)$. 算法中$w$取什么值保证算法是最优的?当$w=0$时, 这个算法是什么搜索?$w=1$呢?$w=2$呢? -#text(fill: blue)[ - === Solution 4.2 - +#ans[ - $w=0 => f(n) = 2g(n)$ 此时算法与 UCS 算法相同, 选择最小的 $g(n)$ - $w=1 => f(n) = g(n) + h(n)$ 此时算法与 $A^*$ 算法相同, 选择最小的 $f(n)$ - $w=2 => f(n) = 2h(n)$ 此时算法与 Greedy 算法相同, 选择最小的 $h(n)$ @@ -100,19 +105,17 @@ Due 2024.03.24 4.6 设计一个启发函数, 使它在八数码游戏中有时会估计过高, 并说明它在什么样的特殊问题下会导致次最优解.(可以借助计算机的帮助) 证明:如果 $h$ 被高估的部分从来不超过 $c$, $A^*$ 算法返回的解的耗散多出的部分也不超过 $c$. -#text(fill: blue)[ - === Solution 4.6 - +#ans[ - *设计一个启发函数, 使它在八数码游戏中有时会估计过高, 并说明它在什么样的特殊问题下会导致次最优解. * - #image("./img/Solution_4.6.jpg", width: 70%) + #image("./imgs/Solution_4.6.jpg", width: 70%) - *证明:如果 $h$ 被高估的部分从来不超过 $c$, $A^*$ 算法返回的解的耗散多出的部分也不超过 $c$.* 考虑 $h(n)<=h^*(n)+c$, 并且令$G^'$为耗散超过$c$的解 ($g(G^') > C^* + c$). 考虑在到达最优解的路径上所有节点$n$: $ - f(n) = g(n) + h(n) <= g(n) + h^*(n) + c = g(G) + h^*(G) + c = C^* + c <= g(G^') + f(n) = g(n) + h(n) <= g(n) + h^*(n) + c = g(G) + h^*(G) + c = C^* + c <= g(G^') $ 在到达最优解之前不会到达 $G^'$, 这样 $A^*$ 算法返回的解的耗散多出的部分也不超过 $c$. @@ -123,9 +126,7 @@ Due 2024.03.24 4.7 证明如果一个启发式是一致的, 它肯定是可采纳的. 构造一个非一致的可采纳启发式. -#text(fill: blue)[ - === Solution 4.7 - +#ans[ - 一致:$h(n) <= c(n, a, n') + h(n')$ - 可采纳:$h(n) <= h^*(n)$ @@ -133,6 +134,6 @@ Due 2024.03.24 构造一个非一致的可采纳启发式: - #image("./img/Solution_4.7.jpg", width: 50%) + #image("./imgs/Solution_4.7.jpg", width: 50%) ] \ No newline at end of file diff --git a/ea2724-ai_hw/hw3.typ b/ea2724-ai_hw/hw3.typ index 6c61ce0..fd8a793 100644 --- a/ea2724-ai_hw/hw3.typ +++ b/ea2724-ai_hw/hw3.typ @@ -1,12 +1,19 @@ == HW3 Due 2024.03.31 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 6.5 6.5 分别用带有前向检验、MRV 和最少约束值启发式的回溯算法手工求解图 6.2 中的密码算术问题. -#text(fill: blue)[ - === Solution 6.5 - +#ans[ 首先考虑 1-相容: #align(center)[ @@ -14,49 +21,33 @@ Due 2024.03.31 stroke: blue, columns: (auto, auto, auto, auto, auto, auto, auto, auto, auto), align: center, - [$C_1$], - [$C_2$], - [$C_3$], - [$F$], - [$T$], - [$U$], - [$W$], - [$R$], - [$O$], - [$0, 1$], - [$0, 1$], - [$0, 1$], - [$1-9$], - [$1-9$], - [$0-9$], - [$0-9$], - [$0-9$], - [$0-9$], + [$C_1$], [$C_2$], [$C_3$], [$F$], [$T$], [$U$], [$W$], [$R$], [$O$], + [$0, 1$], [$0, 1$], [$0, 1$], [$1-9$], [$1-9$], [$0-9$], [$0-9$], [$0-9$], [$0-9$], ) ] 所有约束: $ - 2O &= R + 10 dot C_3 \ - 2W + C_3 &= U + 10 dot C_2 \ - 2T + C_2 &= O + 10 dot C_1 \ - C_1 &= F \ - "ALLDIFF" & {F, T, U, W, R, O} + 2O &= R + 10 dot C_3 \ + 2W + C_3 &= U + 10 dot C_2 \ + 2T + C_2 &= O + 10 dot C_1 \ + C_1 &= F \ + "ALLDIFF" & {F, T, U, W, R, O} $ 按照 $X_i$ 进行整理: $ - C_1&: , \ - C_2&: , \ - C_3&: , \ - F&: \ - T&: \ - U&: \ - W&: \ - R&: \ - O&: , \ + C_1&: , \ + C_2&: , \ + C_3&: , \ + F&: \ + T&: \ + U&: \ + W&: \ + R&: \ + O&: , \ $ #align(center)[ @@ -64,56 +55,11 @@ Due 2024.03.31 stroke: blue, columns: (auto, auto, auto, auto, auto, auto, auto, auto, auto, auto), align: center, - [], - [$C_1$], - [$C_2$], - [$C_3$], - [$F$], - [$T$], - [$U$], - [$W$], - [$R$], - [$O$], - [$$], - [$1$], - [$0, 1$], - [$0, 1$], - [$1$], - [$1-9$], - [$0-9$], - [$0-9$], - [$0-9$], - [$0-9$], - [$ and "ALLDIFF"$], - [$1$], - [$0, 1$], - [$0, 1$], - [$1$], - [$1-9$], - [$0-9$], - [$0-9$], - [$0-9$], - [$1-9$], - [$"ALLDIFF"$], - [$1$], - [$0, 1$], - [$0, 1$], - [$1$], - [$2-9$], - [$0, 2-9$], - [$0, 2-9$], - [$0, 2-9$], - [$2-9$], - [$$], - [$1$], - [$0, 1$], - [$0, 1$], - [$1$], - [$2-9$], - [$0, 2-9$], - [$0, 2-9$], - [$0, 2, 4, 6, 8$], - [$2-9$], + [], [$C_1$], [$C_2$], [$C_3$], [$F$], [$T$], [$U$], [$W$], [$R$], [$O$], + [$$], [$1$], [$0, 1$], [$0, 1$], [$1$], [$1-9$], [$0-9$], [$0-9$], [$0-9$], [$0-9$], + [$ and "ALLDIFF"$], [$1$], [$0, 1$], [$0, 1$], [$1$], [$1-9$], [$0-9$], [$0-9$], [$0-9$], [$1-9$], + [$"ALLDIFF"$], [$1$], [$0, 1$], [$0, 1$], [$1$], [$2-9$], [$0, 2-9$], [$0, 2-9$], [$0, 2-9$], [$2-9$], + [$$], [$1$], [$0, 1$], [$0, 1$], [$1$], [$2-9$], [$0, 2-9$], [$0, 2-9$], [$0, 2, 4, 6, 8$], [$2-9$], [$$], [$1$], [$0, 1$], @@ -124,16 +70,8 @@ Due 2024.03.31 [$0, 2-9$], [$0, 2, 4, 6, 8$], [$2-9$], - [$"SET:" C_2 = 0$], - [$1$], - [$0$], - [$0, 1$], - [$1$], - [$5-9$], - [$0, 2-9$], - [$0, 2-9$], - [$0, 2, 4, 6, 8$], - [$2-9$], + + [$"SET:" C_2 = 0$], [$1$], [$0$], [$0, 1$], [$1$], [$5-9$], [$0, 2-9$], [$0, 2-9$], [$0, 2, 4, 6, 8$], [$2-9$], [$$], [$1$], [$0$], @@ -144,6 +82,7 @@ Due 2024.03.31 [$0, 2, 3, 4$], [$0, 2, 4, 6, 8$], [$2-9$], + [$$], [$1$], [$0$], @@ -154,6 +93,7 @@ Due 2024.03.31 [$0, 2, 3, 4$], [$0, 2, 4, 6, 8$], [$2, 4, 6, 8$], + [$"SET:" C_3 = 0$], [$1$], [$0$], @@ -164,26 +104,9 @@ Due 2024.03.31 [$0, 2, 3, 4$], [$0, 2, 4, 6, 8$], [$2, 4, 6, 8$], - [$$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5-9$], - [$0, 2-9$], - [$0, 2, 3, 4$], - [$0, 4, 8$], - [$2, 4$], - [$$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$0, 2-9$], - [$0, 2, 3, 4$], - [$0, 4, 8$], - [$2, 4$], + + [$$], [$1$], [$0$], [$0$], [$1$], [$5-9$], [$0, 2-9$], [$0, 2, 3, 4$], [$0, 4, 8$], [$2, 4$], + [$$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$0, 2-9$], [$0, 2, 3, 4$], [$0, 4, 8$], [$2, 4$], [$$], [$1$], [$0$], @@ -194,75 +117,22 @@ Due 2024.03.31 [$0, 2, 3, 4$], [$0, 4, 8$], [$2, 4$], - [$"SET:" O=4$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$0, 4, 6, 8$], - [$0, 2, 3, 4$], - [$0, 4, 8$], - [$4$], - [$"ALLDIFF"$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$0, 6, 8$], - [$0, 2, 3$], - [$0, 8$], - [$4$], - [$$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$0, 6, 8$], - [$0, 2, 3$], - [$8$], - [$4$], - [$"ALLDIFF"$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$0, 6$], - [$0, 2, 3$], - [$8$], - [$4$], - [$ and "ALLDIFF"$], - [$1$], - [$0$], - [$0$], - [$1$], - [$5, 6, 7$], - [$6$], - [$3$], - [$8$], - [$4$], - [$$], - [$1$], - [$0$], - [$0$], - [$1$], - [$7$], - [$6$], - [$3$], - [$8$], - [$4$], + + [$"SET:" O=4$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$0, 4, 6, 8$], [$0, 2, 3, 4$], [$0, 4, 8$], [$4$], + [$"ALLDIFF"$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$0, 6, 8$], [$0, 2, 3$], [$0, 8$], [$4$], + [$$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$0, 6, 8$], [$0, 2, 3$], [$8$], [$4$], + [$"ALLDIFF"$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$0, 6$], [$0, 2, 3$], [$8$], [$4$], + [$ and "ALLDIFF"$], [$1$], [$0$], [$0$], [$1$], [$5, 6, 7$], [$6$], [$3$], [$8$], [$4$], + [$$], [$1$], [$0$], [$0$], [$1$], [$7$], [$6$], [$3$], [$8$], [$4$], ) ] Solution: $ - &quad &quad 7 &quad 3 &quad 4 \ - &quad + &quad 7 &quad 3 &quad 4 \ - = &quad 1 &quad 4 &quad 6 &quad 8 + &quad &quad 7 &quad 3 &quad 4 \ + &quad + &quad 7 &quad 3 &quad 4 \ + = &quad 1 &quad 4 &quad 6 &quad 8 $ ] @@ -270,93 +140,21 @@ Due 2024.03.31 6.11 用 AC-3 算法说明弧相容对图 6.1 中问题能够检测出部分赋值 $"WA"="GREEN", "V" = "RED"$, 的不相容. -#text(fill: blue)[ - === Solution 6.11 - +#ans[ #table( columns: (auto, auto, auto, auto, auto, auto, auto, auto), stroke: blue, align: center, - [], - [WA], - [NT], - [Q], - [NSW], - [V], - [SA], - [T], - [], - [G], - [R G B], - [R G B], - [R G B], - [R], - [R G B], - [R G B], - [WA, SA], - [G], - [R G B], - [R G B], - [R G B], - [R], - [R B], - [R G B], - [WA, NT], - [G], - [R B], - [R G B], - [R G B], - [R], - [R B], - [R G B], - [V, SA], - [G], - [R B], - [R G B], - [R G B], - [R], - [B], - [R G B], - [V, NSW], - [G], - [R B], - [R G B], - [G B], - [R], - [B], - [R G B], - [SA, NSW], - [G], - [R B], - [R G B], - [G], - [R], - [B], - [R G B], - [SA, Q], - [G], - [R B], - [R G], - [G], - [R], - [B], - [R G B], - [SA, NT], - [G], - [R], - [R G], - [G], - [R], - [B], - [R G B], - [NT, Q], - [G], - [R], - [G], - [G], - [R], - [B], - [R G B], + [], [WA], [NT], [Q], [NSW], [V], [SA], [T], + [], [G], [R G B], [R G B], [R G B], [R], [R G B], [R G B], + [WA, SA], [G], [R G B], [R G B], [R G B], [R], [R B], [R G B], + [WA, NT], [G], [R B], [R G B], [R G B], [R], [R B], [R G B], + [V, SA], [G], [R B], [R G B], [R G B], [R], [B], [R G B], + [V, NSW], [G], [R B], [R G B], [G B], [R], [B], [R G B], + [SA, NSW], [G], [R B], [R G B], [G], [R], [B], [R G B], + [SA, Q], [G], [R B], [R G], [G], [R], [B], [R G B], + [SA, NT], [G], [R], [R G], [G], [R], [B], [R G B], + [NT, Q], [G], [R], [G], [G], [R], [B], [R G B], ) 注意到此时 $Q="NSB"="GREEN"$, 破坏约束, AC-3 算法可以检测出这种不相容. @@ -367,9 +165,7 @@ Due 2024.03.31 6.12 用 AC-3 算法求解树结构 CSP 在最坏情况下的复杂度是多少? -#text(fill: blue)[ - === Solution 6.12 - +#ans[ 树结构中每个弧最多会被检查一次, 因此 AC-3 最坏情况下复杂度为 $O(E D)$, 其中 $E$ 为弧的数量, $D$ 为定义域的大小. // 对应的算法考虑如下: diff --git a/ea2724-ai_hw/hw4.typ b/ea2724-ai_hw/hw4.typ index bc6a400..977b2e0 100644 --- a/ea2724-ai_hw/hw4.typ +++ b/ea2724-ai_hw/hw4.typ @@ -1,41 +1,47 @@ == HW4 Due 2024.04.09 -=== Question 5.9 - -5.9 本题以井字棋(圈与十字游戏)为例练习博弈中的基本概念. 定义 $X_n$ 为恰好有 $n$ 个 $X$ 而没有 $O$ 的行、列或者对角线的数目. 同样 $O_n$ 为正好有 $n$ 个 $O$ 的行、列或者对角线的数目. 效用函数给 $X_3=1$ 的棋局 $+1$, 给 $O_3 = 1$ 的棋局 $-1$. 所有其他终止状态效用值为 $0$. 对于非终止状态, 使用线性的评估函数定义为 $"Eval"(s) = 3X_2(s) + X_1(s) - (3 O_2(s) + O_1(s))$ . - -a. 估算可能的井字棋局数. - -b. 考虑对称性, 给出从空棋盘开始的深度为2的完整博弈树(即, 在棋盘上一个 $X$ 一个 $O$ 的棋局). -c. 标出深度为$2$的棋局的评估函数值. +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] -d. 使用极小极大算法标出深度为$1$和$0$的棋局的倒推值,并根据这些值选出最佳的起始行棋. +=== Question 5.9 -e. 假设结点按对 $alpha-beta$ 剪枝的最优顺序生成, 圈出使用 $alpha-beta$ 剪枝将被剪掉的深度为2的结点. +5.9 本题以井字棋(圈与十字游戏)为例练习博弈中的基本概念. 定义 $X_n$ 为恰好有 $n$ 个 $X$ 而没有 $O$ 的行、列或者对角线的数目. 同样 $O_n$ 为正好有 $n$ 个 $O$ 的行、列或者对角线的数目. 效用函数给 $X_3=1$ 的棋局 $+1$, 给 $O_3 = 1$ 的棋局 $-1$. 所有其他终止状态效用值为 $0$. 对于非终止状态, 使用线性的评估函数定义为 $"Eval"(s) = 3X_2(s) + X_1(s) - (3 O_2(s) + O_1(s))$ . -#text(fill: blue)[ - === Solution 5.9 ++ 估算可能的井字棋局数. ++ 考虑对称性, 给出从空棋盘开始的深度为2的完整博弈树(即, 在棋盘上一个 $X$ 一个 $O$ 的棋局). ++ 标出深度为$2$的棋局的评估函数值. ++ 使用极小极大算法标出深度为$1$和$0$的棋局的倒推值,并根据这些值选出最佳的起始行棋. ++ 假设结点按对 $alpha-beta$ 剪枝的最优顺序生成, 圈出使用 $alpha-beta$ 剪枝将被剪掉的深度为2的结点. - a. 考虑到最小深度 $5$, 最大深度 $9$, 每个位置有 $3$ 种可能, 因此可能的井字棋局数为 $ sum_(i=5)^9 i! approx 4.1 times 10^5 $ +#ans[ + + + + 考虑到最小深度 $5$, 最大深度 $9$, 每个位置有 $3$ 种可能, 因此可能的井字棋局数为 $ sum_(i=5)^9 i! approx 4.1 times 10^5 $ - 上述估算给出了实际局数的一个上界, 显然部分棋局在中途就会因为一方胜利而结束. 在此数量级上, 我们可以通过简单的程序给出实际上的井字棋局数: + 上述估算给出了实际局数的一个上界, 显然部分棋局在中途就会因为一方胜利而结束. 在此数量级上, 我们可以通过简单的程序给出实际上的井字棋局数: - 完整的代码链接放在了 #link("https://gist.github.com/tiankaima/5a58fcf5dd3b53b29ff75b0347ba889a")[这里], 也放在本次作业的末尾, 运行后得到: + 完整的代码链接放在了 #link("https://github.com/tiankaima/USTC_AI_24/blob/main/utils/Q5_9.cpp")[这里], 运行后得到: - ```text - Total possible games: 255168 - Total win for player 1: 131184 - Total win for player 2: 77904 - Total draw: 46080 - ``` + ```text + Total possible games: 255168 + Total win for player 1: 131184 + Total win for player 2: 77904 + Total draw: 46080 + ``` - #rect(width: 100%, height: 0.2pt, fill: blue) + #rect(width: 100%, height: 0.2pt, fill: blue) - b, c, d, e: 如图: + + + + + + 如图: #align(center)[ - #image("./img/Solution_5.9.jpg", width: 60%, fit: "contain") + #image("./imgs/Solution_5.9.jpg", width: 60%, fit: "contain") ] 其中 d 的最佳行棋为 顶点 / 中心处; 剪枝、评估函数值等已标注在图中. @@ -45,226 +51,110 @@ e. 假设结点按对 $alpha-beta$ 剪枝的最优顺序生成, 圈出使用 $al 5.8 考虑图 5.17 中描述的两人游戏. -a. 根据如下约定画出完整博弈树: - -- 每个状态用 $(s_A, s_B)$表示, 其中 $s_A$ 和 $s_B$ 表示棋子的位置. -- 每个终止状态用方框画出, 用圆圈写出它的博弈值. -- 把循环状态(在到根结点的路径上已经出现过的状态)画上双层方框. 由于不清楚他们的值, 在圆圈里标记一个“? ”. - -b. 给出每个结点倒推的极小极大值(也标记在圆圈里). 解释怎样处理“?”值和为什么这么处理. - -c. 解释标准的极小极大算法为什么在这棵博弈树中会失败, 简要说明你将如何修正它, 在(b)的图上画出你的答案. 你修正后的算法对于所有包含循环的游戏都能给出最优决策吗? - -d. 这个4-方格游戏可以推广到$n$个方格, 其中. 证明如果 $n$ 是偶数 $A$ 一定能赢, 而 $n$ 是奇数则 $A$ 一定会输. - -#text(fill: blue)[ - === Solution 5.8 - - a, b: - #align(center)[ - #image("./img/Solution_5.8_1.jpg", width: 50%, fit: "contain") - ] - - b, c: - 对上述循环状态, 可以先赋 $0$, 计算出重复节点真实值, 再回溯更新 ($alpha-beta$ 向前剪枝). - 考虑一组循环的更新路径 $(P_1, dots.c, P_(2k), P_1)$, 考虑其中的一次更新 $P_i$, 即 $P_i^' = "MAX"("MIN"(dots.c "MIN"(P_i, dots.c )))$, 其中 $P_i = "MAX"("MIN"(dots.c "MIN"(0, dots.c )))$, 这样的更新是至多平凡的, 意味着从 $(P_i, P_(i-1), P_(i-2))$ 的更新至多为 $P_i$ 本身, 并且从一个节点开始停止. - // 通过这样的做法, - 对于 $"MIN"$ 节点的操作类似, 在一般性包含循环的游戏中都能给出最优决策. - // *这样的迭代总能在有限时间完成: * 反证, 如果存在无限时间的迭代更新, 必然存在一组循环的更新路径 $(P_1, dots.c, P_2k, P_1)$, 考虑其中的一次更新 $P_i$, 即 $P_i^' = "MAX"("MIN"(dots.c "MIN"(P_i, dots.c )))$, 其中 $P_i = "MAX"("MIN"(dots.c "MIN"(0, dots.c )))$, 这样的更新是至多平凡的, 意味着从 $(P_i, P_(i-1), P_(i-2))$ 的前向更新至多更新为 $P_i$ 本身 ++ 根据如下约定画出完整博弈树: + - 每个状态用 $(s_A, s_B)$表示, 其中 $s_A$ 和 $s_B$ 表示棋子的位置. + - 每个终止状态用方框画出, 用圆圈写出它的博弈值. + - 把循环状态(在到根结点的路径上已经出现过的状态)画上双层方框. 由于不清楚他们的值, 在圆圈里标记一个“? ”. ++ 给出每个结点倒推的极小极大值 (也标记在圆圈里). 解释怎样处理“?”值和为什么这么处理. ++ 解释标准的极小极大算法为什么在这棵博弈树中会失败, 简要说明你将如何修正它, 在 (b) 的图上画出你的答案. 你修正后的算法对于所有包含循环的游戏都能给出最优决策吗? ++ 这个4-方格游戏可以推广到$n$个方格, 其中. 证明如果 $n$ 是偶数 $A$ 一定能赢, 而 $n$ 是奇数则 $A$ 一定会输. + +#ans[ + + + + + #align(center)[ + #image("./imgs/Solution_5.8_1.jpg", width: 50%, fit: "contain") + ] + + 对上述循环状态, 可以先赋 $0$, 计算出重复节点真实值, 再回溯更新 ($alpha-beta$ 向前剪枝). + 考虑一组循环的更新路径 $(P_1, dots.c, P_(2k), P_1)$, 考虑其中的一次更新 $P_i$, 即 $P_i^' = "MAX"("MIN"(dots.c "MIN"(P_i, dots.c )))$, 其中 $P_i = "MAX"("MIN"(dots.c "MIN"(0, dots.c )))$, 这样的更新是至多平凡的, 意味着从 $(P_i, P_(i-1), P_(i-2))$ 的更新至多为 $P_i$ 本身, 并且从一个节点开始停止. + 对于 $"MIN"$ 节点的操作类似, 在一般性包含循环的游戏中都能给出最优决策. - #box[ - d: - 在上述博弈图中, 我们容易发现 + + 在上述博弈图中, 我们容易发现 - $n=3$ 时, B 总有必胜策略 (考虑从 $=>^A (1,3)$ 开始的子图, 并去掉 $=>^B (3,4)$ 的分枝) - $n=4$ 时, A 总有必胜策略 - $n=5$ 时, B的必胜策略: $(1,5) =>^A (2,5) =>^B (2,4) =>^A {(1,4), (3,4)}$, 前者可以视为颠倒的 $n=4$ 的情况(左右颠倒、选手颠倒), 后者的必胜策略: $ (3,4) =>^B (3,2) =>^A (x, 2) =>^B (x, 1) $ 即可获胜. - #rect(stroke: blue.opacify(50%))[ + #rect(stroke: blue.opacify(50%), inset: 1em)[ 考虑到对 $n<=2$ 时游戏无意义, 奇数的部分与偶数的部分讨论类似, 我们下面仅讨论 $n=2i, 2<=i<=k$ 时 A 有必胜策略, $n=2k+2$ 时 A 的必胜策略: $ - (1, 2k+2) =>^A (2, 2k+2) =>^B (2, 2k+1) =>^A (3, 2k+1) &=>^B (3, 2k+2) =>^A dots.c quad & (2k-2) \ - & =>^B (3, 2k) =>^A dots.c quad & (2k - 4) + (1, 2k+2) =>^A (2, 2k+2) =>^B (2, 2k+1) =>^A (3, 2k+1) &=>^B (3, 2k+2) =>^A dots.c quad & (2k-2) \ + & =>^B (3, 2k) =>^A dots.c quad & (2k - 4) $ 只需要将 $n = 2k - 2$ 的策略应用到 $(3, 2k+2)$, $n = 2k - 4$ 的策略应用到 $(3, 2k)$ 即可(始终不向左走, 并且在 $B$ 第一次到达 $3$ 之前到达$2k+2$, 在此之前 B 不可能到达 $1$) ] - ] ] === Question 5.13 请给出 $alpha - beta$ 剪枝正确性的形式化证明. 要做到这一点需要考虑图 5.18, 问题为是否要剪掉节点 $n_j$, 它是一个 MAX 节点, 是 $n_1$ 的一个后代. 基本思路是当且仅当 $n_1$ 的极小极大值可以被证明独立于 $n_j$ 的值时, 会发生剪枝. -a. $n_1$ 的值是所有后代节点的最小值 $n_1 = min(n_2, n_(2,1), dots.c , n_(2 b_2))$, 请为 $n_2$ 找到类似的表达式, 以便得到用$n_j$ 表示的 $n_1$ 的表达式. - -#text(fill: blue)[ - $ - &n_2 = max(n_(2,1), n_(2,2), dots.c , n_(2 b_2)) \ - &n_1 = min(max(min( ... quad max(n_j, dots.c), dots.c), dots.c)) - $ -] - -b. #strike[深度为 $i$ 的结点 $n_i$ 的极小极大值已知, $l_i$ 是在结点 $n_i$ 左侧结点的极小值(或者极大值). 同样, $r_i$ 是 $n_i$ 在右侧的未探索过的结点的极小值(或者极大值). 用 $l_i$ 和 $r_i$ 的值重写 $n_1$ 的表达式. ] - -*这个翻译完全不准确, 正确的翻译是:* - -$l_i$ 是在结点 $n_i$ 左侧结点的极小值(或者极大值), 其大小已知. 同样, $r_i$ 是 $n_i$ 在右侧的未探索过的结点的极小值(或者极大值). 用 $l_i$ 和 $r_i$ 的值重写 $n_1$ 的表达式. - -#text(fill: blue)[ - $ - &n_1 = min(l_2, n_2, r_2) \ - &n_2 = max(l_3, n_3, r_3) \ - &dots \ - &n_1 = min(l_2, max(l_3, dots.c , n_j, dots.c), r_1) - $ -] - -c. 现在重新形式化表达式, 来说明为了向 $n_1$ 施加影响, 不能超出由 $l_i$ 值得到的某特定界限. - -#text(fill: blue)[ - // 根据 $alpha-beta$ 剪枝的递归性质, $forall i l_j$, 那么 $n_(j-1) tilde (l_j, r_j)$. 不存在从 $n_j$ 到 $n_(j-1)$ 的影响. - // - 如果 $n_j < l_(j-1)$, 那么 $min(l_j, n_j, r_j) < n_j < l_(j-1) => n_(j-2) tilde (l_(j-1), r_(j-1))$, 不存在从 $n_(j-1)$ 到 $n_(j-2)$ 的影响. - // 对以上讨论进行归纳, 容易得到 $n_j > l_(2k + 1), forall k$ - // 考虑所有 MAX 节点 $2k-1$ 的 子节点, $l_(2k)$ 是已经探索过的最大值. 如果 $n_j < l_(2k)$, 在如下的操作时, $n_j$ 的值会被忽略: - // $ - // n_(2k-1) = max(l_(2k), n_(2k), r_(2k)) > l_(2k) > n_j - // $ - - 考虑对定义做如下改进, 我们自下而上定义 $n_(2k+1)^' = max(l_(2k+2), n_(2k+2))$ 以及 $n_(2k)^' = min(l_(2k), n_(2k+1))$: - - $ - &n_1^' = min(l_2, n_2) \ - &n_2^' = max(l_3, n_3) \ - &dots \ - &n_(j-1)^' = min(l_j, n_j) \ - $ - - 这样 $n_j$ 对 $n_1$ 施加影响 $<=>$ $n_1^' = n_2^' = dots.c = n_j$ ++ $n_1$ 的值是所有后代节点的最小值 $n_1 = min(n_2, n_(2,1), dots.c , n_(2 b_2))$, 请为 $n_2$ 找到类似的表达式, 以便得到用$n_j$ 表示的 $n_1$ 的表达式. + #ans[ + $ + &n_2 = max(n_(2,1), n_(2,2), dots.c , n_(2 b_2)) \ + &n_1 = min(max(min( ... quad max(n_j, dots.c), dots.c), dots.c)) + $ + ] ++ #strike[深度为 $i$ 的结点 $n_i$ 的极小极大值已知, $l_i$ 是在结点 $n_i$ 左侧结点的极小值 (或者极大值). 同样, $r_i$ 是 $n_i$ 在右侧的未探索过的结点的极小值(或者极大值). 用 $l_i$ 和 $r_i$ 的值重写 $n_1$ 的表达式. ] + + *这个翻译完全不准确, 正确的翻译是:* + $l_i$ 是在结点 $n_i$ 左侧结点的极小值 (或者极大值), 其大小已知. 同样, $r_i$ 是 $n_i$ 在右侧的未探索过的结点的极小值(或者极大值). 用 $l_i$ 和 $r_i$ 的值重写 $n_1$ 的表达式. + + #ans[ + $ + &n_1 = min(l_2, n_2, r_2) \ + &n_2 = max(l_3, n_3, r_3) \ + &dots \ + &n_1 = min(l_2, max(l_3, dots.c , n_j, dots.c), r_1) + $ + ] ++ 现在重新形式化表达式, 来说明为了向 $n_1$ 施加影响, 不能超出由 $l_i$ 值得到的某特定界限. + #ans[ + // 根据 $alpha-beta$ 剪枝的递归性质, $forall i l_j$, 那么 $n_(j-1) tilde (l_j, r_j)$. 不存在从 $n_j$ 到 $n_(j-1)$ 的影响. + // - 如果 $n_j < l_(j-1)$, 那么 $min(l_j, n_j, r_j) < n_j < l_(j-1) => n_(j-2) tilde (l_(j-1), r_(j-1))$, 不存在从 $n_(j-1)$ 到 $n_(j-2)$ 的影响. + // 对以上讨论进行归纳, 容易得到 $n_j > l_(2k + 1), forall k$ + // 考虑所有 MAX 节点 $2k-1$ 的 子节点, $l_(2k)$ 是已经探索过的最大值. 如果 $n_j < l_(2k)$, 在如下的操作时, $n_j$ 的值会被忽略: + // $ + // n_(2k-1) = max(l_(2k), n_(2k), r_(2k)) > l_(2k) > n_j + // $ - 因此只需要满足: $forall i = 2k$, $n_i^' <=l_i$, $forall i = 2k+1$, $n_i^' >= l_i$, + 考虑对定义做如下改进, 我们自下而上定义 $n_(2k+1)^' = max(l_(2k+2), n_(2k+2))$ 以及 $n_(2k)^' = min(l_(2k), n_(2k+1))$: - $ - n_j = n_i^' <= l_i, &forall i = 2k + 1 &quad => quad n_j &<= min(l_3, l_5, dots.c, l_(j-1)) &= beta\ - n_j = n_i^' >= l_i, &forall i = 2k &quad => quad n_j &>= max(l_2, l_4, dots.c, l_j) &= alpha - $ + $ + &n_1^' = min(l_2, n_2) \ + &n_2^' = max(l_3, n_3) \ + &dots \ + &n_(j-1)^' = min(l_j, n_j) \ + $ - 对应到 $n_j$ 作为 MAX 节点: + 这样 $n_j$ 对 $n_1$ 施加影响 $<=>$ $n_1^' = n_2^' = dots.c = n_j$ - - $max(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) <= beta$, 因此 只需要在遍历子节点时, 保证 $n_(j, b_i) <= beta$ + 因此只需要满足: $forall i = 2k$, $n_i^' <=l_i$, $forall i = 2k+1$, $n_i^' >= l_i$, - - $max(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) >= alpha$, 可在遍历后由父节点 (MIN) 判断 + $ + n_j = n_i^' <= l_i, &forall i = 2k + 1 &quad => quad n_j &<= min(l_3, l_5, dots.c, l_(j-1)) &= beta\ + n_j = n_i^' >= l_i, &forall i = 2k &quad => quad n_j &>= max(l_2, l_4, dots.c, l_j) &= alpha + $ - 不满足上述要求的节点可以被剪掉. -] + 对应到 $n_j$ 作为 MAX 节点: -d. 假设 $n_j$ 是 MIN 节点的情况, 请重复上面的过程. + - $max(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) <= beta$, 因此 只需要在遍历子节点时, 保证 $n_(j, b_i) <= beta$ -#text(fill: blue)[ - 对应到 $n_j$ 作为 MIN 节点: + - $max(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) >= alpha$, 可在遍历后由父节点 (MIN) 判断 - - $min(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) <= beta$, 可在遍历后由父节点 (MAX) 判断 + 不满足上述要求的节点可以被剪掉. + ] ++ 假设 $n_j$ 是 MIN 节点的情况, 请重复上面的过程. + #ans[ + 对应到 $n_j$ 作为 MIN 节点: - - $min(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) >= alpha$, 因此 只需要在遍历子节点时, 保证 $n_(j, b_i) >= alpha$ + - $min(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) <= beta$, 可在遍历后由父节点 (MAX) 判断 - 上述过程实际上给出了 $alpha-beta$ 剪枝的一个构造, 保证了形式化证明的正确性. -] + - $min(n_(j+1, 1), n_(j+1, 2), dots.c n_(j+1, b_(j+1))) >= alpha$, 因此 只需要在遍历子节点时, 保证 $n_(j, b_i) >= alpha$ -#pagebreak() - -=== Appendix -==== Question 5.9 Code - -```cpp -#include "iostream" -#include "vector" - -typedef struct { - unsigned char data[9]; -} TicTacToeBoard; - -std::vector next_moves(const TicTacToeBoard &board, int player) { - std::vector moves; - for (int i = 0; i < 9; i++) { - if (board.data[i] == 0) { - TicTacToeBoard new_board = board; - new_board.data[i] = player; - moves.push_back(new_board); - } - } - return moves; -} - -unsigned char is_game_finished(const TicTacToeBoard &board) { - // Check rows - for (int i = 0; i < 3; i++) { - if (board.data[i * 3] != 0 && board.data[i * 3] == board.data[i * 3 + 1] && - board.data[i * 3] == board.data[i * 3 + 2]) { - return board.data[i * 3]; - } - } - // Check columns - for (int i = 0; i < 3; i++) { - if (board.data[i] != 0 && board.data[i] == board.data[i + 3] && board.data[i] == board.data[i + 6]) { - return board.data[i]; - } - } - // Check diagonals - if (board.data[0] != 0 && board.data[0] == board.data[4] && board.data[0] == board.data[8]) { - return board.data[0]; - } - if (board.data[2] != 0 && board.data[2] == board.data[4] && board.data[2] == board.data[6]) { - return board.data[2]; - } - - // if the board is full - bool flag = true; - for (unsigned char i: board.data) { - if (i == 0) { - flag = false; - break; - } - } - if (flag) return 0; - - return 3; -} - -int total_possible_games = 0; -int total_win_for_player1 = 0; -int total_win_for_player2 = 0; -int total_draw = 0; - -void play_game(TicTacToeBoard board, int player) { // NOLINT(*-no-recursion) - unsigned char result = is_game_finished(board); - if (result != 3) { - total_possible_games++; - if (result == 1) { - total_win_for_player1++; - } else if (result == 2) { - total_win_for_player2++; - } else { - total_draw++; - } - return; - } - - std::vector moves = next_moves(board, player); - for (TicTacToeBoard &move: moves) { - play_game(move, 3 - player); - } -} - -int main() { - TicTacToeBoard initial_board = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - - play_game(initial_board, 1); - - std::cout << "Total possible games: " << total_possible_games << std::endl; - std::cout << "Total win for player 1: " << total_win_for_player1 << std::endl; - std::cout << "Total win for player 2: " << total_win_for_player2 << std::endl; - std::cout << "Total draw: " << total_draw << std::endl; -} -``` \ No newline at end of file + 上述过程实际上给出了 $alpha-beta$ 剪枝的一个构造, 保证了形式化证明的正确性. + ] \ No newline at end of file diff --git a/ea2724-ai_hw/hw5.typ b/ea2724-ai_hw/hw5.typ index 175aa0a..4fad571 100644 --- a/ea2724-ai_hw/hw5.typ +++ b/ea2724-ai_hw/hw5.typ @@ -1,35 +1,44 @@ == HW5 Due 2024.04.18 + +#let ans(it) = [ + #pad(1em)[ + #text(fill: blue)[ + #it + ] + ] +] + === Question 7.13 7.13 本题考查子句盒蕴含语句之间的关系. a. 证明子句 $(not P_1 or dots.c or not P_m or Q)$ 逻辑等价于蕴含语句 $(P_1 and dots.c and P_m) => Q$. -#text(fill: blue)[ +#ans[ $ - &(not P_1 or dots.c or not P_m or Q) \ - eq.triple & ((not P_1 or dots.c or not P_m) or Q) \ - eq.triple & (not (P_1 and dots.c and P_m) or Q) space.quad & "De Morgan" \ - eq.triple & ((P_1 and dots.c and P_m) => Q) space.quad & "implication elimination" + &(not P_1 or dots.c or not P_m or Q) \ + eq.triple & ((not P_1 or dots.c or not P_m) or Q) \ + eq.triple & (not (P_1 and dots.c and P_m) or Q) space.quad & "De Morgan" \ + eq.triple & ((P_1 and dots.c and P_m) => Q) space.quad & "implication elimination" $ ] b. 证明每个子句 (不管正文字的数量) 都可以写成 $(P_1 and dots.c and P_m) => (Q_q or dot.c or Q_n)$ 的形式, 其中 $p_i$ 和 $Q_i$ 都是命题词. 由这类语句构成的知识库表示为 *蕴含范式* 或称 *Kowalski范式*. -#text(fill: blue)[ +#ans[ 将语句表达成 $(not P_1 or dots.c or not P_m or Q_1 or dots.c Q_n)$ 的形式, 则有: $ - & (not P_1 or dots.c or not P_m or Q_1 or dots.c Q_n) \ - eq.triple & (not P_1 or dots.c or not P_m or Q) \ - eq.triple & (P_1 and dots.c and P_m) => (Q_1 or dots.c or Q_n) + & (not P_1 or dots.c or not P_m or Q_1 or dots.c Q_n) \ + eq.triple & (not P_1 or dots.c or not P_m or Q) \ + eq.triple & (P_1 and dots.c and P_m) => (Q_1 or dots.c or Q_n) $ ] c. 写出蕴含范式语句的完整归结规则. -#text(fill: blue)[ +#ans[ $ - p_q and dots.c p_j and dots.c p_(n_1) => r_1 or dots.c or r_(n_2) \ - s_1 and dots.c s_(n_3) => q_1 or dots.c or q_k or dots.c or q_(n_4) \ - overline("SUBST"(theta, (p_1 or dots.c p_(j-1) or p_(j+1) or p_1 or p_(n_1) or s_1 or dots.c or s_(n_3) => r_1 or dots.c or r_(n_2) or q_1 or dots.c or q_k or dots.c or q_(n_4)))) + p_q and dots.c p_j and dots.c p_(n_1) => r_1 or dots.c or r_(n_2) \ + s_1 and dots.c s_(n_3) => q_1 or dots.c or q_k or dots.c or q_(n_4) \ + overline("SUBST"(theta, (p_1 or dots.c p_(j-1) or p_(j+1) or p_1 or p_(n_1) or s_1 or dots.c or s_(n_3) => r_1 or dots.c or r_(n_2) or q_1 or dots.c or q_k or dots.c or q_(n_4)))) $ ] @@ -37,7 +46,7 @@ c. 写出蕴含范式语句的完整归结规则. 证明. 证明前向链接算法的完备性. -#text(fill: blue)[ +#ans[ 证明前向链接算法的完备性, 即证明 FC 可以推出每个被 KB 蕴含的原子语句: - 考查 inferred 表的最终状态(FC 到达不动点之后, 不在出现新的推理), 将这个表推理出的所有符号设为 true, 其他符号设为 false, 将这个表视为一个逻辑模型 m. - 注意到原始 KB 的每个限定子句在这个模型下都为真 diff --git a/ea2724-ai_hw/hw6.typ b/ea2724-ai_hw/hw6.typ index e1a5224..0390337 100644 --- a/ea2724-ai_hw/hw6.typ +++ b/ea2724-ai_hw/hw6.typ @@ -1,21 +1,21 @@ +#import "@preview/cetz:0.2.2": * == HW6 Due 2024.04.28 -#import "@preview/cetz:0.2.2": canvas, draw, tree -#let ans(it) = { - box(inset: 1em, width: 100%)[ +#let ans(it) = [ + #pad(1em)[ #text(fill: blue)[ #it ] ] -} +] === Question 8.13 解释下面给出的 Wumpus 世界中相邻方格的定义存在什么问题: $ -forall x,y "Adjacent"([x,y], [x+1,y]) and "Adjacent"([x,y], [x,y+1]) + forall x,y "Adjacent"([x,y], [x+1,y]) and "Adjacent"([x,y], [x,y+1]) $ #ans[ @@ -26,240 +26,211 @@ $ 用一个相容的词汇表(需要你自己定义)在一阶逻辑中表示下列语句: -- a. 某些学生在 2001 年春季学期上法语课. - -- b. 上法语课的每个学生都通过了考试. - -- c. 只有一个学生在 2001 年春节学期上希腊语课. - -- d. 希腊语课的最好成绩总是比法语课的最好成绩高. - -#ans[ - 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) - - Takes(student, course, semester) - - - Passes(student, course, semester) - - - Score(student, course, semester, score) - - - x > y (x 比 y 大) - - 那么上面的四个语句可以分别表示如下: - - - a. $exists x, "Student"(x) and "Takes"(x, "French", "Spring2021")$ - - - b. $forall x, "Student"(x) and "Takes"(x, "French", "Spring2021") => "Passes"(x, "French", "Spring2021")$ - - - c. $exists x, "Student"(x) and "Takes"(x, "Greek", "Spring2021") and (forall y, "Student"(y) and "Takes"(y, "Greek", "Spring2021") => x = y)$ - - 注: 上述描述 = 存在这样的一个学生, 而且对于所有满足这样条件的学生, 都是同一个学生. - - - d. $forall s, x, exists y, "Semester"(s) and "Student"(x) and "Student"(y) and "Takes"(x, "Greek", s) and "Takes"(y, "French", s) => "Score"(x, "Greek", s) > "Score"(y, "French", s)$ -] - -- e. 每个买保险都是聪明的. -- f. 没有人会买昂贵的保险. -- g. 有一个代理, 他只向那些没投保的卖保险. - -#ans[ - 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) - - BuyInsurance(agent, insurance) - - - Expensive(insurance) - - - Smart(agent) - - - SellInsurance(agent, agent, insurance) - - - Insured(agent) - - 那么上面的三个语句可以分别表示如下: - - - e. $forall x, exists y, "Agent"(x) and "Policy"(y) and "BuyInsurance"(x, y) => "Smart"(x)$ - - - f. $forall x,y, "Agent"(x) and "Policy"(y) and "Expensive"(y) => not "BuyInsurance"(x, y)$ - - - g. $exists x, "Agent"(x) and (forall y, forall z, "Policy"(z) and "SellInsurance"(x, y, z)) => "Agent"(y) and (not "Insured"(y))$ -] - -- h. 镇上有一个理发师, 他给所有不自己刮胡子的人刮胡子. - -#ans[ - 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) - - Barber(agent) - - - Shave(A, B) (A 给 B 刮胡子) - - - SelfShave(agent) - - 那么上面的语句可以表示如下: - - - h. $exists x, "Agent"(x) and (forall y, "Agent"(y) and not "SelfShave"(y)) => "Shave"(x, y)$ -] - -- i. 在英国出生的人, 如果其双亲都是英国公民或者永久居住者, 那么此人生来就是一个英国公民. -- j. 在英国以外的地方出生的人, 如果其双亲生来就是英国公民, 那么此人血统上是一个英国公民. - -#ans[ - 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) - - BornIn(agent, place) - - - BritishCitizen(agent) - - - PermanentResident(agent) - - - Parent(agent, agent) - - - BloodCitizen(agent) - - 那么上面的两个语句可以分别表示如下: ++ 某些学生在 2001 年春季学期上法语课. ++ 上法语课的每个学生都通过了考试. ++ 只有一个学生在 2001 年春节学期上希腊语课. ++ 希腊语课的最好成绩总是比法语课的最好成绩高. + #ans[ + 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) + - Takes(student, course, semester) + - Passes(student, course, semester) + - Score(student, course, semester, score) + - x > y (x 比 y 大) + + 那么上面的四个语句可以分别表示如下: + + + $exists x, "Student"(x) and "Takes"(x, "French", "Spring2021")$ + + $forall x, "Student"(x) and "Takes"(x, "French", "Spring2021") => "Passes"(x, "French", "Spring2021")$ + + $exists x, "Student"(x) and "Takes"(x, "Greek", "Spring2021") and ( + forall y, "Student"(y) and "Takes"(y, "Greek", "Spring2021") => x = y + )$ + - 注: 上述描述 = 存在这样的一个学生, 而且对于所有满足这样条件的学生, 都是同一个学生. + + $forall s, x, exists y, "Semester"(s) and "Student"(x) and "Student"(y) and "Takes"(x, "Greek", s) and "Takes"( + y, "French", s + ) => "Score"(x, "Greek", s) > "Score"(y, "French", s)$ + ] ++ 每个买保险都是聪明的. ++ 没有人会买昂贵的保险. ++ 有一个代理, 他只向那些没投保的卖保险. + #ans[ + 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) + - BuyInsurance(agent, insurance) + - Expensive(insurance) + - Smart(agent) + - SellInsurance(agent, agent, insurance) + - Insured(agent) + + 那么上面的三个语句可以分别表示如下: + + #set enum(start: 5) + + $forall x, exists y, "Agent"(x) and "Policy"(y) and "BuyInsurance"(x, y) => "Smart"(x)$ + + $forall x,y, "Agent"(x) and "Policy"(y) and "Expensive"(y) => not "BuyInsurance"(x, y)$ + + $exists x, "Agent"(x) and (forall y, forall z, "Policy"(z) and "SellInsurance"(x, y, z)) => "Agent"(y) and ( + not "Insured"(y) + )$ + ] ++ 镇上有一个理发师, 他给所有不自己刮胡子的人刮胡子. - - i. $forall x, "Agent"(x) and "BornIn"(x, "UK") and (forall y, "Parent"(y, x) => ("BritishCitizen"(y) or "PermanentResident"(y))) => "BritishCitizen"(x)$ + #ans[ + 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) + - Barber(agent) + - Shave(A, B) (A 给 B 刮胡子) + - SelfShave(agent) - - j. $forall x, "Agent"(x) and not "BornIn"(x, "UK") and (forall y, "Parent"(y, x) => "BritishCitizen"(y)) => "BloodCitizen"(x)$ -] + 那么上面的语句可以表示如下: + #set enum(start: 8) + + $exists x, "Agent"(x) and (forall y, "Agent"(y) and not "SelfShave"(y)) => "Shave"(x, y)$ + ] ++ 在英国出生的人, 如果其双亲都是英国公民或者永久居住者, 那么此人生来就是一个英国公民. ++ 在英国以外的地方出生的人, 如果其双亲生来就是英国公民, 那么此人血统上是一个英国公民. + #ans[ + 定义词汇表如下: (防止赘述, 我们省略一些不必说明的定义) + - BornIn(agent, place) + - BritishCitizen(agent) + - PermanentResident(agent) + - Parent(agent, agent) + - BloodCitizen(agent) + + 那么上面的两个语句可以分别表示如下: + #set enum(start: 9) + + + $forall x, "Agent"(x) and "BornIn"(x, "UK") and ( + forall y, "Parent"(y, x) => ("BritishCitizen"(y) or "PermanentResident"(y)) + ) => "BritishCitizen"(x)$ + + $forall x, "Agent"(x) and not "BornIn"(x, "UK") and ( + forall y, "Parent"(y, x) => "BritishCitizen"(y) + ) => "BloodCitizen"(x)$ + ] === Question 9.3 假定知识库中只包括一条语句: $exists x, "AsHighAs"(x, "Everest")$. 下列哪个语句是应用存在量词实例化之后的合法结果? -- a. $"AsHighAs"("Everest", "Everest")$ -- b. $"AsHighAs"("kilimanjaro", "Everest")$ -- c. $"AsHighAs"("kilimanjaro", "Everest") and "AsHighAs"("benNevis", "Everest")$ ++ $"AsHighAs"("Everest", "Everest")$ ++ $"AsHighAs"("kilimanjaro", "Everest")$ ++ $"AsHighAs"("kilimanjaro", "Everest") and "AsHighAs"("benNevis", "Everest")$ #ans[ 仅 b & c. - a. Everest 已经出现在命题中, 应该进行标准化分离(重新命名)以避免混淆. + a: Everest 已经出现在命题中, 应该进行标准化分离(重新命名)以避免混淆. ] === Question 9.4 对于下列每对原子语句, 如果存在请给出最一般的合一置换: -- a. $P(A,B,B), P(x,y,z)$ - -#ans[ - ${x\/A, y\/B, z\/B}$ -] - -- b. $Q(y,G(A,B)), Q(G(x,x),y)$ - -#ans[ - 不存在, $x$ 不可能同时置换为 $A$ 和 $B$. -] - -- c. $:"Older"("Father"(y),y), "Older"("Father"(x), "John")$ - -#ans[ - ${x\/"John", y\/"John"}$ -] - -- d. $"Knows"("Father"(y),y), "Knows"(x,x)$ - -#ans[ - 不存在, $x$ 不可能同时置换为 $"Father"(y)$ 和 $y$. -] ++ $P(A,B,B), P(x,y,z)$ + #ans[ + ${x\/A, y\/B, z\/B}$ + ] ++ $Q(y,G(A,B)), Q(G(x,x),y)$ + #ans[ + 不存在, $x$ 不可能同时置换为 $A$ 和 $B$. + ] ++ $:"Older"("Father"(y),y), "Older"("Father"(x), "John")$ + #ans[ + ${x\/"John", y\/"John"}$ + ] ++ $"Knows"("Father"(y),y), "Knows"(x,x)$ + #ans[ + 不存在, $x$ 不可能同时置换为 $"Father"(y)$ 和 $y$. + ] === Question 9.6 #ans[ - - a. 马, 奶牛, 猪都是哺乳动物. - $ - &"Horse"(x) => "Mammal"(x) \ - &"Cow"(x) => "Mammal"(x) \ - &"Pig"(x) => "Mammal"(x) - $ - - - b. 马的后代是马. - $ - "Offspring"(x,y) and "Horse"(y) => "Horse"(x)\ - $ - - - c. Bluebeard 是马. - $ - "Horse"("Bluebeard") - $ - - - d. Bluebeard 是 Charlie 的家长. - $ - "Parent"("Bluebeard", "Charlie") - $ - - - e. 后代与家长是相互的. - $ - &"Offspring"(x,y) => "Parent"(y,x)\ - &"Parent"(x,y) => "Offspring"(y,x)\ - $ - - - f. 所有哺乳动物都有家长. - $ - "Mammal"(x) => "Parent"(S(x), x) - $ - 其中 $S$ 是 Skolem 函数. + #show math.equation.where(block: true): it => box(width: 100%, it) + + 马, 奶牛, 猪都是哺乳动物. + $ + &"Horse"(x) => "Mammal"(x) \ + &"Cow"(x) => "Mammal"(x) \ + &"Pig"(x) => "Mammal"(x) + $ + + 马的后代是马. + $ + "Offspring"(x,y) and "Horse"(y) => "Horse"(x)\ + $ + + Bluebeard 是马. + $ + "Horse"("Bluebeard") + $ + + Bluebeard 是 Charlie 的家长. + $ + "Parent"("Bluebeard", "Charlie") + $ + + 后代与家长是相互的. + $ + &"Offspring"(x,y) => "Parent"(y,x)\ + &"Parent"(x,y) => "Offspring"(y,x)\ + $ + + 所有哺乳动物都有家长. + $ + "Mammal"(x) => "Parent"(S(x), x) + $ + 其中 $S$ 是 Skolem 函数. ] === Question 9.13 本题中需要用到你在习题 9.6 中写出的语句, 运用反向链接算法来回答问题. -- a. 画出用穷举反向链接算法为查询 $exists h, "horse"(h)$ 生成的证明树, 其中子句按照给定的顺序进行排序 -- b. 对于本领域, 你注意到了什么? -- c. 实际上从你的语句中得出了多少个 $h$ 的解? ++ 画出用穷举反向链接算法为查询 $exists h, "horse"(h)$ 生成的证明树, 其中子句按照给定的顺序进行排序 ++ 对于本领域, 你注意到了什么? ++ 实际上从你的语句中得出了多少个 $h$ 的解? #ans[ - - a. 证明树如下: - #let data = ( - [Horse(h)], - (([Offspring(h, y)]), [Parent(y,h)]), - ( - [Horse(Bluebeard)], + + 证明树如下: + #let data = ( + [Horse(h)], + (([Offspring(h, y)]), [Parent(y,h)]), ( - [Offspring(Bluebeard, y)], + [Horse(Bluebeard)], ( - [Parent(y, Bluebeard)], + [Offspring(Bluebeard, y)], ( - [Offspring(y, Charlie)], - [$dots.v$], - [] + [Parent(y, Bluebeard)], + ( + [Offspring(y, Charlie)], + [$dots.v$], + [], + ), + [], ), - [] + [], ), - [] + [], ), - [] ) - ) - - #canvas( - length: 1cm, - { - import draw: * - - set-style( - content: (padding: .2), - fill: gray.lighten(70%), - stroke: gray.lighten(70%), - ) - - tree.tree( - data, - spread: 2., - grow: 1.5, - draw-node: (node, ..) => { - content((), node.content) - }, - draw-edge: (from, to, ..) => { - line( - (a: from, number: .6, b: to), - (a: to, number: .6, b: from), - mark: (end: ">"), - ) - }, - name: "tree", - ) - }, - ) - - - b. 上面的证明树会陷入无限循环, 因为 $"Offspring"(x,y) and "Horse"(y) => "Horse"(x)$ - - - c. 两个 $"Horse"("Bluebeard") $, $"Horse"("Charlie")$ + + #canvas( + length: 0.9cm, + { + import draw: * + + set-style( + content: (padding: .2), + fill: gray.lighten(70%), + stroke: gray.lighten(70%), + ) + + tree.tree( + data, + spread: 2., + grow: 1.5, + draw-node: (node, ..) => { + content((), node.content) + }, + draw-edge: (from, to, ..) => { + line( + (a: from, number: .6, b: to), + (a: to, number: .6, b: from), + mark: (end: ">"), + ) + }, + name: "tree", + ) + }, + ) + + 上面的证明树会陷入无限循环, 因为 $"Offspring"(x,y) and "Horse"(y) => "Horse"(x)$ + + 两个 $"Horse"("Bluebeard") $, $"Horse"("Charlie")$ ] \ No newline at end of file diff --git a/ea2724-ai_hw/hw7.typ b/ea2724-ai_hw/hw7.typ index cb62d72..630cf15 100644 --- a/ea2724-ai_hw/hw7.typ +++ b/ea2724-ai_hw/hw7.typ @@ -2,16 +2,17 @@ Due 2024.05.12 #import "@preview/diagraph:0.2.1": * -#let ans(it) = { - box(inset: 1em, width: 100%)[ +#let ans(it) = [ + #pad(1em)[ #text(fill: blue)[ #it ] ] -} +] #show math.equation: it => [ #math.display(it) ] +#show image: it => align(center, it) === Question 13.15 @@ -32,24 +33,18 @@ Due 2024.05.12 }, stroke: blue, align: center, - [], - [阳性], - [阴性], - [患病: $1\/10000$], - [$1\/10000 times 99\/100$], - [$1\/10000 times 1\/100$], - [未患病: $9999\/10000$], - [$9999\/10000 times 1\/100$], - [$9999\/10000 times 99\/100$], + [], [阳性], [阴性], + [患病: $1\/10000$], [$1\/10000 times 99\/100$], [$1\/10000 times 1\/100$], + [未患病: $9999\/10000$], [$9999\/10000 times 1\/100$], [$9999\/10000 times 99\/100$], ) 在已知我检测结果为阳性的情况下, 我确实患病的概率为: $ - (1\/10000 times 99\/100) / (1\/10000 times 99\/100 + 9999\/10000 times 1\/100) approx 0.0098 < 1% + (1\/10000 times 99\/100) / (1\/10000 times 99\/100 + 9999\/10000 times 1\/100) approx 0.0098 < 1% $ 如果这并不是罕见病, 例如每$100$人就有$1$人患病, 那么在阳性检测结果下我确实患病的概率将会是: $ - (1\/100 times 99\/100) / (1\/100 times 99\/100 + 99\/100 times 1\/100) = 0.5 + (1\/100 times 99\/100) / (1\/100 times 99\/100 + 99\/100 times 1\/100) = 0.5 $ 从这个角度说, 这种病很罕见对于我而言是一个好消息. @@ -59,108 +54,90 @@ Due 2024.05.12 假设给你一只袋子,装有个无偏差的硬币,并且告诉你其中$n$个硬币是正常的,一面是正面而另一面是反面。不过剩余$1$枚硬币是伪造的,它的两面都是正面。 -a. 假设你把手伸进口袋均匀随机地取出一枚硬币,把它抛出去,硬币落地后正面朝上。那么你取出伪币的(条件)概率是多少? - -#ans[ - $ - &P("fake") = 1 / n &quad& P("normal") = 1 - 1 / n&\ - &P("head"|"fake") = 1 &quad& P("head"|"normal") = 1 / 2&\ - &P("tail"|"fake") = 0 &quad& P("tail"|"normal") = 1 / 2&\ - $ - $ - => P("fake"|"head") = (P("head"|"fake")P("fake")) / P("head") = (1\/n) / (1\/n + (1-1\/n)\/2) = 2 / (n+1) - $ -] - -b. 假设你不停地抛这枚硬币,一共抛了$k$次,而且看到$k$次正面向上。那么你取出伪币的条件概率是多少? - -#ans[ - $ - P("fake"|"head"^k) = (P("head"^k|"fake")P("fake")) / P("head"^k) = (1^k dot 1\/n) / (1^k dot 1\/n + (1-1\/n) dot ( - 1\/2 - )^k) = (2^k) / (2^k+n-1) - $ -] - -c. 假设你希望通过把取出的硬币抛$k$次的方法来确定它是不是伪造的。如果抛次后都是正面朝上,那么决策过程返回 fake(伪造),否则返回 normal(正常)。这个过程发生错误的(无条件)概率是多少? - -#ans[ - $ - P("WA") = P("normal" and "head"^k) = (1-1 / n) dot (1 / 2)^k - $ -] ++ 假设你把手伸进口袋均匀随机地取出一枚硬币,把它抛出去,硬币落地后正面朝上。那么你取出伪币的(条件)概率是多少? + #ans[ + $ + &P("fake") = 1 / n &quad& P("normal") = 1 - 1 / n&\ + &P("head"|"fake") = 1 &quad& P("head"|"normal") = 1 / 2&\ + &P("tail"|"fake") = 0 &quad& P("tail"|"normal") = 1 / 2&\ + $ + $ + => P("fake"|"head") = (P("head"|"fake")P("fake")) / P("head") = (1\/n) / (1\/n + (1-1\/n)\/2) = 2 / (n+1) + $ + ] ++ 假设你不停地抛这枚硬币,一共抛了$k$次,而且看到$k$次正面向上。那么你取出伪币的条件概率是多少? + + #ans[ + $ + P("fake"|"head"^k) = (P("head"^k|"fake")P("fake")) / P("head"^k) = (1^k dot 1\/n) / (1^k dot 1\/n + (1-1\/n) dot ( + 1\/2 + )^k) = (2^k) / (2^k+n-1) + $ + ] ++ 假设你希望通过把取出的硬币抛$k$次的方法来确定它是不是伪造的。如果抛次后都是正面朝上,那么决策过程返回 fake(伪造),否则返回 normal(正常)。这个过程发生错误的(无条件)概率是多少? + #ans[ + $ + P("WA") = P("normal" and "head"^k) = (1-1 / n) dot (1 / 2)^k + $ + ] === Question 13.21 (改编自Pearl (1988)的著述.) 假设你是雅典一次夜间出租车肇事逃逸的交通事的目击者。雅典所有的出租车都是蓝色或者绿色的。而你发誓所看见的肇事出租车是蓝色的。大量测试表明,在昏暗的灯光条件下,区分蓝色和绿色的可靠度为 $75 percent$。 -a. 有可能据此计算出肇事出租车最可能是什么颜色吗?(提示:请仔细区分命题“肇事车是蓝色的”和命题“肇事车看起来是蓝色的”。) - -#ans[ - 不能. 我们知道肇事车看起来的颜色, 但是不知道真实颜色的概率分布. 例如, 如果绿色出租车的数量远远多于蓝色出租车, 那么即使看起来是蓝色的车辆的概率也可能很高.(与上面罕见病的例子类似) -] - -b. 如果你知道雅典的出租车 $10$ 辆中有 $9$ 辆是绿色的呢? - -#ans[ - 也与上面罕见病类似, 我们整理出所有可能的情况如下: - - #table( - columns: (auto, auto, auto), - fill: (x, y) => { - if (x == 0 or y == 0) and not (x == 0 and y == 0) { - blue.lighten(80%) - } - if (x == 0 and y == 0) { - blue.lighten(60%) - } - }, - stroke: blue, - align: center, - [], - [看起来蓝色], - [看起来绿色], - [真实蓝色], - [$1\/10 times 3\/4$], - [$1\/10 times 1\/4$], - [真实绿色], - [$9\/10 times 1\/4$], - [$9\/10 times 3\/4$], - ) - - 因此在 「看起来是蓝色」的前提下, 真实是蓝色的概率为: $1\/4$, 真实是绿色的概率为 $3\/4$. 肇事车最可能是绿色的. -] ++ 有可能据此计算出肇事出租车最可能是什么颜色吗?(提示:请仔细区分命题“肇事车是蓝色的”和命题“肇事车看起来是蓝色的”。) + #ans[ + 不能. 我们知道肇事车看起来的颜色, 但是不知道真实颜色的概率分布. 例如, 如果绿色出租车的数量远远多于蓝色出租车, 那么即使看起来是蓝色的车辆的概率也可能很高.(与上面罕见病的例子类似) + ] ++ 如果你知道雅典的出租车 $10$ 辆中有 $9$ 辆是绿色的呢? + #ans[ + 也与上面罕见病类似, 我们整理出所有可能的情况如下: + + #table( + columns: (auto, auto, auto), + fill: (x, y) => { + if (x == 0 or y == 0) and not (x == 0 and y == 0) { + blue.lighten(80%) + } + if (x == 0 and y == 0) { + blue.lighten(60%) + } + }, + stroke: blue, + align: center, + [], [看起来蓝色], [看起来绿色], + [真实蓝色], [$1\/10 times 3\/4$], [$1\/10 times 1\/4$], + [真实绿色], [$9\/10 times 1\/4$], [$9\/10 times 3\/4$], + ) + + 因此在 「看起来是蓝色」的前提下, 真实是蓝色的概率为: $1\/4$, 真实是绿色的概率为 $3\/4$. 肇事车最可能是绿色的. + ] === Question 13.22 文本分类是基于文本内容将给定的一个文档分类成固定的几个类中的一类。朴素贝叶斯模型经常用于这个问题。在朴素贝叶斯模型中,查询(query)变量是这个文档的类别,而结果(effect)变量是语言中每个单词的存在与否;假设文档中单词的出现是独立的,单词的出现频率由文档类别决定。 -a. 给定一组已经被分类的文档,准确解释如何构造这样的模型。 - -#ans[ - 考虑一组已经分类的文档, $C = {C_i}$, 对于每个单词 $w_j$, 我们可以计算出在每个类别下的概率 $P(w_j|C_i)$. - - 我们再计算每个类别的概率 $P(C_i)$, 以及每个单词的概率 $P(w_j)$. -] - -b. 准确解释如何分类一个新文档。 - -#ans[ - 考虑一篇新文档含有单词 $w_1 ,dots.c, w_k$, 分别计算在各个分类下, 这些单词出现的概率: - - $ - P(C_i|w_1,dots,w_k) &= (P(w_1, dots.c, w_k) dot P(C_i)) / (P(w_1, dots.c, w_k))\ - &= (limits(product)_i P(w_j|C_i) dot P(C_i)) / (P(w_1, dots.c, w_k)) - $ ++ 给定一组已经被分类的文档,准确解释如何构造这样的模型。 + #ans[ + 考虑一组已经分类的文档, $C = {C_i}$, 对于每个单词 $w_j$, 我们可以计算出在每个类别下的概率 $P(w_j|C_i)$. - 无需计算分母, 只需比较各个分类下的概率即可. -] + 我们再计算每个类别的概率 $P(C_i)$, 以及每个单词的概率 $P(w_j)$. + ] ++ 准确解释如何分类一个新文档。 + #ans[ + 考虑一篇新文档含有单词 $w_1 ,dots.c, w_k$, 分别计算在各个分类下, 这些单词出现的概率: -c. 题目中的条件独立性假设合理吗?请讨论。 + $ + P(C_i|w_1,dots,w_k) &= (P(w_1, dots.c, w_k) dot P(C_i)) / (P(w_1, dots.c, w_k))\ + &= (limits(product)_i P(w_j|C_i) dot P(C_i)) / (P(w_1, dots.c, w_k)) + $ -#ans[ - 这个假设并不合理. 例如, 在一篇关于机器学习的文章中, 出现了 "机器" 这个词, 那么 "学习" 这个词出现的概率就会变得很大. 这两个词并不是独立的. -] + 无需计算分母, 只需比较各个分类下的概率即可. + ] ++ 题目中的条件独立性假设合理吗?请讨论。 + #ans[ + 这个假设并不合理. 例如, 在一篇关于机器学习的文章中, 出现了 "机器" 这个词, 那么 "学习" 这个词出现的概率就会变得很大. 这两个词并不是独立的. + ] === Question 14.12 @@ -209,6 +186,7 @@ c. 题目中的条件独立性假设合理吗?请讨论。 } ```) ], + [ (i) ], @@ -221,233 +199,228 @@ c. 题目中的条件独立性假设合理吗?请讨论。 ) ] -a. 这三种网络结构哪些是对上述信息的正确(但不一定高效)表示? - -#ans[ - (ii), (iii) 正确; - - 考虑到 $ P(N mid(|)M_1)!=P(N|M_1,F_1) $ 所以 $F_1$ 与 $M$ 应该同时连接到 $N$, (i) 不正确. -] - -b.哪一种网络结构是最好的?请解释。 - -#ans[ - (ii), 关系少, 更紧致. -] - -c.当 $N in {1,2,3}, quad M_1 in {0,1,2,3,4}$时,请写出 $P(M_1 mid(|) N)$ 的条件概率表。概率分布表里的每个条目都应该表达为参数$e$和/或$f$的一个函数。 - -#ans[ - - $ - P(M_1 mid(|) N) &= P(M_1 mid(|) N, F_1) P(F_1 mid(|) N) + P(M_1 mid(N), not F_1) P(not F_1 mid(|) N)\ - &= P(M_1 mid(|) N, F_1) P(F_1) + P(M_1 mid(N), not F_1) P(not F_1)\ - $ - - #table( - columns: (auto, auto, auto, auto, auto, auto), - align: center, - fill: (x, y) => { - if (x == 0 or y == 0) and not (x == 0 and y == 0) { - blue.lighten(80%) - } - if (x == 0 and y == 0) { - blue.lighten(90%) - } - }, - stroke: blue, - [ - $P(M_1 mid(|) N)$ - ], - [ - $M_1 = 0$ - ], - [ - $M_1 = 1$ - ], - [ - $M_1 = 2$ - ], - [ - $M_1 = 3$ - ], - [ - $M_1 = 4$ - ], - [ - $N = 1$ - ], - [ - $f+e(1-f)$ - ], - [ - $(1-2e)(1-f)$ - ], - [ - $e(1-f)$ - ], - [ - #set text(fill: red) - $0$ - ], - [ - $0$ - ], - [ - $N = 2$ - ], - [ - $f$ - ], - [ - #set text(fill: green) - $e(1-f)$ - ], - [ - $(1-2e)(1-f)$ - ], - [ - #set text(fill: green) - $e(1-f)$ - ], - [ - $0$ - ], - [ - $N = 3$ - ], - [ - $f$ - ], - [ - #set text(fill: red) - $0$ - ], - [ - $e(1-f)$ - ], - [ - $(1-2e)(1-f)$ - ], - [ - $e(1-f)$ - ], - ) -] - -d.假设 $M_1 = 1, quad M_2 = 3$。如果我们假设 $N$ 取值上没有先验概率约束,可能的恒星数目是多少? - -#ans[ - - #table( - columns: (auto, auto, auto, auto, auto, auto, auto), - align: center, - fill: (x, y) => { - if (x == 0 or y == 0) and not (x == 0 and y == 0) { - blue.lighten(80%) - } - if (x == 0 and y == 0) { - blue.lighten(90%) - } - }, - stroke: blue, - [ - $P(M_1 mid(|) N)$ - ], - [ - $M_1 = 0$ - ], - [ - $M_1 = 1$ - ], - [ - $M_1 = 2$ - ], - [ - $M_1 = 3$ - ], - [ - $M_1 = 4$ - ], - [ - $dots.c$ - ], - [ - $N = 4$ - ], - [ - $f$ - ], - [ - #set text(fill: green) - $f$ - ], - [ - $0$ - ], - [ - #set text(fill: green) - $e(1-f)$ - ], - [ - $(1-2e)(1-f)$ - ], - [ - $dots.c$ - ], - [ - $N=5$ - ], - [ - $f$ - ], - [ - $f$ - ], - [ - $f$ - ], - [ - #set text(fill: red) - $0$ - ], - [ - $e(1-f)$ - ], - [ - $dots.c$ - ], - ) - #let color_r(x) = text(fill: red, $#x$) - $ - P(M = 3 mid(|) N = 0) = 0 &quad& => &quad& N!=0\ - P(M = 3 mid(|) N = 1) = 0 &quad& => &quad& N!=1\ - P(M = 1 mid(|) N = 3) = 0 &quad& => &quad& N!=3\ - P(M = 1 mid(|) N = 5) = 0 &quad& => &quad& N!=5\ - $ - - $P(M = i mid(|) N = n) > 0 quad forall i = 1,3; n = 2,4$ 已经在表中标记出来了. (考虑到 $f approx 0$ 时=, 我们近似地认为每行加起来为 $1$. ) - - 考虑 $n >= 6$ 时, $P(M = 1 mid(|) N = n) = P(M = 3 mid(|) N = n) = f > 0$. - - 因此可能的 $n$ 的取值为 $2,4$ 或 $n>=6$ -] - -e.在这些观测结果下,最可能的恒星数目是多少?解释如何计算这个数目,或者,如果不可能计算,请解释还需要什么附加信息以及它将如何影响结果。 ++ 这三种网络结构哪些是对上述信息的正确(但不一定高效)表示? + #ans[ + (ii), (iii) 正确; -#ans[ - 缺少 $N$ 的先验概率分布, 无法计算最可能的恒星数目. + 考虑到 $ P(N mid(|)M_1)!=P(N|M_1,F_1) $ 所以 $F_1$ 与 $M$ 应该同时连接到 $N$, (i) 不正确. + ] ++ 哪一种网络结构是最好的?请解释。 + #ans[ + (ii), 关系少, 更紧致. + ] ++ 当 $N in {1,2,3}, quad M_1 in {0,1,2,3,4}$时,请写出 $P(M_1 mid(|) N)$ 的条件概率表。概率分布表里的每个条目都应该表达为参数$e$和/或$f$的一个函数。 + #ans[ + + $ + P(M_1 mid(|) N) &= P(M_1 mid(|) N, F_1) P(F_1 mid(|) N) + P(M_1 mid(N), not F_1) P(not F_1 mid(|) N)\ + &= P(M_1 mid(|) N, F_1) P(F_1) + P(M_1 mid(N), not F_1) P(not F_1)\ + $ + + #table( + columns: (auto, auto, auto, auto, auto, auto), + align: center, + fill: (x, y) => { + if (x == 0 or y == 0) and not (x == 0 and y == 0) { + blue.lighten(80%) + } + if (x == 0 and y == 0) { + blue.lighten(90%) + } + }, + stroke: blue, + [ + $P(M_1 mid(|) N)$ + ], + [ + $M_1 = 0$ + ], + [ + $M_1 = 1$ + ], + [ + $M_1 = 2$ + ], + [ + $M_1 = 3$ + ], + [ + $M_1 = 4$ + ], + + [ + $N = 1$ + ], + [ + $f+e(1-f)$ + ], + [ + $(1-2e)(1-f)$ + ], + [ + $e(1-f)$ + ], + [ + #set text(fill: red) + $0$ + ], + [ + $0$ + ], + + [ + $N = 2$ + ], + [ + $f$ + ], + [ + #set text(fill: green) + $e(1-f)$ + ], + [ + $(1-2e)(1-f)$ + ], + [ + #set text(fill: green) + $e(1-f)$ + ], + [ + $0$ + ], + + [ + $N = 3$ + ], + [ + $f$ + ], + [ + #set text(fill: red) + $0$ + ], + [ + $e(1-f)$ + ], + [ + $(1-2e)(1-f)$ + ], + [ + $e(1-f)$ + ], + ) + ] ++ 假设 $M_1 = 1, quad M_2 = 3$。如果我们假设 $N$ 取值上没有先验概率约束,可能的恒星数目是多少? + #ans[ + #table( + columns: (auto, auto, auto, auto, auto, auto, auto), + align: center, + fill: (x, y) => { + if (x == 0 or y == 0) and not (x == 0 and y == 0) { + blue.lighten(80%) + } + if (x == 0 and y == 0) { + blue.lighten(90%) + } + }, + stroke: blue, + [ + $P(M_1 mid(|) N)$ + ], + [ + $M_1 = 0$ + ], + [ + $M_1 = 1$ + ], + [ + $M_1 = 2$ + ], + [ + $M_1 = 3$ + ], + [ + $M_1 = 4$ + ], + [ + $dots.c$ + ], + + [ + $N = 4$ + ], + [ + $f$ + ], + [ + #set text(fill: green) + $f$ + ], + [ + $0$ + ], + [ + #set text(fill: green) + $e(1-f)$ + ], + [ + $(1-2e)(1-f)$ + ], + [ + $dots.c$ + ], + + [ + $N=5$ + ], + [ + $f$ + ], + [ + $f$ + ], + [ + $f$ + ], + [ + #set text(fill: red) + $0$ + ], + [ + $e(1-f)$ + ], + [ + $dots.c$ + ], + ) + #let color_r(x) = text(fill: red, $#x$) + $ + P(M = 3 mid(|) N = 0) = 0 &quad& => &quad& N!=0\ + P(M = 3 mid(|) N = 1) = 0 &quad& => &quad& N!=1\ + P(M = 1 mid(|) N = 3) = 0 &quad& => &quad& N!=3\ + P(M = 1 mid(|) N = 5) = 0 &quad& => &quad& N!=5\ + $ + + $P(M = i mid(|) N = n) > 0 quad forall i = 1,3; n = 2,4$ 已经在表中标记出来了. (考虑到 $f approx 0$ 时=, 我们近似地认为每行加起来为 $1$. ) + + 考虑 $n >= 6$ 时, $P(M = 1 mid(|) N = n) = P(M = 3 mid(|) N = n) = f > 0$. + + 因此可能的 $n$ 的取值为 $2,4$ 或 $n>=6$ + ] ++ 在这些观测结果下,最可能的恒星数目是多少?解释如何计算这个数目,或者,如果不可能计算,请解释还需要什么附加信息以及它将如何影响结果。 + #ans[ + 缺少 $N$ 的先验概率分布, 无法计算最可能的恒星数目. - 考虑我们提供一个分布: $P(N=n) = p_n quad forall n = 2,4,6,7, dots$ + 考虑我们提供一个分布: $P(N=n) = p_n quad forall n = 2,4,6,7, dots$ - $ - &P(N=2, M_1 = 1, M_2 = 3) &=& p_2 e^2(1-f)^2\ - &P(N=4, M_1 = 1, M_2 = 3) &=& p_4 e f(1-f)^2\ - (n>=6) quad &P(N=n, M_1 = 1, M_2 = 3) &=& p_n f^2\ - $ + $ + &P(N=2, M_1 = 1, M_2 = 3) &=& p_2 e^2(1-f)^2\ + &P(N=4, M_1 = 1, M_2 = 3) &=& p_4 e f(1-f)^2\ + (n>=6) quad &P(N=n, M_1 = 1, M_2 = 3) &=& p_n f^2\ + $ - 计算出并比较大小即可, 取 $n="argmax"_n P(N=n, M_1 = 1, M_2 = 3)$. -] + 计算出并比较大小即可, 取 $n="argmax"_n P(N=n, M_1 = 1, M_2 = 3)$. + ] === Question 14.13 @@ -455,16 +428,16 @@ e.在这些观测结果下,最可能的恒星数目是多少?解释如何计 #ans[ $ - cal(P)(N mid(|) M_1=2, M_2=2) &= alpha sum_(f_1,f_2) cal(P)(f_1, f_2, N, M_1=2,M_2=2)\ - &=alpha sum_(f_1,f_2) P(f_1) P(f_2) cal(P)(N) P(M_1=2,M_2=2) + cal(P)(N mid(|) M_1=2, M_2=2) &= alpha sum_(f_1,f_2) cal(P)(f_1, f_2, N, M_1=2,M_2=2)\ + &=alpha sum_(f_1,f_2) P(f_1) P(f_2) cal(P)(N) P(M_1=2,M_2=2) $ 考虑到 $M_1=M_2=2$, 只有 $F_1=F_2="false"$ 时才能满足, 因此: $ - cal(P)(N mid(|) M_1=2, M_2=2) &= alpha (1-f)^2 angle.l p_1, p_2, p_3 angle.r angle.l e, (1-2e), e angle.r angle.l e, ( - 1-2e - ), e angle.r\ - &= alpha^' angle.l p_1 e^2, p_2(1-2e)^2, p_3 e^2 angle.r + cal(P)(N mid(|) M_1=2, M_2=2) &= alpha (1-f)^2 angle.l p_1, p_2, p_3 angle.r angle.l e, ( + 1-2e + ), e angle.r angle.l e, (1-2e), e angle.r\ + &= alpha^' angle.l p_1 e^2, p_2(1-2e)^2, p_3 e^2 angle.r $ ] \ No newline at end of file diff --git a/ea2724-ai_hw/hw8.typ b/ea2724-ai_hw/hw8.typ index 5964af0..0d7e0f5 100644 --- a/ea2724-ai_hw/hw8.typ +++ b/ea2724-ai_hw/hw8.typ @@ -121,7 +121,7 @@ $ 计算得到: $w=(-1,2)^T, b = -2$, 超平面方程: $-x+2y-2=0$ - #image("./img/Solution_HW8_Q4.png", width: 70%) + #image("./imgs/Solution_HW8_Q4.png", width: 70%) ] === Q5 diff --git a/ea2724-ai_hw/img/Solution_4.6.jpg b/ea2724-ai_hw/imgs/Solution_4.6.jpg similarity index 100% rename from ea2724-ai_hw/img/Solution_4.6.jpg rename to ea2724-ai_hw/imgs/Solution_4.6.jpg diff --git a/ea2724-ai_hw/img/Solution_4.7.jpg b/ea2724-ai_hw/imgs/Solution_4.7.jpg similarity index 100% rename from ea2724-ai_hw/img/Solution_4.7.jpg rename to ea2724-ai_hw/imgs/Solution_4.7.jpg diff --git a/ea2724-ai_hw/img/Solution_5.8_1.jpg b/ea2724-ai_hw/imgs/Solution_5.8_1.jpg similarity index 100% rename from ea2724-ai_hw/img/Solution_5.8_1.jpg rename to ea2724-ai_hw/imgs/Solution_5.8_1.jpg diff --git a/ea2724-ai_hw/img/Solution_5.9.jpg b/ea2724-ai_hw/imgs/Solution_5.9.jpg similarity index 100% rename from ea2724-ai_hw/img/Solution_5.9.jpg rename to ea2724-ai_hw/imgs/Solution_5.9.jpg diff --git a/ea2724-ai_hw/img/Solution_HW8_Q4.png b/ea2724-ai_hw/imgs/Solution_HW8_Q4.png similarity index 100% rename from ea2724-ai_hw/img/Solution_HW8_Q4.png rename to ea2724-ai_hw/imgs/Solution_HW8_Q4.png diff --git a/ea2724-ai_hw/imgs/sticker_1.jpg b/ea2724-ai_hw/imgs/sticker_1.jpg new file mode 100644 index 0000000..c4072b6 Binary files /dev/null and b/ea2724-ai_hw/imgs/sticker_1.jpg differ diff --git a/ea2724-ai_hw/main.typ b/ea2724-ai_hw/main.typ index 68bbaa8..097cb5c 100644 --- a/ea2724-ai_hw/main.typ +++ b/ea2724-ai_hw/main.typ @@ -1,24 +1,49 @@ +#import "@preview/cetz:0.2.2": * +#import "@preview/diagraph:0.2.1": * + #set text( font: ("linux libertine", "Source Han Serif SC", "Source Han Serif"), size: 10pt, ) -= USTC/AI2024 人工智能基础 书面作业 +#align(horizon + right)[ + #text(size: 12pt)[ + = USTC/ALGO24 人工智能基础 书面作业 + ] + PB21000030 马天开 -PB21000030 马天开 + #v(4em) -#include "hw8.typ" -#pagebreak() -#include "hw7.typ" + 2024 年 春季学期 中国科学技术大学 人工智能基础 课程书面作业. + + #v(4em) + + 使用 Typst 编写而成, 代码托管在: #link("https://github.com/tiankaima/typst-notes") + + 本文档以 CC BY-NC-SA 4.0 协议发布. 请遵守学术诚信, 不得用于商业用途. + + #image("imgs/sticker_1.jpg", width: 30%) +] + +#pagebreak(weak: true) + +#show math.equation: it => math.display(it) +#show image: it => align(center, it) +#show raw.where(block: true): it => rect(stroke: 0.02em, width: 100%, inset: 1em, it) +#set enum(numbering: "a)") + +#include "hw1.typ" #pagebreak() -#include "hw6.typ" +#include "hw2.typ" #pagebreak() -#include "hw5.typ" +#include "hw3.typ" #pagebreak() #include "hw4.typ" #pagebreak() -#include "hw3.typ" +#include "hw5.typ" #pagebreak() -#include "hw2.typ" +#include "hw6.typ" #pagebreak() -#include "hw1.typ" +#include "hw7.typ" +#pagebreak() +#include "hw8.typ" \ No newline at end of file