[通識] 文明的進程 小組報告

主題

跨國的文明競逐與衝突-原住民的文化問題

報告核心-文明的傲慢

「原住民」稱呼為何而來?

誠心臣服在我太陽帝國之下

正因為我們是侵略者!他們才是 真‧台灣人

AcFun 線上看-《賽德克巴萊》

在評論中大陸人這麼說

  • 「為什麼他們不說國語?」
  • 「一隻豬發生的血案?」
  • 「他們才是真台灣人啊。」

都已經被我們給文明化了

要求弱勢族群做出相同的行為-那就是一種 傲慢

文化差異

漢人文化需要競爭,做任何事情都需要競爭,而原住民只要在工作上能夠溫飽就能快樂過活,藉由唱歌舞蹈等表現方式來闡述他們的快樂,及時行樂整是他們的天性,說他們懶惰不上進才是我們的傲慢。相較於競爭,他們是互助合作的生命共同體,在那種生存環境下,農耕、狩獵都要互相幫忙,你說競爭下的快樂帶給多少回饋?

把我的尊嚴還給我!

如何表現自己的英勇事蹟?奮勇殺敵、狩獵得到的 骸骨 作為一個能力階層。即使如此,敬老尊賢是重要的文化,年齡階層而非能力階層。做為一個活在漢人社會的人而言,能力若決定一生,而談快樂?雖然能力不如人,難道就培養不出比自己厲害的人?也許虎媽就是這麼來的。

還敢帶刀 ... 混蛋!

佩刀難道錯了嗎?佩刀是因為生活所需,也是我們地位的象徵。憑什麼要求不能帶刀,那你們帶刀又是什麼意思,相比中古世紀騎士可以制裁的對象,低層社會人們只能對自己以下的對象進行攻擊。

融入現代社會

  • 第一階段-原住民成年人
    從成年人開始步入社會,雖然一開始會接受很殘酷的生活適應,還必須使用 漢姓 ,論名字對自尊的重要性,即使謀求到工作,並且逐漸適應生活所需。(有多少人能失去自己的名字?)
  • 第二階段-孩子教育
    由於長時間活在漢人社會,孩子學習也就必須上小學,然而文化的成長背景不同下,做為父母能教導什麼給孩子?就因為環境不同,知識理解的差異所引來歧視,難道就是錯的嗎?
  • 第三階段-傳統繼承
    村落沒有新血、沒有傳承,不就是鼓勵他們進入漢人社會的原因嗎?

什麼樣背景的人用什麼方式學,不是比較好理解嗎?學習成績不好沒什麼好擔心,只是規格面向不同。不懂不是問題,只是要換的方式。

保有精神

也改變不了這張不被文明認同的臉

我們的信仰、精神,藉由血緣牽連在一起。

巴萬,你的獵場在哪裡?

矛盾所在

  • 用很多補償條款鼓勵原住民進入我們漢人社會,但又希望他們保有他們自己的文化?

鼓勵改變,但卻又希望不變?(你們這群人到底想怎樣!)

  • 武力較強的文明使得我們成功掠奪這塊土地,而這種文明真的是文明嗎?難道不就是個野蠻人?
  • 想想印地安原住民的文化,真的是所謂低於來自被歐洲驅逐的人們所擁有的嗎?
  • 如果你們所說小七是文明的象徵?想要成為你們所說的文明文化有錯嗎?

反問小朋友:「沒有漢堡和薯條,你們都吃什麼?」小朋友答說,就吃海裡抓的九孔和龍蝦。

  • 文章中見到蘭嶼小孩吃山珍海味,那豈不是反了?依照生活的飲食水準,到底是誰過得奢侈?

世界原住民

當年英國統治的殖民地眾多,要不是他們可以退回祖國,那群人也是相當龐大的原住民。然而我們仗著人數眾多,無法退出的處境,厚臉皮地活在這片土地。不是中國對待少數民族的方式,他們在同一個文化脈絡下分支成長,即使不能理解,也能知道自己是同一脈人,已經磨得相當長久的時間。

縱使看著別國對待本國原住民的方式,例如:規劃保護區、歸還土地… 等,同時也表明了曾經使用過的暴力,他們的處境與我們台灣不同,他們有原本的家可以回,而我們必須對抗其他國家的勢力,必須與原住民站在同一條船上,也許對待他們的方式相比別國來說殘酷,一旦我們的立場被別國 (如中國,他們又會怎麼對待原住民?) 取代,那到底是誰殘酷?

被消費的文化

文明化造就觀光行為

觀光是大多數人的娛樂,也因此造就服務業的產生。談談服務業與文明化的關係

這個新的公民身分的尊貴性,首先意味著華人社會本來以長幼輩分及遠近
親疏為基礎的傳統人際關係階序必須被鬆動,好讓尊貴的自豪自信得以越過這
些差異位置所包含的舉止規範和情感限制,而成為所有主體都可以近用的現代
情感特質。在這方面,第一個重要的結構性發展就是台灣產業結構劇變後的服
務業人際互動模式,以及隨之在日常生活中不斷重複的互動消費實踐,它們都
使得新規訓不再只是外加的強制和要求,而得以徹底融入主體的生活活動與內
在自我情感。

這深入探討可能要問一下何春蕤老師,總之身處服務業的情感,肯定是原住民們所無法理解的,一開始覺得他們好客,不知不覺地商業化他們,直到他們的好心被利用,才逐漸地被厭惡。

反思

當我們對外說出「我們台灣人」到底是指那些人?是活在這片土地上的所有人?那接下來的話就是共同意識嗎?正因為要對外證明我們是個國,才急切地想要讓所有活在這片土地上的人,至少有一個共同意志?

我們用更殘酷的方式生存,剝奪那些活在幕後的人的生存條件與資源,真的有比原住民文明嗎?追求文明結果,竟是雙面刃?

探討

在各國文化的核心目標不同時,它們對待原住民的方式也有所不同,到底是給予相同地位?還是給予空間適性發展?我想這牽涉到-到底有沒有必要活在「社會」牢籠,他們明明不用看處在強勢文化人們的臉色,自給自足活得很好,為何他們要踏入我們的文化?

也許以前原住民的人數與文化有關係,為了生存不得不離開原本的文化,背負著必須學習更多文化知識的壓力。這種不對稱的學習,真的造就我們欺壓原住民了嗎?

文化模式與人口承載量

造成必要的出走的主因。根據人口普查統計,至今原住民已經從日治時代的七萬多人暴增到五十多萬人,它們的生活習性支撐這麼多人嗎?

看待偏見

偏見有時也是一種讚美 。即使是你所認為不文明的舉動,不就是正因為做了你做不到的事情?

文化分工

唱歌、表演真的是唯一生存之道?原住民未來若要發展特色,難道唱歌表演就是唯一了嗎?在很多原住民歌手的興起下,就只能朝著同一個方向嗎?

學校教育

窮鄉僻壤的村落,書上這麼多內容壓根沒見過,為何而學?遵守什麼規矩?

補償條例

一個跨世代的心態,但要知道強勢文化下也有弱勢成員,而生存的價值是因為他們的需求而存在,有時給予環境正表示處於文明的鑑賞期。

生活教育

生活就是最好的教育,有人走得出去,也一定會有人走不出去,為了 部落 而走的民族精神?

器具演進

從人工到電動-難道有人畫畫一開始就學電繪嗎?沒什麼大驚小怪的,會電腦打字就不會寫字了嗎?

Read More +

計算幾何 - HW04

Chapter 7

7.1

Prove that for any n > 3 there is a set of n point sites in the plane such that one of the cells of Vor(P) has n−1 vertices

證明一個點個數 n > 3 的 Voronoi diagram,存在一個 cell 具有 n - 1 個頂點。

7.1

如圖所示,一個點放置在圓心,剩餘的 n - 1 個放置在圓周上。則中間的 cell 必然有 n - 1 個頂點。

7.3

Show that$\Omega (nlogn)$ is a lower bound for computing Voronoi diagrams by reducing the sorting problem to the problem of computing Voronoi diagrams. You can assume that the Voronoi diagram algorithm should be able to compute for every vertex of the Voronoi diagram its incident edges in cyclic order around the vertex.

7.3

證明 Voronoi diagram 的 lower bound$\Omega (nlogn)$,藉由 reduce 到 sorting problem。

關於 reduce 證明,將一個簡單、約束較少的問題 A,藉由一個合適的轉換,變成一個困難問題 B 的 subset,已知 A 的 lower bound,則 B 的 lower bound 至少與 A 相同。

  1. 假設排序 n 個整數$x_{1}, x_{2}, ..., x_{n}$
  2. 轉換成$(x_{1}, 0), (x_{2}, 0), ..., (x_{n}, 0)$ 將所有點放置在 x 軸上,並且額外增加一點$(\infty, 0)$。將 n + 1 個點找到 Voronoi diagram,對於$(\infty, 0)$ 的 cell 而言,恰好邊都是由另外 n 個點對應的 cell 構成 cell edge (相鄰)。假設儲存邊的順序為順或逆時針,則邊的順序等價排序結果。

最後如上圖所示,又已知轉換需要$O(n)$,sorting$\Omega (nlogn)$,則 Voronoi diagram 的 lower bound$\Omega (nlogn)$

7.5

Give an example where the parabola defined by some site$p_{i}$ contributes more than one arc to the beach line. Can you give an example where it contributes a linear number of arcs?

7.5

如上圖所示$p_{i}$ 拉出的拋物線 (parabola) 有可能提供多個弧 (arc)。(最左側的點提供 2 個弧)

