Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ramsayleung/ramsayleung.github.io
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramsayliang committed Jan 16, 2023
2 parents 09beaba + 8d834e6 commit 33ef946
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 0 deletions.
174 changes: 174 additions & 0 deletions content/post/2022/topological_sorting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
+++
title = "Topological Sort"
date = 2022-05-22T10:34:00+08:00
lastmod = 2022-05-22T16:22:34+08:00
tags = ["graph", "algorithm"]
categories = ["algorithm"]
draft = false
toc = true
+++

## <span class="section-num">1</span> Definition {#definition}

In computer science, a topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge `uv` from vertex `u` to vertx `v`, `u` comes before `v` in the ordering.

It sounds pretty academic, but I am sure you are using topological sort unconsciously every single day.


## <span class="section-num">2</span> Application {#application}

Many real world situations can be modeled as a graph with directed edges where some events must occur before others. Then a topological sort gives an order in which to perform these events, for instance:


### <span class="section-num">2.1</span> College class prerequisites {#college-class-prerequisites}

You must take course `b` first if you want to take course `a`. For example, in your alma mater, the student must complete `PHYS:1511(College Physics)` or `PHYS:1611(Introductory Physics I)` before taking `College Physics II`.

The courses can be represented by vertices, and there is an edge from `College Physics` to `College Physics II` since `PHYS:1511` must be finished before `College Physics II` can be enrolled.

{{< figure src="/ox-hugo/course_prerequsites.png" link="/ox-hugo/course_prerequsites.png" >}}


### <span class="section-num">2.2</span> Job scheduling {#job-scheduling}

scheduling a sequence of jobs or tasks based on their dependencies. The jobs are represented by vertices, and there is an edge from `x` to `y` if job `x` must be completed before job `y` can be started.

{{< figure src="/ox-hugo/job_scheduling.png" link="/ox-hugo/job_scheduling.png" >}}

In the context of a CI/CD pipeline, the relationships between jobs can be represented by directed graph(specifically speaking, by directed acyclic graph). For example, in a CI pipeline, `build` job should be finished before start `test` job and `lint` job.


### <span class="section-num">2.3</span> Program build dependencies {#program-build-dependencies}

You want to figure out in which order you should compile all the program's dependencies so that you will never try and compile a dependency for which you haven't first built all of its dependencies.

A typical example is `GNU Make`: you specific your targets in a `makefile`, `Make` will parse `makefile`, and figure out which target should be built firstly. Supposing you have a `makefile` like this:

```makefile
# Makefile for analysis report

output/figure_1.png: data/input_file_1.csv scripts/generate_histogram.py
python scripts/generate_histogram.py -i data/input_file_1.csv -o output/figure_1.png

output/figure_2.png: data/input_file_2.csv scripts/generate_histogram.py
python scripts/generate_histogram.py -i data/input_file_2.csv -o output/figure_2.png

output/report.pdf: report/report.tex output/figure_1.png output/figure_2.png
cd report/ && pdflatex report.tex && mv report.pdf ../output/report.pdf
```

`Make` will generate a DAG internally to figure out which target should be executed firstly with typological sort:

{{< figure src="/ox-hugo/build_dependencies.png" link="/ox-hugo/build_dependencies.png" >}}


## <span class="section-num">3</span> Directed Acyclic Graph {#directed-acyclic-graph}

Back to the definition, we say that a topological ordering of a directed graph is a linear ordering of its vertices, but not all directed graphs have a topological ordering.

A topological ordering is possible if and only if the graph has no directed cycles, that is, if it's a directed acyclic graph(DAG).

Let us see some examples:

{{< figure src="/ox-hugo/directed_acyclic_graph.png" link="/ox-hugo/directed_acyclic_graph.png" >}}

The definition requires that only the directed acyclic graph has a topological ordering, but why? What happens if we are trying to find a topological ordering of a directed graph? Let's take the `figure 3` for an example.