一個點$p_{i}$ 存有的 arc 數量與 cell$p_{i}$) 的頂點數量線性相關。由 exercose 7.1 得到最多$O(n)$ 的頂點。同理 arc 數量最多$O(n)$

beach line 上的 arc 數最多為 Voronoi diagram 的 edge 數,又 Voronoi diagram 的 edge 最大數為$3n - 6$,也因此最多為$O(n)$

7.10

Let P be a set of n points in the plane. Give an$O(nlogn)$ time algorithm to find two points in P that are closest together. Show that your algorithm is correct.

Algorithm:

  1. 建造 Voronoi Diagram by fortune’s algorithm$O(nlogn)$
  2. 對於每一個 cell$p_{i}$) 檢查鄰居 cell$p_{neighbor}$),計算$distance(p_{i}, p_{neighbor})$ 的結果。Voronoi diagram 的 edge 數$3n - 6$,每一條 edge 檢查只需要$O(1)$$O(n)$

證明:每一個點所張開的 cell 只會與相鄰的 cell 最近,否則不符合 Voronoi diagram 的定義。

7.14

Show that the farthest point Voronoi diagram on n points in the plane has at most 2n−3 (bounded or unbounded) edges. Also give an exact bound on the maximum number of vertices in the farthest point Voronoi diagram.

  • 歐拉公式$v - e + f = 2$
  • 一個頂點至少三條邊。
  • farthest point Voronoi diagram 的最多有 n - 2 個頂點。
    • 對於每一個頂點而言,通過其相鄰 cell 對應的點的外接圓,其圓包含所有平面點。
    • 這種圓最多 n - 2 個。
  • 從隨機增量算法中得知,插入一個點時,最多增加一個 vertex (繞行時,會刪除對於 cell 相交兩個線段之間的所有 vertex,這種 vertex 至少一個,並且增加與線段的交點 1 個)。$v(3) = 1, v(n) = v(n-1) + 1 \text{ for } n > 3$
  • 考慮增加一個虛點,連接所有 unbounded edge $v - e + f = 2 \Rightarrow (n-2+1) - e + n = 2 \Rightarrow e = 2n - 3$

Chpater 9

9.2

The degree of a point in a triangulation is the number of edges incident to it. Give an example of a set of n points in the plane such that, no matter how the set is triangulated, there is always a point whose degree is n−1.

對於任意三角化的結果,總會有一個點的 degree = n - 1。

9.2

  • 此點一定能用一條線區隔所有剩餘點。
  • 剩餘 n - 1 個點,一定能滿足任兩點的連線不遮蔽其他的點。

example:n - 1 個點落在$y = e^{x}$ 上,且$x < p$,另外一點在$(p, q)$

9.4

Prove that the smallest angle of any triangulation of a convex polygon whose vertices lie on a circle is the same. This implies that any completion of the Delaunay triangulation of a set of points maximizes the minimum angle.

對於所有頂點共圓的凸多邊形,任何的三角化的最小角度都會相同。

  1. 任何三角形必然是圓上三點。
  2. 任何凸邊形的邊都會是一個三角形上的邊
  3. 三角形的邊都是圓的弦,並且對應角度正比弦長大小。
  4. 凸多邊形的最小弦長是多邊上的邊,又因一定會在三角形上,任何三角化一定包含這個最小角。

9.7

Prove that all edges of DG(Pr) that are not in DG(Pr−1) are incident to pr. In other words, the new edges of DG(Pr) form a star as in Figure 9.8. Give a direct proof, without referring to algorithm DELAUNAYTRIANGULATION.

對於新增加的邊$e$,只會與新加入的點$p_{r}$ 相連。

  • 從 Voronoi diagram 等價 Delaunay triangulation,加入點的 cell,不會使其他兩個 cell 從沒相鄰變成相鄰。

  • 對於$\Delta(p_{i}, p_{j}, p_{k})$ 之間加入$p_{r}$,由於$C(p_{i}, p_{j}, p_{k})$ 內部不存在任何點$C'(p_{i}, p_{r})$ (兩點當直徑),得到$C' \subseteq C$,且$C'$ 內部不存在任何點,確定$\bar{p_{i} p_{r}}$ 屬於 Delaunay 上。同理$\bar{p_{j} p_{r}}$$\bar{p_{k} p_{r}}$

  • 由於$\Delta(p_{l}, p_{i}, p_{j})$ 原本是 Delaunay 上,如果 flip$\bar{p_{i} p_{j}}$,得到$C(p_{i}, p_{r}, p_{l}) \subseteq C(p_{l}, p_{i}, p_{j})$$C(p_{j}, p_{r}, p_{l}) \subseteq C(p_{l}, p_{i}, p_{j})$,確定$\bar{p_{r} p_{l}}$ 屬於 Delaunay 上。

  • 也因此,對於增加的三角形進行檢查時,每次已經保證該三角形其中兩邊一定屬於 Delaunay 上,同時必然有$p_{r}$,flip 的邊一定會接到$p_{r}$ 上。遞迴得證。

9.11

A Euclidean minimum spanning tree (EMST) of a set P of points in the plane is a tree of minimum total edge length connecting all the points. EMST’s are interesting in applications where we want to connect sites in a planar environment by communication lines (local area networks), roads, railroads, or the like.

  1. Prove that the set of edges of a Delaunay triangulation of P contains an EMST for P.
  2. Use this result to give an O(nlogn) algorithm to compute an EMST for P.

對於歐幾里得距離的平面最小生成樹。

  1. 證明 EMST 的 edge set 被 Delaunay triangulation 的 edge set 包含。(參考 wiki)
    目標: every edge not in a Delaunay triangulation is also not in any EMST

    • 最小生成樹的性質:任何一個 cycle 上的最重邊將不會在最小生成樹中。
    • Delaunay triangulation: If there is a circle with two of the input points on its boundary which contains no other input points, the line between those two points is an edge of every Delaunay triangulation.

      對於鈍角三角形,最大邊必然不在 EMST 中,然而對於 Delaunay triangulation 性質,必須考慮他們兩點的 boundary (shared Voronoi edge) 是否存在。

      假設 p, q 之間沒有邊於 Delaunay,則對於任意通過 p, q 的圓都存在點 r 在圓內,從性質中發現 r 到 p, q 的距離一定小於 p q 之間的距離。同時在 EMST 中,p q r 三點會構成鈍角三角形,其中 p q 是最大邊,p q 之間必然沒有邊。

  2. 找到 EMST 的$O(nlogn)$ 算法
    Algorithm:

    1. 利用 Delaunay triangulation 找到所有邊$O(nlogn)$
    2. 最多有 3n - 6 條邊,利用 MST 中的 kruskal’s algorithm$O(ElogE)$
      3.$E = O(3n-6) = O(n)$,得到$O(nlogn)$ 的做法。

9.13

The Gabriel graph of a set P of points in the plane is defined as follows:
p q Two points p and q are connected by an edge of the Gabriel graph if and only if the disc with diameter pq does not contain any other point of P.

  1. Prove that DG(P) contains the Gabriel graph of P.
  2. Prove that p and q are adjacent in the Gabriel graph of P if and only if the Delaunay edge between p and q intersects its dual Voronoi edge.
  3. Give an O(nlogn) time algorithm to compute the Gabriel graph of a set of n points

Gabriel graph:任兩點之間為直徑的圓內若沒有其他點,則兩點之間有邊。

  1. 證明 subgraph 關係。
  • 根據 Theorem 9.6 (1) 任三點圓內$C(p_{i}, p_{j}, p_{k})$沒有其他點,但是$C(p_{i}, p_{j})$ 內部可能存有其他點 (如單純的 n = 3 的鈍角三角形)。找到$e_{p_{i}, p_{j}} \notin Gabriel \text{ but } e_{p_{i}, p_{j}} \in Delaunay$
    *$C(p_{i}, p_{j})$ 內部沒有其他點,則兩點之間必然有 shared Voronoi edge,符合 Theorem 9.6 (2)。得到 $\text{ if }e_{p_{i}, p_{j}} \in Gabriel \text{ , then } e_{p_{i}, p_{j}} \in Delaunay$,得證$g(P) \subseteq DG(P)$
  1. 如果$\bar{pq}$ 經過多個 Voronoi edge,則$\bar{pq}$ 上一點 x 滿足 $$\bar{xr} < \bar{xp}, \bar{xr} < \bar{xq} \\ \Rightarrow \angle rpx < \angle prx, \angle rqx < \angle xrq \text{(triangle)} \\ \text{let } \angle rpx = a, \angle prx = c, \angle rqx = b, \angle xrq = d \\ \Rightarrow a + b + c + d = 180^{\circ} \\ \Rightarrow c + d > 90^{\circ}$$

符合圓內角性質,點 r 一定在圓內,得證$e_{p_{i}, p_{j}} \notin Gabriel$

  1. 在 O(n logn) 時間內完成。
    Algorithm:

    1. 利用 Delaunay triangulation 找到所有邊$O(nlogn)$
    2. $e_{p{i}, p{j}} \in DG(P)$ 進行測試是否有點落在$C(p{i}, p{j})$$O(n)$

      只需要拿鄰居進行檢測,鄰居最多 2 個 (共邊的三角形)。

9.14

The relative neighborhood graph of a set P of points in the plane is defined as follows: Two points p and q are connected by an edge of the relative neighborhood graph if and only if

$d(p, q) \leq \underset{r \in P, r \neq p, q }{min} max(d(p, r), d(q, r)).$
  1. Given two points p and q, let lune(p,q) be the moon-shaped region p q lune(p,q) formed as the intersection of the two circles around p and q whose radius is d(p,q). Prove that p and q are connected in the relative neighborhood graph if and only if lune(p,q) does not contain any point of P in its interior.
  2. Prove that DG(P) contains the relative neighborhood graph of P.
  3. Design an algorithm to compute the relative neighborhood graph of a given point set.

整體而言類似 9.13。

  1. 若 p, q 之間沒有邊,則 $$\exists r : d(p, q) > \underset{r \in P, r \neq p, q }{min} max(d(p, r), d(q, r)) \\ \exists r : d(p, q) > d(p, r) \text{ and } d(p, q) > d(q, r)$$ AND 就是做交集操作,不知道該怎麼寫才好。
  2. 與 9.14 依樣畫葫蘆,只是$lune(p, q) \subseteq C(p, q)$,則更暗示$\text{ if }e_{p_{i}, p_{j}} \in G \text{ , then } e_{p_{i}, p_{j}} \in Gabriel$
  3. 速度是$O(n^{2})$,沒辦法單純看鄰居進行檢查。拿每一條邊進行 O(n) 窮舉。不過在分散式計算,整體是 O(n)。
Read More +

[通識] 文明的進程 Week 10

重大體悟

羞恥重要的性質是在行為舉止後對於 自我優越感下降 恐懼 ,個人害怕喪失他人的尊重,思考這些帶來的可能性,也就是羞恥情感!其實活得身分低下、與那些自認不同的人處於相同地位。

學了半學期羞恥,這時才發現那吞噬信心的巨獸- 羞恥 ,不知道何時開始,它就像常駐技能似的,不管睡著還醒著都沒有關閉的跡象,這樣活著像遊戲 BUG 似的存在,那麼地與眾不同。

也許,早在那年發現自我弱點時,就烙上那 奴隸的印記 ,不斷地想要遮掩身分的不同,隨時隨地都要小心祕密被發現,想到個人價值有可能在一夕崩落,羞恥感壟罩整個心頭。其實我就是那身分低下的奴,不斷地遮掩印記,卻試圖想要往那更高層爬去。

既然都爬到這,還不想崩落、還不想被發現,至少還要在某些人中存有價值,帶著罪惡感不斷輪迴,也因此走了自己最不想走的路,但是不這麼做,自我價值就在瞬眼之間消散。

如今,崩落假想也隨之成長,直到那再也無法遮掩自己的脆弱前,假想帶來的恐懼不斷地侵蝕我。

回過頭來

段考檢討

寫點與印象答案比較不同的,總之能想到自己很多是零分面向的作答,無知就是我的本體。

  • 為何 淡定 hold 住 的情感為何在中世紀比較沒有呢?
    中世紀的人必須野蠻,對人的關係不是 朋友就是敵人 ,任何一點猶豫將把自己處於不利地位,為了生存,這些克制自我的情感將成為阻礙。
  • 解釋 內心世界 為何而生?
    隨著文明化,人與人之間的關係相當重要,在 人際互動 的親密下,考慮遠程利益,不斷地盤算要做出甚麼樣的決策,才能最適應未來、現在的人際網路,也因此要表現出那衝突、矛盾的思緒都會在內心世界中。
  • 對於中古世紀以及現代教育對於 兒童教育 的方針有何基礎的不同?
    中世紀的兒童教育,兒童就是小大人,什麼都必須知道、什麼都能做,因為它們要趕快成為大人。相對於近代,防止被帶壞、很多不能學、不能知道,不斷地隔離成人的內容。
  • 為什麼機場配置的「紅外線水龍頭」高科技廁所是一個文明化的象徵?
    隔離人與人之間的接觸,同時也是在衛生觀念的防病、防疫措施。隔絕彼此已經作為一個文明化的指標。

本周課程

本周圍繞的主題為社會結構與人際關係,不過說是禮儀與社會結構之間交互關係也可,作為階級區隔,人與人之間所需的禮儀也會有所不同。

曾經說到階級流動與禮儀之間的關係,在不同階級下,人的生活型態不同,面對不同的環境就需要不同的禮儀,即使是在相同時空下,對人制宜也是相當重要的!

階級競逐

作為看待一個社會階級流動,正因為流動的存在,也會形成激烈的競逐,而作為競逐的項目也會隨著年代、國情不同而有所變化,從文憑、車款、養生、 … 都能見得。在傳統社會的世襲中,階級也許不太變化,權貴般的生活到了現代,如果把自己家境多有錢拿出來凸顯階級,也許還比不上一個有品味、氣質、風度的平民百姓。

你的強大若無法帶給別人恩惠,充其量就是個異類。

不過從印度婆羅門教、種姓制度看來,用了一個宗教藉口使得人們相信此生所為將決定下個人生的階級,某些手段利益看來,相當高明呢!社會看起來肯定相當安定,各盡其職。如果沒有太離譜的表現,制度當初為了血統純正的說法,就能達到目標。

結構改變

當社會結構改變時,帶動的是許多職業的消失。當然在科技的發展下,也不少職業消失,而這些人去了哪裡?又有甚麼樣的心理狀態改變?

曾想過自己一身技能,在一個事件動盪下一文不值嗎?接著又要何去何從,找到自我價值?

細看武士階級的年代,其實那段日子在早些時間都消失,他們練就一身武藝,卻沒有在年代中獲得需要、找到工作,不管是在西方騎士、東方武士都有相同的處境,即使後來在重要人士旁進行護衛工作,但身分地位上也有所轉變,至少在禮儀上也必須相對於在戰場上那樣的狂野,轉為平靜的心態。

在中國歷史角度看來,從諸侯分權到王權獨大,武力霸權帶來的壟斷、和平,卻也造成武士們再也沒有表現的機會,何處才有戰場讓咱們逞逞威風?每天面對帝王鞠躬盡瘁,哪適合咱們?也因此不少人從國民崇拜的英勇武士落魄到連下一餐都找不到,即便現在沒了戰場,也要秉持著武士精神度日!絕不能讓別人看到自己軟弱的地方!

講到這,講到動物也有此特性,再凶猛的動物即使自己受傷處於弱勢,若展現脆弱的一面,也會受到反撲。

在西方歷史中,最有印象的是具有領土的貴族們,當商人興起,開始擁有大把大把鈔票時,農地生產不及鈔票來得有價值,金錢觀念勝過於階級,貴族們也無法守住自己的農民,最後要倚靠皇宮的保護,最後遺失自己的自由。「 雖然窮,但我們自由。 」這一詞也在某些勵志的文章中見到,金錢的重要性還是看個人操守吧。

投票是什麼?「有錢有勢的人動員沒錢沒勢的人進行大規模支持活動」-老師一語,全堂竊笑。

到了現代,仍然有許多國家存有兩極化,例如 墨西哥 貧民窟,上網搜尋的結果,還真是一線之隔,可謂「 住得近、習相遠 」老師的意思可能不是這樣,在分工體系下,人們從自給自足轉變到相互依賴,開始有了密切交易,同時也帶來緊張氣氛。

達爾文獎:「讓自己愚蠢的基因不再自由地傳播出去」,對人類的演化做出了貢獻。亦有人認為,達爾文獎是用來記錄「那些在演化過程中走得最慢的人們」。

內心世界

在現在的人情交易所中,深思熟慮、自我克制、精確調整情緒成為交易所的基礎籌碼,只要拿著這些籌碼去,多少能搏得人情網路,同時了解人情網路的拓樸關係,有助於思考站於哪個地位進行支持,可謂拓樸學的二分圖、三分圖之類的關係呢!一個人改變關係,可能標染都要更動!

我們將會變成一個縝密分析的生物,就為了站在有利的位置上,不斷地將訊息解析,否則無法立於社會中。必須知道情感用事也無法撼動這個世界,世界道理不依個人意志運作。

作為這一點,如果一個人思考的太多,針對、多角式、深入剖分的思考會不會造成反應速度的延遲?意即聰明到跟笨蛋似的。

國人特有現象,在一般常理下,自己做出脫格行為將會為自己帶來羞恥,對於別人做的,則會身感難堪,但是我們似乎更進化了?會感到憎恨。

Read More +

自然語言處理 論文研讀 1

Introduction

語意分析涉及正反意見在文字語句中判定,因此必須使用多方視角看待問題與答案,這一點在之前,有人做過意見導向的資訊萃取、資訊摘要 (於文件、語句、片語)。語意分析通常分為三個階段, 校準 辨識 分類 所有已經讀取的文句。這篇論文探討文件分級 (document-level) 的分析,將會著重分析 特定類型的評論文件

第一個問題-極性分類 (polarity classification),對於目標決策正極性 (贊同) 或者是 負極性 (反對),最近也在擴大到中性文件的分類上,雖然研究成果相當多且廣,極性分類仍然是自然語言處理系統中重大的挑戰。

接著將會著重於語言學上的極性分類。在語言學中,建立一個高校的極性分類透過:

  • high order n-grams
  • 複合形容詞,例如 happy 被視為正,而 terrible 視為負面。
  • 詞彙的相依關係
  • 來自於中立文件中所描述的詞組

… 本文略

主要是極性分類,反映正反兩方兩種評論,為了增加精準度,其一種方法把單純闡述事實的評論去除、以及在中性評論用的用詞特別處理,接著對於形容詞與關聯名詞做統計,確保面向的評論對象是所需。

至於 n-gram 部分,有說明到 n 越大,將會造成模糊範圍增加,這樣一來其極性價值就會被削減,對於精準度是會掉的,只用 n = 2 好不好?他說他複合使用 n = 2 和 n = 3 將精準度提升,看到所謂顯著 2% 上升,似乎跟誤差無仿。

Read More +

[通識] 文明的進程 Week 9

心得