{{< figure src="/ox-hugo/dag_issue.png" link="/ox-hugo/dag_issue.png" >}}

The directed graph problem has no solution, this is the reason why directed cycle is forbidden


## <span class="section-num">4</span> Kahn's Algorithm {#kahn-s-algorithm}

There are several [algorithms](https://en.wikipedia.org/wiki/Topological_sorting#Algorithms) for topological sorting, Kahn's algorithm is one of them, based on breadth first search.

The intuition behind Kahn's algorithm is pretty straightforward:

****To repeatedly remove nodes without any dependencies from the graph and add them to the topological ordering****

As nodes without dependencies are removed from the graph, the original nodes depend on the removed node should be free now.

We keep removing nodes without dependencies from the graph until all nodes are processed, or a cycle is detected.

The dependencies of one node are represented as in-degree of this node.

Let's take a quick example of how to find out a topological ordering of a given graph with Kahn's algorithm.

{{< figure src="/ox-hugo/kahn's_algorithm_1.png" link="/ox-hugo/kahn's_algorithm_1.png" >}}

{{< figure src="/ox-hugo/kahn's_algorithm_2.png" link="/ox-hugo/kahn's_algorithm_2.png" >}}

{{< figure src="/ox-hugo/kahn's_algorithm_3.png" link="/ox-hugo/kahn's_algorithm_3.png" >}}

{{< figure src="/ox-hugo/kahn's_algorithm_4.png" link="/ox-hugo/kahn's_algorithm_4.png" >}}

Now we should understand how Kahn's algorithm works. Let's have a look at a C++ implementation of Kahn's algorithm:

```C++
#include <deque>
#include <vector>
// Kahn's algorithm
// `adj` is a directed acyclic graph represented as an adjacency list.
std::vector<int>
findTopologicalOrder(const std::vector<std::vector<int>> &adj) {
int n = adj.size();

std::vector<int> in_degree(n, 0);

for (int i = 0; i < n; i++) {
for (const auto &to_vertex : adj[i]) {
in_degree[to_vertex]++;
}
}

// queue contains nodes with no incoming edges
std::deque<int> queue;
for (int i = 0; i < n; i++) {
if (in_degree[i] == 0) {
queue.push_back(i);
}
}

std::vector<int> order(n, 0);

int index = 0;
while (queue.size() > 0) {
int cur = queue.front();
queue.pop_front();
order[index++] = cur;

for (const auto &next : adj[cur]) {
if (--in_degree[next] == 0) {
queue.push_back(next);
}
}
}

// there is no cycle
if (n == index) {
return order;
} else {
// return an empty list if there is a cycle
return std::vector<int>{};
}
}
```
## <span class="section-num">5</span> Bonus {#bonus}
When a pregnant woman takes calcium pills, she must make sure also that her diet is rich in vitamin D, since this vitamin makes the absorption of calcium possible.
After reading the demonstration of topological ordering, you (and I) too should take a certain vitamin, metaphorically speaking, to help you absorb. The vitamin D I pick for you (and myself) is two leetcode problems, which involve with the most typical use case of topological ordering -- college class prerequisites:
- [Course Schedule](https://leetcode.com/problems/course-schedule/)
- [Course Schedule II](https://leetcode.com/problems/course-schedule-ii/)
## <span class="section-num">6</span> Reference {#reference}
- [Topological Sort | Kahn's Algorithm | Graph Theory](https://www.youtube.com/watch?v=cIBFEhD77b4)
- [Directed Acyclic Graph](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/)
- [Hands-on Tutorial on Make](https://gertjanvandenburg.com/files/talk/make.html)
- [Topological sorting](https://en.wikipedia.org/wiki/Topological_sorting)
78 changes: 78 additions & 0 deletions content/post/2022/党员_党权与党争.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
+++
title = "党员,党权与党争"
date = 2022-02-20T13:35:35
lastmod = 2022-03-10T09:33:35+08:00
tags = ["book", "history"]
categories = ["book"]
draft = false
toc = true
+++

## <span class="section-num">1</span> 前言 {#前言}

> 秦人不暇自哀而后人哀之,后人哀之而不鉴之,亦使后人而复哀后人也
每个朝代灭亡之后,就会由下一个朝代的史官编写,如元朝灭亡之后,就由明朝来撰写《元史》。虽然国民党政权在大陆败退之后,没有史官来专门编写《民国史》,但还是有许多资料来探究国民党失败的原因。而《党员,党权与党争》就从组织角度来考察国民党失败的原因。

想来,以后也会有类似的,研究共产党的学术资料。


## <span class="section-num">2</span> 以俄为师 {#以俄为师}

中国国民党承续兴中会,同盟会,国民党,中华革命党而来,期间不仅名称数度更易,其组织形式亦几度因革。1924年国民党改组,借鉴俄国布尔什维克的组织模式,建立了一套全新的政党组织体系。

有感于国民党党务不振,孙中山于1924年从组织技术层面学习苏俄的建党,治党方法。实现三民主义为体,俄共组织为用,从党的组织结构,党章党纪,基层组织建制,基于党的军队建设,全面向苏俄学习,企图打造出一个组织严密,富有战斗力的新党。

只是,国民党师法俄共的组织形式,将党建在国上,实行以党治国,一党专政。但是,孙中山三民主义理念中的政治蓝图又是基于西方民主体制而设计的。也就是,国民党借鉴了两个不能同时并立的政治架构,拼装了一台不伦不类的政治机器,成立国民政府后一方面依照西方分权学说,成立五院,另一方面又依照苏俄党治学说,设立集权的中执会,中政会。这种兼收并蓄,可谓错漏百出。


## <span class="section-num">3</span> 清党分共 {#清党分共}

在1924年的国民党一大上,孙中山提出了「联俄」,「联共」,「扶助工农」的三大政策,期望在苏俄和中共共产党的帮助下,完成反帝反封的国民革命。而国民党与共产党的合作关系,是被称为「党内合作」的合作关系,并不是国民党与共产党两个政党开展合作,而是共产党员以个人身份加入国民党,成为跨党党员,开展工作。

国共两党的党员,在实际的工作中,是呈现出「国民党在上层,共产党在下层」这样的状态。国民党差不多专做上层的工作,而下层的民众运动,国民党员参加的少,共产党员参加的多,因此形成了一种畸形的发展。到1926年,国民党二大召开前后,甚至出现共产党「包办」大部分国民党党务的现象,据中共领导人称,在国民党二大召开前后,大约有90%的国民党地方组织处于共产党员和国民党左派的领导之下。

1924-1927年的国共关系,既是一种相互合作的关系,又是一种相互竞存的关系。到第一次国共合作的后期,国共合作关系已经从原来的国民党「容共」,变成共产党「容国」。即使共产党员远少于国民党员,但因为其组织严密,工作高效,已经成为国民党党内之党。

两党组织动作的巨大反差,国民党内部一方面为内部组织松懈而忧虑,更对共产党组织严密而恐惧,这种忧虑和恐惧衍化为「分共」,「反共」的主张与行动,另一方面促使部分富有革命热情的国民党青年,在强烈对比之下,加下到组织更严密的共产党去,这又加深了国民党内部的恐惧与忧虑。

在此种忧虑与压力之下,1927年4月12日蒋介石下令武力清党分共,屠杀共产党员,就变得理所当然。如果蒋不分共,国民党的情况也不会好转,只会被和平演变成共产党。


## <span class="section-num">4</span> 党务不振 {#党务不振}

「四一二」清共,对共产党造成了巨大的伤害,让共产党意识到「文斗」虽强,但是还是干不过刀把子,悟出了枪杆里出政权的道理。很多人没有意识到的是,清共对国民党同样造成巨大的伤害,因为共产党使用秘密党员制,因此,要分共时,并不知道哪个是共产党员,哪个是国民党员。

蒋介石的亲信陈果夫曾经使用过一种荒谬儿戏至极的方法来辨别两党党员:让屋子里面的人相互殴打,然后他认为打着打着,共产党员就会帮助共产党员,国民党员就会帮助国民党员,就能借此分出两党党员。

因为分不清共产党员,就免不了杀错人,把「像」共产党的党员杀完之后,就开始把有革命热情的左派国民党员和群众都当成共产党杀了,清共之旋风越刮越大,甚至国民党民都无人敢做真正的革命之事,地主劣绅趁机诬陷减租减息等不利于现有特权阶级的国民党党员为共产党员,以除之而后快,以致人人自危。甚至还有索婚不成,诬其为共党以杀之的可悲之事。

此种分党手段造成的严重后果就是,国民党在国民心中的民心一落千丈,并再也回不去了。而在基层乡镇,因此大量干实事的国民党员被杀,导致基层权力空虚,地主劣绅趁虚而入,摇身一变成为国民党员,把持基层党权。

在蒋介石独裁及派系核相争的帝王心术之下,中上层的党员,忠于派系多过忠于党,对权力的向往大于对革命理想的践行,党统在各派系激烈的权力斗争中濒于破裂,党务亦在派系的内耗中日趋衰微。

蒋既无决心重组党务,又不愿意放弃手中独裁的权力,失去民心,党心,国民党的党务建设有如泥牛入海,再也无法拉回来了. 自北伐后,国民党民心日失,党务难振。

自分党至国民党败退台湾,党务再没再振之机。


## <span class="section-num">5</span> 以军治党 {#以军治党}

自孙中山逝世,蒋介石依靠黄埔系的党军之力上位,靠军权登上国民党权力的高位。而因为党权不振,无法通过党来治理国家,蒋就希望通过军队来治理国家,由原来的以党治军,变成以军治党。

蒋的军治理念,首先表现为放大军人在国家社会中的作用,蒋认为,在任何时候,任何国家,军人乾了应该是社会的主导群体。其次,强调军队组织在国家和社会的各个领域的普适性,认为无论古今中外,要组织成一个健全的国家和社会,都是要全国军队化。

蒋介石对军权和军治的过分迷恋,分散甚至取代了他对党治和党务组织建设的关注与考虑。而蒋重军轻党的原因是多方面的,在与汪精卫及胡汉民的「继承人」之争中,前者都是通过党权与蒋所持的军权相争,蒋难免会有把党权作为障碍之想。其次,1931-1932年之交,蒋二次下野时,反思认为国民党的各级党组织并不忠于他,而他的一生中,最为依赖的权势资源就是军队,拿着个锤子,难免看什么都像钉子。

在蒋介石重军轻党的主导下,军权日趋膨胀,党权日趋低落,从中央到地方,军权凌驾于党政之上,党治徒有其表,军治实际取代了党治。

而军治,既是党权不振的因,又是党权不振的果,可谓因果纠缠,恶性循环。


## <span class="section-num">6</span> 总结 {#总结}

国民党依照俄共实行一党专政,而在实际运行中,其组织散漫性,又像西方议会政党,只重政见不重组织。国民党是一个弱势独裁政党,国民党并非不想独裁,而是独裁之心有余,独裁之力不足。国民党和中国共产党都是以俄为师的中国学生,花开两朵,各表一枝。全盘俄化的中国共产党赢了只学到半套功夫的国民党,而国民党后又败在年轻的民进党手下。

蒋公一再以「亡党亡国」警示其党员,然而,事实却是,党破山河在,党亡国不亡。而后之视今,亦尤今之视昔。

只是未想,时运弄人,两个学生尚在,引以为师的苏共竟先消散在历史的尘埃中。
Binary file added static/ox-hugo/build_dependencies.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/course_prerequsites.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/dag_issue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/directed_acyclic_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/job_scheduling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/kahn's_algorithm_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/kahn's_algorithm_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/kahn's_algorithm_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/ox-hugo/kahn's_algorithm_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 33ef946

Please sign in to comment.