請閱讀 梁文道:媚俗,並寫出:你覺得台灣媒體中最常出現哪些情感字眼?反映了怎樣的情感專制呢?(100字)

文章中描述有關 激動 動情 兩字的使用,呈現一種媚俗的表現,

媚俗(德語:Kitsch)是一種被視為次等的視覺藝術形式,對現存藝術風格欠缺品味地作複製,又或是對已獲廣泛認同的藝術作毫無價值的模仿。
媚俗這個概念最初所描述的一類藝術作品,是對19世紀在美學上傳達誇張的傷悲和情緒的藝術手法(例如通俗劇)的一種回應,所以,「媚俗藝術」和「傷感藝術」有密切關係。

那篇文章是在 2010 年寫的,至今也有 4 年多的時間,而現今正在選舉當頭,而在經歷食安風暴的那段日子,新聞中最常出現的一詞為 痛批 ,這一詞是由新聞媒體創造出來的,在其他文本中是沒有任何中文字詞解釋。

其實這一詞等同於 回應 ,但是又增添了情感上的強化,呈現一種委屈、於心不忍的回應,有一種 明明對你這麼好,為什麼你居然這麼對我 。儘管當事者並沒有這樣的情感,但仍然是作為為某些族群發聲的言論,亦或是一種包裝罵人的態度。

越來越少見到苛責、辱罵、… 等,一種單方面說明對方不好之處, 痛批 一詞給予發言人背景、地位,讓人覺得他說話必然有其理由、逼不得已說出這樣的話來。

直接地情緒化辱罵的發言,都將用 痛批 來包裝過於單一情緒化不理智的發言,也就是課程講的內容,我們再也無法直視情緒,任何不理智的情緒都必須被美化成另外一種較為平靜的情感。

Read More +

[通識] 文明的進程 小考集

好幾題都 0 分,也許只是相性不合。而我也只是寫寫我的回答,沒有什麼標準答案。

Week 1

  1. Brad 小學時的校長做了一件甚麼事情讓 Brad 終身難忘?
    讓 Brad 參加音樂會,在音樂會的最後上台自白疾病的原因與如何面對,受到同學們的認同與理解。

  2. Brad 的父親最後幫學校圖書館建書櫃,還送 Brad 甚麼當作和解的禮物?
    一頂工地安全帽。

  3. Brad 接電話時為什麼總是先說自己養了狗?
    因為妥瑞症引起的聲音有如狗吠一般,先避免對方猜疑發生了什麼。

  4. Brad 說他也有閱讀困難,是怎麼樣的困難?
    無法控制自己的脖子不時擺動,使得無法長時間專注於書本內容。

  5. Brad 對於進入那些公共場合有所顧忌?為什麼?
    圖書館、教會、電影院、音樂會。因為那而的人們必須保持固定的儀態和禮貌。

Week 2

  1. 哪個特質不屬於現代心靈:(1) 顧忌他人觀感 (2) 喜怒形於色 (3) 觀察盤算對方。
    (2) 喜怒形於色。(1)(3) 都有著抑制自我生物本能、顧及他人的模式,(2) 則沒有。

  2. 中世紀餐桌上最不常見的餐具是? (1) 主餐盤 (2) 刀子 (3) 叉子
    (3) 叉子。刀子與主餐盤為餐點必備的工具和器材,而叉子是用來區隔他人食物而存在,當時物質不豐裕的情況下,算是奢侈地存在。

  3. 為什麼 Erasmas 在禮儀書中判斷「用餐時胡吃海塞」是鄉巴佬的行為?
    原本作答為 有如飢餓的野獸,為了區隔人與野獸的差別。 0 分
    行為不得體,沒有顧及他人的觀感,鄉巴佬總是做這些事情。(應該類似於這種回答?)

  4. 人際互動的「文明化」如何有助於科學研究方法的發展?
    原本作答為 文明化的互動反應物質生活與當時文化的流行,是一個直接的證據。 0 分
    人際互動的行為反應社會階級結構,藉此了解結構進行研究。(應該類似於這種回答?)

  5. 越是自命文明的人就越容易對他人的舉止感到「不舒服」為什麼?
    原本作答為 因為認為禮儀與自己相同才算文明,舉止不同的他人只會像野獸。 0 分
    階級高低的差別反應在舉止,因此在對於不同階級的人感到厭惡,也等同於對別人行為感到不舒服。

Week 3

  1. 中世紀貴族用餐最可能出現的菜色是:牛排、無骨鴨胸肉、全羊?
    全羊。當時還沒有食物幕後處理的概念,之後才有避見死相的道德感。

  2. 中世紀禮儀最不可能反映的是:身分階級、個人偏好、家庭背景?
    個人偏好。當時禮儀與階級有關,不會涉及強調個人。

  3. 文藝復興禮儀書最不可能說的是:不可粗俗、注意衛生、迴避不雅?
    原本作答為 衛生是後期科技進步,才用衛生理由取代粗俗的理由。 0 分
    注意衛生。當時講就是顧及別人,從不可粗俗、迴避不雅中可以發現都在顧及別人的觀感。注意衛生是在民主平等後,階級不重要,顧及自己才更有約束力。

  4. 就食物的準備而言,為何西方人覺得中華文化的飲食方式很「文明」?
    因為食物會經過多道手法,讓食用時看不出原貌,並且便於入口。不用吐骨。

  5. 這兩張「最後的晚餐」,哪張場景看起來年代較早?你的理由?
    第二張較早,因為沒有個人的餐具。晚期的餐具才比較普及。

    居然有藝術類型學生答題,根據畫風的不同來判斷年代 … 等,給這專業跪了,不過想必是 0 分

Week 4

  1. 文藝復興時期常常提醒人們「天使無所不在」,目的是什麼?
    在不需要顧及他人的需求時,仍要遵守禮儀的理由。

  2. 禮儀書說,便後從廁所回到社交場合時,不能讓人看出洗過手,為什麼?
    會讓場合的人因濕淋淋的手而想起廁所的那些汙穢。(備註:早期甚至希望不洗手。)

  3. 台北捷運地上劃的排隊等候線,其實不是 高度文明 的標誌,為什麼?
    因為需要外物的約束,如何不需要線就能遵守,表示規則內化,那是更文明。

  4. 為何用禮儀書來提升自己氣質的人,反而暴露自己階級地位不高?
    原本作答為 禮儀書的存在是在階級流動的幫手,教導低階級融入上層階級。 0 分
    教導階級高的社為人士的行為模式,正因為需要學習,才表示自己不處於上層階級。

  5. 就 Elias 而言,為什麼社會越文明,其兒童與成人之間的差距就越大?
    成人的禮儀要求越高,兒童在短時間內無法對百年禮儀融會貫通,而這只是相對差距。

Week 5

  1. 在課程 ppt 中,老師用多重比基尼泳裝的貓咪來嘲諷什麼?
    原本作答為 沒有必要這麼遮遮掩掩,一個母親的象徵竟被當作情色。 0 分
    過度地遮掩身體、過度道德化的結果。

  2. 以下何者 不是 社會歷史發展的結果?(1) 哈欠 (2) 洗手 (3) 掩鼻 (4) 遮體。為什麼?
    打哈欠一直都是生物自然反應。其餘皆為後天環境影響而做的事情。但是打哈欠用手遮住也算是後天教育而成。

  3. 為什麼當前的清涼穿著其是 不是 世風日下,而是文明化成功的象徵。

    世風日下:社會的風俗習慣日漸澆薄,每況愈下。(答題時根本不知道這個詞什麼意思。)

    原本作答為 因為向別人暴露身體原本是羞恥的事,面對自己身體不怕外人注目,是心靈上的昇華,外表遮掩不是限制。 0 分 (生物本能不就是要遮掩自我弱點嗎?)
    因為環境影響,代表治安好,不會有鹹豬手的人出現,因此才敢做出清涼穿著。

  4. 「人生:就是成人的生活」這個信念對於中世紀的兒童教育有何引響?
    原本作答為 讓兒童失去原本應有的童年,更早步入成人階段,沒有純真無潔的思想,都被羞恥的教育而想太多什麼不能做的事情。 0 分
    很多事情不能去做、不能去想。因此很多事情也不知道後果的嚴重性。

  5. 文明的 硬體技術 可以使得羞恥情感固定下來,請舉一個例子說明。

    那時卡在硬體設備與軟體技術,兩個弄在一起時,一直想不到那是什麼鬼,於是在被迫交卷前亂填答案。結果只是單純講硬體設備。

    廁所。利用大量的裝飾、氣氛,來隔絕與生物的排泄行為的聯想。

結語

被助教寫了 沒掌握本課程關鍵重點 沒有吸收 。我不否認,好幾堂課還在想算法分析。

Read More +

自然語言處理 - HW02

編譯環境

Dev-C++ 5.6.3

作業內容

給予 5000 筆的亞馬遜書店評論,每一個評論都已經分類好,總共有五種類型的書評,分別為 book, dvd, health, music, 以及 toys_games

利用這 5000 筆分類好的書評寫一個分類器,接著讀入另外測試資料,測試資料每一個書評有既定分類,使用分類器判斷是否符合既定分類,分別計算對於每一種分類書評的準確度 (Accuracy) 和精準度 (Precision)。

  • 準確度:接近正確答案的機率,在這裡可以理解為分類出來的結果等於實際結果的機率。
  • 精準度:測試結果一致的機率,在這裡可以理解為分類出來的結果中,實際上是正確的機率。(是否集中於某個實際結果)

還有一個混用準確度和精準度的概念 f,假設準確度為 R,精準度為 P。

$F = \frac{1}{\alpha \frac{1}{P} + (1 - \alpha) \frac{1}{R}} = \frac{(\beta^{2} + 1) PR}{\beta^{2}P+R}$

所謂的 F1 定義為$\beta = 1, \alpha = 1/2$,最後得到$F = 2PR / (P+R)$

關於輸入輸出資料

  • gold_standard.xml : 黃金標準的 5000 筆評論
  • test_outcome.xml :原本認為是 測試用的反饋資料,用來檢測寫的分類器好不好。 後更正為助教的分類器跑出來的結果。

通常會拿到一大筆資料,經驗上 3/4 的資料會拿來訓練,剩下 1/4 會拿來檢測。也就是資料量於 3 : 1,至於一段資料怎麼切分有很多方式,可以擷取中間一段的 1/4 … 等都可以。

看一下 xml 格式

gold_standard.xml
1
2
3
4
5
6
7
8
<RDF rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Text category="music">Forget the fact that despite the grumbling
about today's "music" ...</Text>
<Text category="health">Printed all over the box are the words
"with infrared heat". ...</Text>
<Text category="music">I just finished seeing the movie and loved
the song at the end ...</Text>
...

看起來最多兩層,如果不用插件來解析 XML,遞迴處理寫一個 parser 應該不是問題。

於是就這麼蠻幹 XML parser 下去,仔細查閱一下給定的 XML,會發現文件中有 &amp;amp;&amp;amp;quot; 的確在 XML 的元素 content 不會出現 >, < … 等字元,就跟 HTML 的 character entities 一樣都需要被替換成特殊的顯示規格。但真沒有見過上述的那兩個格式,仔細檢查發現應該是對應 and 字串和 " 引號。解析完作 replace 動作。

回過頭來看這次所需要的公式:

$$P(c) = \frac{N_{c}}{N} \\ P(w|c) = \frac{count(w,c)+1}{count(c)+|V|} \\ P(c|s) = P(c) \prod P(w_{i}|c)$$

參數說明:

$P(c)$ 表示該分類佔有群體的機率,也就是在 5000 筆評論中,分類 c 佔有百分比$N_{c}$ 表示有多少筆評論屬於 c 分類$N$ 表示評論筆數,這裡已知$N = 5000$ $P(w|c)$ 單詞 w 在分類 c 的出現機率為何$count(w,c)$ 單詞 w 在分類 c 中出現的次數$count(c)$ 屬於 c 分類中字詞總數 (評論總共有多少字)$|V|$ 分類 c 中使用的單詞集合大小。
*$P(c|s)$ 評論句子 s 在分類 c 的機率為何。

隨後找$P(c|s)$ 機率值最大作為分類依準。

最後要找到分類是否正確,對於每一種分類 c 會得到表格

實際結果\分類結果 Classifier no Classifier yes
Truth no true negative(TN) false positive(FP)
Truth yes false negative(FN) true positive(TP)

準確度 R 意即:TP / (TP + FN)、精準度 P 意即:TP / (TP + FP)

對於 Micro-average 和 Macro-average 的計算,Micro 和 Macro 概念上我理解程式幾何平均和算數平均的概念,Micro 會把每個分類 c 的表單結果累加到一個表格,隨後按照一般分類算法計算準確和精準度,而 Macro 則是將每個分類算完的結果取算術平均。

代碼

傻傻地用分類器判斷與助教的決策比較的運行結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
process gold_standard.xml ...
statistics model built ...
--------------------+----------
book | 1000
dvd | 1000
health | 1000
music | 1000
toys_games | 1000
--------------------+----------
process test_outcome.xml ...
testing test_outcome.xml ...
| AC\Assign| book| dvd| health| music|toys_games|
| book| 892| 29| 17| 9| 25|
| dvd| 22| 829| 16| 48| 41|
| health| 30| 19| 975| 46| 177|
| music| 5| 13| 12| 870| 28|
|toys_games| 10| 16| 43| 21| 807|
book
p :0.9301355579
r :0.9176954733
f :0.9238736406
dvd
p :0.9150110375
r :0.8671548117
f :0.8904403867
health
p :0.9172154280
r :0.7818765036
f :0.8441558442
music
p :0.8752515091
r :0.9375000000
f :0.9053069719
toys_games
p :0.7486085343
r :0.8996655518
f :0.8172151899
Micro-average
p :0.8746000000
r :0.8746000000
f :0.8746000000
Macro-average
p :0.8772444134
r :0.8807784681
f :0.8790078886
--------------------------------
Process exited after 6.545 seconds with return value 0

後來發現是公式理解錯誤

  • 真陽性 (TP, true positive)
    正確的肯定。又稱:命中 (hit)
  • 真陰性 (TN, true negative)
    正確的否定。又稱:正確拒絕 (correct rejection)
  • 偽陽性 (FP, false positive)
    錯誤的肯定,又稱:假警報 (false alarm),第一型錯誤
  • 偽陰性 (FN, false negative)
    錯誤的否定,又稱:未命中 (miss),第二型錯誤

準確度就是在正確答案中找誤判,而精準度就是在判斷正確下找錯誤。

後來實驗用 gold_standard.xml train 和 test,運行結果為

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| AC\Assign| book| dvd| health| music|toys_games|
| book| 950| 7| 15| 3| 25|
| dvd| 7| 895| 33| 21| 44|
| health| 1| 0| 984| 1| 14|
| music| 1| 3| 15| 968| 13|
|toys_games| 0| 1| 16| 1| 982|
book
p :0.9906152242
r :0.9500000000
f :0.9698825932
dvd
p :0.9878587196
r :0.8950000000
f :0.9391395593
health
p :0.9256820320
r :0.9840000000
f :0.9539505574
music
p :0.9738430584
r :0.9680000000
f :0.9709127382
toys_games
p :0.9109461967
r :0.9820000000
f :0.9451395573
Micro-average
p :0.9558000000
r :0.9558000000
f :0.9558000000
Macro-average
p :0.9577890462
r :0.9558000000
f :0.9567934893

當然不能拿相同的 train 和 test data 來用,但是也明顯地發現,這個 model 仍然沒有辦法達到很高純度的結果,在部分比例中也只達到 90% 的精度。

那有沒有一種情況,我們將六種分類的共同交集字符給去除?這樣的效果會不會比較好呢?例如常用的 Ithinkit … 等,在 model 中直接無視這些常用字集的效果如何呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void custom() {
set<string> common;
int first_set = 1;
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
set<string> s;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
s.insert(jt->first);
if (first_set) common = s, first_set = 0;
else {
set<string> C;
set_intersection(common.begin(), common.end(), s.begin(), s.end(), inserter(C, C.begin()));
common = C;
}
}
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
for (set<string>::iterator jt = common.begin();
jt != common.end(); jt++)
R.erase(*jt);
int cnt = 0;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
cnt += jt->second;
count_category[it->first] = cnt;
}
}

上述代碼為將每一個分類的字集與共同交集,並且將共同交集從每個分類中移除,同時將記數重新統計。根據實驗結果,很多分類都直接噴掉,也許是專有名詞使用的量太少,雖然每個字集仍然有上千上萬不等,但是在分類效應上某些分類完全消失。效果差到不行,所以就直接無視吧。或者提供點意見吧。

回過頭來解一下關於作業內容,其實作業內容可以化簡為:

輸入只有一組測資,該組測資會有數行,每一行上會有兩個分類結果,第一個分類結果為標準答案,第二個分類結果為根據模型運算的結果。對於測資輸出每一個分類的準確度、精準度以及 f1 的數據結果。

兩個輸入檔案可以壓縮為

Input

1
2
3
4
5
6
7
5000
music music
book health
music music
toys_games book
music music
... here are more rows

很明顯地,第二個評論中,誤把 book 類型判斷成 health。

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| AC\Assign| book| dvd| health| music|toys_games|
| book| 907| 25| 48| 7| 13|
| dvd| 35| 873| 43| 24| 25|
| health| 10| 2| 932| 11| 45|
| music| 9| 46| 56| 865| 24|
|toys_games| 11| 10| 168| 21| 790|
book
p :0.9331275720
r :0.9070000000
f :0.9198782961
dvd
p :0.9131799163
r :0.8730000000
f :0.8926380368
health
p :0.7473937450
r :0.9320000000
f :0.8295505118
music
p :0.9321120690
r :0.8650000000
f :0.8973029046
toys_games
p :0.8807134894
r :0.7900000000
f :0.8328940432
Micro-average
p :0.8734000000
r :0.8734000000
f :0.8734000000
Macro-average
p :0.8813053583
r :0.8734000000
f :0.8773348714
--------------------------------
Process exited after 1.736 seconds with return value 0

答案算出來當然跟助教一下啊,知道什麼是 sample output 嗎?在 ACMer 的眼中,代表根據算法不同,答案也許會有誤差,或者是測資不同造成答案不同。而 sample output 通常告訴我們的是輸出格式與可能情況,而非測資的正確答案。

我就是很笨,無法理解這個世界。不知道那檔案是有序對應,看到 attribute 名稱 name 一樣,內容 content 不一樣就自動補完無法理解的英文部分,而沒有去看 tag 中 inner content 內容是相同的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#include <stdio.h>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <sstream>
#include <math.h>
#include <ctype.h>
#include <string>
#include <string.h>
#include <set>
#include <algorithm>
using namespace std;
class XMLParser {
public:
struct Node {
string tag_name, content;
map<string, string> attr;
vector<Node> child;
};
Node root;
XMLParser(string text = "") {
sin << text;
root = Node();
build(root, "");
}
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
string html2text(string s) {
string ret(s);
replaceAll(ret, "&amp;amp;quot;", "\"");
replaceAll(ret, "&amp;amp;", "and");
return ret;
}
private:
stringstream sin;
void getTagContent(Node &u) {
char c, div;
while (sin.get(c)) {
if (c == '<') {
while (sin.get(c) && isspace(c));
u.tag_name = c;
while (sin.get(c) && c != '>' && !isspace(c))
u.tag_name += c;
if (c == '>') return;
while (true) {
while (sin.get(c) && isspace(c));
if (c == '>') return;
string a = "", b = "";
a += c;
while (sin.get(c) && !isspace(c) && c != '=')
a += c;
while (sin.get(c) && (isspace(c) || c == '"' || c == '\'')) div = c;
b += c;
while (sin.get(c) && !isspace(c) && c != div)
b += c;
u.attr[a] = b;
}
return;
}
}
}
int build(Node &u, string last) {
getTagContent(u);
if (u.tag_name == last)
return 0;
while (sin.peek() != EOF && sin.peek() != '<') {
char c;
sin.get(c);
u.content += c;
}
u.content = html2text(u.content);
while (sin.peek() != EOF) {
while (sin.peek() != EOF && isspace(sin.peek()))
sin.get();
if (sin.peek() == '<') {
u.child.push_back(Node());
if (!build(u.child[u.child.size() - 1], "/" + u.tag_name)) {
u.child.pop_back();
break;
}
}
}
return 1;
}
};
class StatsModel {
public:
map<string, map<string, int> > categories; // count(w, c)
map<string, int > commentCount; // N_{c}
map<string, int > count_category; // count(c)
map<string, map<string, int> > judgeTable;
int N, V;
int microtable[2][2]; // [truth 0:1][classifier 0:1]
StatsModel() {
N = V = 0;
memset(microtable, 0, sizeof(microtable));
}
vector<string> normalSentence(string content) {
vector<string> w;
stringstream sin(content);
string token;
while (sin >> token) {
token = igntrim(token);
token = str2lower(token);
if (token.length() > 0)
w.push_back(token);
}
return w;
}
void recordJudge(string truth, string classifier) {
judgeTable[truth][classifier]++;
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
int t = (it->first == truth);
int c = (it->first == classifier);
microtable[t][c]++;
}
}
string judgeComment(string category, string content) {
vector<string> w = normalSentence(content);
double Pc, P;
double maxPwc = - 1e+30;
string chooseClass = "";
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
Pc = (double)it->second / N;
P = log(Pc);
map<string, int> &R = categories[it->first];
int count_c = count_category[it->first], count_w_c;
for (int i = 0; i < w.size(); i++) {
count_w_c = 0;
if (R.find(w[i]) != R.end())
count_w_c = R[w[i]];
P += log((double) (count_w_c + 1)/ (count_c + R.size()));
}
if (P > maxPwc)
maxPwc = P, chooseClass = it->first;
}
recordJudge(category, chooseClass);
return chooseClass;
}
void addComment(string category, string content) {
commentCount[category]++, N++;
map<string, int> &S = categories[category];
vector<string> w = normalSentence(content);
for (int i = 0; i < w.size(); i++)
S[w[i]]++;
count_category[category] += w.size(), V += w.size();
}
string igntrim(string s) {
while (s.size() > 0) {
if (isspace(s[0]) || s[0] == '.' || s[0] == ','
|| s[0] == '!' || s[0] == '"' || s[0] == '\'')
s = s.substr(1);
else {
int t = s.length();
if (isspace(s[t-1]) || s[t-1] == '.' || s[t-1] == ','
|| s[t-1] == '!' || s[t-1] == '"')
s = s.substr(0, t-1);
else
return s;
}
}
return s;
}
string str2lower(string s) {
for (int i = 0; i < s.length(); i++)
s[i] = tolower(s[i]);
return s;
}
void custom() {
set<string> common;
int first_set = 1;
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
set<string> s;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
s.insert(jt->first);
if (first_set) common = s, first_set = 0;
else {
set<string> C;
set_intersection(common.begin(), common.end(), s.begin(), s.end(), inserter(C, C.begin()));
common = C;
}
}
for (map<string, map<string, int> >::iterator it = categories.begin();
it != categories.end(); it++) {
map<string, int> &R = it->second;
for (set<string>::iterator jt = common.begin();
jt != common.end(); jt++)
R.erase(*jt);
int cnt = 0;
for (map<string, int>::iterator jt = R.begin();
jt != R.end(); jt++)
cnt += jt->second;
// printf("%d -> %d\n", count_category[it->first], cnt);
count_category[it->first] = cnt;
}
// printf("%d\n", common.size());
}
void print() {
printf("%-20s+%10s\n", string(20, '-').c_str(), string(10, '-').c_str());
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
printf("%-20s|%10d\n", it->first.c_str(), it->second);
}
printf("%-20s+%10s\n", string(20, '-').c_str(), string(10, '-').c_str());
}
void report() {
// print <judge table>
printf("|%10s|", "AC\\Assign");
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++)
printf("%10s|", it->first.c_str());
puts("");
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
printf("|%10s|", it->first.c_str());
for (map<string, int>::iterator jt = commentCount.begin();
jt != commentCount.end(); jt++) {
printf("%10d|", judgeTable[it->first][jt->first]);
}
puts("");
}
// homework format
// recall: fraction of docs in class i classified correctly
// precision: fraction of docs assigned class i that are actually about class i
const double beta = 1;
double micro_r = 0, micro_p = 0, macro_r = 0, macro_p = 0, f1;
for (map<string, int>::iterator it = commentCount.begin();
it != commentCount.end(); it++) {
double recall = 0, precision = 0, f1 = 0;
int sumr = 0, sump = 0;
for (map<string, int>::iterator jt = commentCount.begin();
jt != commentCount.end(); jt++) {
sumr += judgeTable[it->first][jt->first];
sump += judgeTable[jt->first][it->first];
}
recall = (double) judgeTable[it->first][it->first] / sumr;
precision = (double) judgeTable[it->first][it->first] / sump;
f1 = (beta * beta + 1) * precision * recall / (beta * beta * precision + recall);
macro_r += recall, macro_p += precision;
printf("%s\n", it->first.c_str());
printf("%9s :%.10lf\n", "p", precision);
printf("%9s :%.10lf\n", "r", recall);
printf("%9s :%.10lf\n", "f", f1);
}
// for (int i = 0; i < 2; i++, puts(""))
// for (int j = 0; j < 2; j++)
// printf("%5d ", microtable[i][j]);
// [truth 0:1][classifier 0:1] = { {TN, FP}, {FN, TP} }
micro_r = (double) microtable[1][1] / (microtable[1][1] + microtable[1][0]); // TP / (TP + FN)
micro_p = (double) microtable[1][1] / (microtable[1][1] + microtable[1][0]); // TP / (TP + FP)
f1 = (beta * beta + 1) * micro_p * micro_r / (beta * beta * micro_p + micro_r);
printf("%s\n", "Micro-average");
printf("%9s :%.10lf\n", "p", micro_p);
printf("%9s :%.10lf\n", "r", micro_r);
printf("%9s :%.10lf\n", "f", f1);
macro_r /= commentCount.size();
macro_p /= commentCount.size();
f1 = (beta * beta + 1) * macro_p * macro_r / (beta * beta * macro_p + macro_r);
printf("%s\n", "Macro-average");
printf("%9s :%.10lf\n", "p", macro_p);
printf("%9s :%.10lf\n", "r", macro_r);
printf("%9s :%.10lf\n", "f", f1);
}
};
int main() {
ifstream fin("gold_standard.xml");
string xml = "", line;
while (getline(fin, line))
xml += "\n" + line;
printf("process gold_standard.xml ...\n");
XMLParser xmlDoc(xml);
StatsModel statsModel;
printf("statistics model built ...\n");
for (int i = 0; i < xmlDoc.root.child.size(); i++) {
string a = xmlDoc.root.child[i].attr["category"],
b = xmlDoc.root.child[i].content;
statsModel.addComment(a, b);
}
statsModel.print();
// statsModel.custom();
ifstream tin("test_outcome.xml");
xml = "";
while (getline(tin, line))
xml += "\n" + line;
printf("process test_outcome.xml ...\n");
XMLParser testDoc(xml);
printf("testing test_outcome.xml ...\n");
for (int i = 0; i < testDoc.root.child.size(); i++) {
statsModel.recordJudge(xmlDoc.root.child[i].attr["category"], testDoc.root.child[i].attr["category"]);
}
statsModel.report();
return 0;
}
Read More +

[通識] 文明的進程 Week 6

公私領域的分裂,在不同的場合下,擁有的心理、情緒反應會有所不同。在某些場合 渴望愉悅 是必要的行為,抑制住反而有失禮儀。相反地, 否認愉悅 也是有場合是必須的。例如在家裡與在社交場所,在家裡可以因為有家人關係,表現得自然不過,如果什麼都抑制住,反而稱不上家人相處。而在社交場所,即使討厭一個人,也不能在臉上表現出來。

比中指 辱罵別人其實是很文明的舉止,因為並沒有實施暴力行為,是一種克制自我的行為。然而,比中指仍然稱不上是好的禮儀,但已經進步很多。

裸體代表的就是 自然 本相 ,查看其背後的涵義,這在很多理論上作為依據-抗議的主旨。 求自然 求真相

關於小組報告的大綱如下:

  • 為什麼主題有關文明化?
  • 看時間軸中,行為是怎麼形成的?
  • 約束人們做了哪些事情,思考了那些事情。
  • 約束-身分-環境,三者彼此之間的相互關係。
  • 在不同的時空背景下,又有什麼差別?是甚麼原因造成的?

特別注意報告要點:

  • 請說大家沒想過的,觀眾都等著你給的 surprise

本周報告

無處不在的文明教育(家庭、學校、公共空間與媒體)

家庭

談什麼?不談什麼?

首先是性教育、生與死,小時候不談這些,但隨著長大成人就會依依序序跟家裡長輩們談談,關於性、生後事 … 等一些比較嚴肅的話題。

看不看 A 片?寫不寫遺書?A 片的命名如何文明化?

PTT A片取什麼名字最安全?
大陸尋奇、舌尖上的日本、微積分、幫爸爸抓的、流體力學、日文初級音聽檢定 … 等

最後老師特別贊助:取名為 文明的進程

學校

環保意識的培養?

其實我認為學校文明教育從蔣公那時開始到現在就很有不同,學三民主義的課程到現在九年一貫課程,中間經歷了相當多的轉變。老一輩的人三民主義的日子,學著書上的精神,造就他們的價值觀。而我們學習到的只有宏觀歷史,而少了點歷史仇視,沒有嚮往開國元老,敬重政治人物的努力。

小學從品德教育開始,在國中之後便不怎麼有時間上這些,原本有 上,變成用條例規範,逐漸地,我們可以開始閱讀 規則 並且知道要遵守。

公共空間與媒體

媒體很有趣,從小看到大,可以說是一個群體訓練場,看著畫面猜著下面給的標題是否符合,已經快要變成一場遊戲,只要八九不離十,就有十足把握出門跟別人談談這些。在一個單向的管道中,從媒體為何而來?人們疏離開始說起,又或者不想跟別人談這個主題,需要一個媒介替你轉達!

Read More +

計算幾何 - 期中考練習

  1. (15 points total)
    a. (10 points) Given a set of points that are presorted by their x-coordinate value, provide an algorithm that computes the convex hull of these points in O(n).
    b. (5 points) If more than 2 points are possibly on an edge of convex hull, explain briefly how your algorithm handles this case.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int cross(Pt o, Pt a, Pt b) {
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
int monotone(int n, Pt p[], Pt ch[]) {
sort(p, p+n);
int i, m = 0, t;
for(i = 0; i < n; i++)
while(m >= 2 && cross(ch[m-2], ch[m-1], p[i]) <= 0)
m--;
ch[m++] = p[i];
for(i = n-1, t = m+1; i >= 0; i--)
while(m >= t && cross(ch[m-2], ch[m-1], p[i]) <= 0)
m--;
ch[m++] = p[i];
return m - 1;
}

會將三點一線段的中間那一點替除掉,直到一個線段上只經過兩個點。

  1. (20 points total)
    a. (5 points) What are the types of event points in the plane sweep algorithm for line segment intersection problem?
    b. (10 points) Explain briefly when each type of event points is inserted to the event queue. Create a simple example (with 2 line segments) to demonstrate how it works.
    c. (5 points) When will the plane sweep algorithm for line segment intersection problem not suitable? Give a quantitative answer (i.e., describe your answer by using the Big-O notations). In addition, why is applying plane sweep algorithm on subdivision overlay in general a good idea?

  • 掃描時遇到的三種情況
    1. 碰到開始的左端點 (加入此線段)
    2. 碰到結束的右端點 (移除此線段)
    3. 碰到線段之間的交點 (預測下個最近的相交點後,將其包含這個交點線段移除後,重新加入)
  • 很簡單的,請參考上述三種情況繪製。
  • 當交集的數量在$\Theta(n^{2})$ 的時候,複雜度是$\Theta(n^{2}log n)$,還不如直接窮舉任兩個線段計算交點$\Theta(n^{2})$,就算要去重複,常數也比掃描線算法來得低。
  1. (20 points total)
    a. (10 points) Draw a simple polygon with 4 different types of vertices. Mark each vertex with its type. In addition, which two out of these 4 types are NOT allowed in a y-monotone piece?
    b. (5 points) Mark the “helper” for each of the vertices in your part (a) simple polygon that are not allowed in a y-monotone piece.
    c. (5 points) The triangulation of a y-monotone piece (with n vertices) can be done in linear time. Explain briefly why.

  • start, split, end, merge, regular vertex 明明有五種!
  • split, merge vertex 不符合 y-monotone piece
  • 加入 helper,對於 split 而言要往下找 split 或者是 regular vertex 相連,對 merge 而言要往上找 merge 或者是 regular 相連。
  • 因為往左可以根據維護凹性在 O(n) 時間內完成三角化,同理往右走訪。
  1. (20 points total)
    a. (5 points) What is the worst-case time complexity for the algorithm that solves the 2-dimensional linear programming problem?
    b. (5 points) Simplex algorithm is known to solve the linear programming problem in Operational Research. Why don’t we simple apply Simplex algorithm for the 2-dimensional linear programming problem?
    c. (10 points) Let (H, c) be a linear program. We number the half-planes h1, h2,…, hn. Let Hi be the set of the first i constraints, together with the special constraints m1 and m2 (i.e., the bound so that the solution space is limited). Let vi be the optimal point in Hi that satisfies the constraints. Explain why vi = vi-1 if vi-1 is contained in hi.

*$O(n^{2})$ incremental LP problem,每加入一個半平面,都必須重新計算最佳交集。

  • Simplex algorithm O(n log n),在 2D 限制下,可以做到 O(n)。
  • 其實這是一個廢話,因為 hi 加上去,只會讓最佳解更糟,如果最佳解沒變,那麼最佳解仍然維持。
  1. (15 points total)
    a. (10 points) Briefly explain what a “split node” is. Create a balanced one-dimensional search tree with 8 leave nodes to be “1”, “2”, “3”, “4”, “5”, “6”, “7”, and “8”, and a range query [2, 6] to show where the split node is and how it helps to find all numbers in the range.
    b. (5 points) Both kd-trees and range trees are designed to do range query. Give one scenario that the kd-trees should be used and another scenario that the range trees should be adopted.

1
2
3
4
5
6
7
8
9
[4]
/ \
/ \
/ \
[2] [6]
/ \ / \
[1] [3] [5] \
/\ /\ /\ \
[1][2][3][4] [5][6] [7]

找到其中一邊的 split node 的寫法如下:

1
2
3
4
5
6
v = root
while v is not leaf && (r <= xv || xv' > l)
if l <= xv'
v = lc(v)
else
v = rc(v)

最後我們找到兩個 split node [1], [7],在兩個 split node 之間的葉節點都是答案,對於葉節點可以利用建造時,使用一個 linked list 去完成。

  • 對於多維度範圍查找用 range tree 最好,可以保證在$O(log^{d} n)$ 以內找到解,kd-tree 在這種情況很容易退化。
  • 對於最鄰近點搜索則是使用 kd-tree 最好,range tree 反而沒辦法支持這種操作。
  1. (20 points)
    a. (5 points) Draw the trapezoidal map of the following given figure. Note that the bounding box is provided already. (Give each trapezoid a number, which will be used in part (b).)
    b. (10 points) Follow the algorithm to construct the search structure D for the trapezoidal map in part a). The segments are inserted in the order of s4, s3, s2, and s1.
    c. (5 points) In the trapezoidal algorithm, the endpoints of line segments are assumed to have different x-coordinate value (i.e., so-called general position). While a method was provided to relax this constraint, explain briefly why the composite-number method (i.e., transform (x, y) to (x|y, y|x)) which has been used in kd-trees and range trees to deal with the similar constraint was not adopted?

  • 因為它們是 range query,對於相同的 x 值仍然要算相同,利用偏斜的效果不利於操作。
Read More +

計算幾何 - HW03

Master Theorem

$$T(n) = \begin{cases} aT(n/b) + n^{c} & \text{ if } n > 1 \\ d & \text{ if } n = 1 \end{cases}$$

1.$\text{if } log_{b}a < c, T(n) = \theta(n^{c})$
2.$\text{if } log_{b}a = c, T(n) = \theta(n^{c} log n)$
3.$\text{if } log_{b}a > c, T(n) = \theta(n^{log_{b}a})$

Extend Master Theorem

$$T(n) = \begin{cases} aT(n/b) + f(n) & \text{ if } n > 1 \\ d & \text{ if } n = 1 \end{cases} \\ E = log_{b}(a)$$

1.$\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha < -1, T(n) = \theta(n^{E})$
2.$\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha = -1, T(n) = \theta(n^{E} log_{b} log_{b}(n))$
3.$\text{if } f(n) = O(n^{E} (log_{b}n)^{\alpha} ) \text{ and } \alpha > -1, T(n) = \theta(n^{E}(log_{b}n)^{\alpha + 1})$

Chapter 5

5.1

In the proof of the query time of the kd-tree we found the following
recurrence:
$$Q(n) = \begin{cases} O(1) & \text{ if } n = 1 \\ 2 + 2Q(n/4)& \text{ if } n > 1 \end{cases}$$
Prove that this recurrence solves to Q(n) = O(√n). Also show that Ω(√n) is a lower bound for querying in a kd-tree by defining a set of n points and a query rectangle appropriately.


  1. by master theorem,$a = 2, b = 4, c = 0 \Rightarrow Q(n) = \Theta(\sqrt{n})$
    2.$\Omega(\sqrt{n})$ 是 kd-tree 的 lower_bound。如果 + 號存在的行都一直被執行,另外 - 號行都不會被執行,那麼複雜度就會達到$\Omega(\sqrt{n})$,要明白如何加上 report 則會更慢,必須將包含的點依序回報。找一個不包含所有點的細長矩形於正中央即可,每次循環切割到 x 時,保證會留下 n/4 個節點。
1
2
3
4
5
6
7
8
9
10
11
12
13
Algorithm: SEARCHKDTREE(v, R)
if v is leaf
report the points stored at v if it lies in R.
else
- if region(lc(v)) contains R
report subtree lc(v)
+ else if lc(v) intersects R
SEARCHKDTREE(lc(v), R)
- if region(rc(v)) contains R
report subtree rc(v)
+ else if rc(v) intersects R
SEARCHKDTREE(rc(v), R)

5.3

In Section 5.2 it was indicated that kd-trees can also be used to store sets of points in higher-dimensional space. Let P be a set of n points in d-dimensional space. In parts a. and b. you may consider d to be a constant.

  1. Describe an algorithm to construct a d-dimensional kd-tree for the points in P. Prove that the tree uses linear storage and that your algorithm takes$O(n log n)$ time.
  2. Describe the query algorithm for performing a d-dimensional range query. Prove that the query time is bounded by$O(n^{1−1/d} +k)$.
  3. Show that the dependence on d in the amount of storage is linear, that is, show that the amount of storage is$O(dn)$ if we do not consider d to be a constant. Give the dependence on d of the construction time and the query time as well.

1
2
3
4
5
6
7
8
9
Algorithm : build(int k, int l, int r, int dep)
if l > r
return NULL
m = (l + r)/2
Node ret = median axis[k%K] of point[l, r] ----- O(n)
split points[l, r] by median ----- O(n), C++ std::nth_element()
ret.lson = build((k+1)%K, l, m-1);
ret.rson = build((k+1)%K, m+1, r);
return ret;
  1. 利用 median of medians 算法找到中位數,數據儲存用指針來完成搜索,不用移動資料。
    以上代碼根據遞迴公式$T(n) = 2T(n/2) + O(n) \Rightarrow T(n) = \Theta(n log n)$,而 kd-tree 是一個 full binary tree,每一個節點都代表一個實際資料,因此空間複雜度$O(n)$
  2. 假設在 d 為空間,Q(n) 表示 n 個點的詢問,依序按照維度切割 (ex. x, y, z, x …),現在只關注 x 軸上的切割,假設詢問範圍包含所有的 y, z,那麼在 2ed x 節點中,每一個節點具有$n/2^{d}$ 資料,而同一層會有$2^{d-1}$ 個 x 維度的子節點。然後遞迴詢問$2^{d-1}$ 所包含的範圍查找。
    藉由 master theorem,$a = 2^{d-1}, b = 2^{d}, c = 0 \Rightarrow Q(n) = \Theta(n^{1 - 1/d})$ $$Q(n) = \begin{cases} O(1) & \text{ if } n < 2^{d} \\ 2^{d-1} + 2^{d-1} Q(n/2^{d}) & \text{ if } n \geq 2^{d} \end{cases}$$
  3. 如果 d 不是常數,每一個內部節點空間 O(d),有 n 個節點則需 O(dn) 的儲存空間。詢問上,需要在 intersected 花 O(d) 時間決定是否存在交集、包含,再來判斷是否走訪子樹,因此詢問是$2dQ(n) = O(dn^{1-1/d})$,加上回報的效率為$2dQ(n) = O(dn^{1-1/d} + k)$

5.5

Algorithm SEARCHKDTREE can also be used when querying with other ranges than rectangles. For example, a query is answered correctly if the range is a triangle.

a. Show that the query time for range queries with triangles is linear in the worst case, even if no answers are reported at all. Hint: Choose all points to be stored in the kd-tree on the line y = x.
b. Suppose that a data structure is needed that can answer triangular range queries, but only for triangles whose edges are horizontal, vertical, or have slope +1 or −1. Develop a linear size data structure that answers such range queries in O(n3/4+k) time, where k is the number of points reported. Hint: Choose 4 coordinate axes in the plane and use a 4-dimensional kd-tree.
c. Improve the query time to O(n2/3+k). Hint: Solve Exercise 5.4 first.


  1. 最慘情況是 O(n)-詢問範圍為三角形。
    詢問的範圍如圖,所有點落在 y = x 上,三角形範圍是一個很貼近 y = x 的三角形,三角形並沒有包含任何一個點,卻與所有劃分的區域有交集,因此必須走訪所有節點。
  2. 如果要支持三角形範圍查找 (三角形的邊要不垂直、平行、斜率 +1、斜率 -1)。找到一個詢問$O(n^{3/4} + k)$ 的資料結構。
    類似 kd-tree,但是輪替的標準為 x 軸 y 軸 斜率 1 斜率 -1 ,根據 5.3(b) 的公式,相當於 d = 4 的情況,得到$O(n^{1 - 1/4} + k) = O(n^{3/4} + k)$
  3. 加快到$O(n^{2/3} + k)$ 的詢問時間。
    在這裡想到是建立兩個 kd-tree,其中一個順序為 x 軸 斜率 1 斜率 -1 ,另一個順序為 y 軸 斜率 1 斜率 -1 。前者可以回答向上、向下三角形,後者回答向左、向右三角形。相當於 d = 3 的切割,最多拆成 4 個範圍查找$O(4n^{1 - 1/3} + k) = O(n^{2/3} + k)$
    1. 在詢問矩形時,拆成四個三角形查找 (向上、向下、向左、向右三角形)
    2. 在詢問三角形時,拆成兩個三角形查找

5.9

One can use the data structures described in this chapter to determine whether a particular point (a,b) is in a given set by performing a range query with range [a : a]×[b : b].

  1. Prove that performing such a range query on a kd-tree takes time O(logn).
  2. What is the time bound for such a query on a range tree? Prove your answer.

  1. 對於 kd-tree 所消耗的時間 O(log n) 說明。 $[a:a] \times [b:b]$ 並不會跨區間。在 SEARCHKDTREE(v, R) 函數中,Line SEARCHKDTREE(lc(v), R) 和 SEARCHKDTREE(rc(v), R) 只會有一個符合。$$Q(n) = \begin{cases} O(1) & \text{ if } n = 1 \\ 1 + Q(n/2) & \text{ if } n > 1 \end{cases}$$
  2. 對於 kd-tree 所消耗的時間 O(d log n) 說明。
    首先能知道會先在第一維度探訪$[a:a]$ 的葉節點,中間經過 log n 個節點最後到葉節點,然後在其相對應的 y 軸 tree 中查找$[b:b]$ 也是 log n。因此是$O(\sum{i = 1}^{d} log n) = O(d log n)$

5.11

Let S1 be a set of n disjoint horizontal line segments and let S2 be a set
of m disjoint vertical line segments. Give a plane-sweep algorithm that
counts in O((n+m) log(n+m)) time how many intersections there are
in S1 ∪ S2.


給 n 個不相交的水平線段、m 個不相交的垂直線段,在 O((n+m) log (n+m)) 的時間內找到焦點個數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Algorithm:
1. sort all x-coordinate ----- O((n+m) log (n+m))
2. sweep x from small to large, maintain a segment tree or range tree.
for x = -oo to oo
for each horizontal line (sx, y)-(ex, y) in x
if sx = x
1Drangetree.add(y) ----- O(log (n+m))
for each vertical line (x, sy)-(x, ey) in x
ret += 1Drangetree.query(sy, ey) ----- O(log (n+m))
for each horizontal line (sx, y)-(ex, y) in x
if ex = x
1Drangetree.remove(y) ----- O(log (n+m))
return ret

Chapter 6

6.1

Draw the graph of the search structure D for the set of segments depicted
in the margin, for some insertion order of the segments.


雖然沒有加入順序的考量,但是手爆一個 17 個線段、平面空間 29 個的建造 … 也許有點瘋狂,用最簡單的由上而下掃描,造成一個傾斜的樹也是各種不容易。

6.2

Give an example of a set of n line segments with an order on them that
makes the algorithm create a search structure of size Θ(n2) and worst-case
query time Θ(n).


找到一個最慘空間$\Theta(n^{2})$,最慘詢問時間$\Theta(n)$

n 個線段,將其中 n/2 放置在同一個水平線上,對於剩餘 n/2 個:

每次加入的順序 s1, s2, …, si,每次的線段的 x 值會包含前一個線段$s_{i}.lx < s_{i-1}.lx, s_{i}.rx > s_{i-1}.rx$,美加入一個線段,會增加 n/2 個內部節點,並且最大深度增加 1。總計加入 n/2 次,增加的節點數量 O(n/2 x n/2) = O(n^2),深度 O(n/2) = O(n)。

6.5

Given a convex polygon P as an array of its n vertices in sorted order along the boundary. Show that, given a query point q, it can be tested in time O(logn) whether q lies inside P.


由於詢問次數相當多,必須將複雜度降到 O(log n),採用的方式將凸包其中一個點當作基準,則如果在凸包的點而言,一定會落在某個以基點拉出的三角形內部中,為了方便計算,則可以拿外積的正負邊界上。得到可能的三角形後,從邊界中可以藉由外積計算是否同側。

採用射線法 O(n) 肯定是吃大虧的。

part of UVa 12048 - Inhabitants
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
double cross(Pt o, Pt a, Pt b) {
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
int inside_convex(const Pt &p, Pt ch[], int n) {
if(n < 3)
return false;
if(cross(ch[0], p, ch[1]) > eps)
return false;
if(cross(ch[0], p, ch[n-1]) < -eps)
return false;
int l = 2, r = n-1;
int line = -1;
while(l <= r) {
int mid = (l + r)>>1;
if(cross(ch[0],p, ch[mid]) > -eps) {
line = mid;
r = mid - 1;
} else l = mid + 1;
}
return cross(ch[line-1], p, ch[line]) < eps;
}
Read More +