Ex.1 若将y ← \leftarrow ←uniform(0,1)改为y ← \leftarrow ←x,则上述的算法估计的值是什么?
答:此时x和y的取值相等,都位于连接(0,0)和(1,1)的线段上。此时四分之一圆和边长为1的正方形,根据Monte Carlo,面积比变为1: 2 \sqrt2 2。根据下列公式:
π ∗ 1 2 4 ∗ 1 2 = 1 2 \frac{\pi*1^{2}}{4*1^{2}}=\frac{1}{\sqrt{2}} 4∗12π∗12=21
解得 π = 2 2 \pi=2\sqrt2 π=22.
import random
n = 100000
cnt = 0
for i in range(n):
x = random.random()
y = x
if x**2 + y**2 <= 1:
cnt += 1
pi = 4*(cnt/n)
print(pi)
# n = 10, pi = 2.4
# n = 10万, pi = 2.8536
# n = 1000万, pi = 2.8296
Ex.2 在机器上用 4 ∫ 0 1 1 − x 2 d x 4\int_{0}^{1}\sqrt{1-x^{2}}dx 4∫011−x2dx,估计 π \pi π值,给出不同的n值及精度。
答:第一象限框定一个(0,0)到(1,1)的正方形,随机在该区域采样n个点,若某点坐标在曲线 y = 1 − x 2 y=\sqrt{1-x^{2}} y=1−x2下方,则count加一,最终 c o u n t / n count/n count/n即 ∫ 0 1 1 − x 2 d x \int_{0}^{1}\sqrt{1-x^{2}}dx ∫011−x2dx的面积与 1 ∗ 1 1*1 1∗1正方形面积的比值.
import random
import math
def f(x):
return math.sqrt(1-x**2)
n = 100000
cnt = 0
for i in range(n):
x = random.random()
y = random.random()
if y < f(x):
cnt += 1
S = cnt/n
pi = 4*S
print(pi)
# n = 10, pi = 2.8
# n = 1万, pi = 3.16
# n = 100万, pi = 3.1428
# n = 1亿, pi = 3.1417
Ex.3 设a,b, c和d是实数,且 a ≤ b , c ≤ d , f : [ a , b ] → [ c , d ] a\le b,c\le d, f:[a,b]\rightarrow [c,d] a≤b,c≤d,f:[a,b]→[c,d]是一个连续函数,写一概率算法计算积分 ∫ a b f ( x ) d x \int_{a}^{b}f(x)dx ∫abf(x)dx.
答:设函数 f ( x ) = s i n x f(x)=sinx f(x)=sinx, a = 0 , b = π , c = 0 , d = 1 a=0, b=\pi, c=0, d=1 a=0,b=π,c=0,d=1,理论上根据牛顿莱布尼茨公式:
∫ 0 π s i n x d x = [ − c o s ] 0 π = 2 \int_{0}^{\pi}sinxdx=[-cos]_{0}^{\pi}=2 ∫0πsinxdx=[−cos]0π=2
import random
import math
def f(x):
return math.sin(x)
n = 1000000
cnt = 0
a = 0
b = math.pi
c = 0
d = 1
for i in range(n):
x = random.random() * math.pi
y = random.random()
if y <= f(x):
cnt += 1
S = math.pi*(cnt/n)
print(S)
# n = 10, S = 2.8274
# n = 1万, S = 2.0008
# n = 100万, S = 1.9988
# n = 1亿, S = 2.0002
可见当n值越大,计算出的面积与理论值越接近,但计算时间越长。
Ex.4 (p36)用上述算法,估计整数子集1-n的大小,并分析n对估计值的影响.
答:这种计算集合的势算法需要n足够大,且需要运行多次求平均后的结果才能接近于集合的势,下面代码分别是基于不同的n进行实验,每一个n对应运行20次求平均.
import numpy as np
import random
import math
n = 10000000
arr = np.arange(n)
tmp = []
flag = True
cnt = 0
while flag:
r = random.randint(0, n-1)
if r in tmp:
break
else:
tmp.append(r)
cnt += 1
result = 2*cnt**2/math.pi
print(result)
# n = 10, result = 14.53
# n = 10000, result = 7841.2
# n = 1000000, result = 1270204.1
# n = 100000000, result = 91275198.9
当n越大时,概率算法计算后的结果越接近实际。当然对于每个n来说,实验次数越多,其平均值也越接近于真实的n,这个消融实验本题没做要求。
Ex.5 (p54)分析dlogRH的工作原理,指出该算法相应的u和v.
答:Sherwood算法主要的思路是消除掉「某个样例造成最坏复杂度」的情况,包括以下三个步骤:
(1)预处理:通过u(x,r)将原实例x转化为随机实例y,r为一个随机数;
(2)采用确定算法对随机实例y进行求解,得到一个解;
(3)后处理:将上一步得到的解通过v(r, s)变换为原实例的解;
所以dlogRH算法先选择一个随机数r,先求模幂b,c ← \leftarrow ← ba mod p这一步相当于预处理并求出c,随后对这个随机变量c按照确定算法进行求解,得到结果y;最后return那一步即后处理,解出x。
u = ba mod p
v = (y-r) mod (p-1)
Ex.6(p67)写一Sherwood算法C,与算法A,B,D比较,给出实验结果。
直接上代码:
import numpy as np
import random
import math
class Solution:
def __init__(self, n):
self.arr = np.arange(n)
self.ptr = np.empty_like(self.arr)
self.pre = np.empty_like(self.arr)
self.ptr[:-1] = self.arr[1:]
self.ptr[-1] = self.arr[0]
self.pre[1:] = self.arr[:-1]
self.pre[0] = self.arr[-1]
self.shuffle(n)
self.head = 0
for i in range(n):
if self.arr[i] == 0:
self.head = i
self.cnt = 0
def shuffle(self, n): # shuffle the array and keep the order of ptr
for i in range(n):
# print(self.arr)
# print(self.ptr)
# print('++++++++++++++++++++')
r = random.randint(i, n-1)
self.arr[i], self.arr[r] = self.arr[r], self.arr[i]
tmp_r = [self.ptr[r], self.pre[r]]
tmp_i = [self.ptr[i], self.pre[i]]
if i == r:
continue
elif r == self.ptr[i]: # swap the order of index i and r (adjacent)
self.ptr[self.pre[i]] = r
self.pre[self.ptr[r]] = i
self.ptr[i] = tmp_r[0]
self.ptr[r] = i
self.pre[i] = r
self.pre[r] = tmp_i[1]
elif i == self.ptr[r]: # swap the order of index i and r (adjacent)
self.ptr[self.pre[r]] = i
self.pre[self.ptr[i]] = r
self.ptr[i] = r
self.ptr[r] = tmp_i[0]
self.pre[i] = tmp_r[1]
self.pre[r] = i
else: # general situation
self.pre[tmp_i[0]] = r
self.ptr[tmp_i[1]] = r
self.pre[tmp_r[0]] = i
self.ptr[tmp_r[1]] = i
self.pre[i] = tmp_r[1]
self.ptr[i] = tmp_r[0]
self.pre[r] = tmp_i[1]
self.ptr[r] = tmp_i[0]
def funcA(self, x, head):
idx = head
# cnt = 0
while x > self.arr[idx]:
idx = self.ptr[idx]
self.cnt += 1
return idx
def funcB(self, x):
n = len(self.arr)
sqrtn = math.floor(math.sqrt(n)) + 1
max_idx, max_val = self.head, 0
for i in range(sqrtn):
self.cnt += 1
y = self.arr[i]
if y > max_val and x > y:
max_idx, max_val = i, y
return self.funcA(x, max_idx)
def funcC(self, x):
n = len(self.arr)
sqrtn = math.floor(math.sqrt(n)) + 1
max_idx, max_val = self.head, 0
for i in range(sqrtn):
r = random.randint(0, n-1)
self.cnt += 1
y = self.arr[r]
if y > max_val and x > y:
max_idx, max_val = r, y
return self.funcA(x, max_idx)
def funcD(self, x):
n = len(self.arr)
r = random.randint(0, n-1)
val = self.arr[r]
# print(r, val)
self.cnt += 1
if x > val:
return self.funcA(x, self.ptr[r])
elif x < val:
return self.funcA(x, self.head)
else:
return r
s = Solution(100000)
print(s.arr)
print(s.ptr)
x = 50000
# print(s.funcA(x, s.head)) # cnt == 50000 constant
# print(s.funcD(x)) # cnt = 35933 on avg (10 times)
# print(s.funcB(x)) # cnt = 654.2 on avg (10 times)
# print(s.funcC(x)) # cnt = 720 on avg (10 times)
# print(s.cnt)
实验结果:实验中令数组长度n=100000,数组为一个1-100000的整数序列,经过shuffle进行打乱,但ptr的顺序保持一致。实验中用四种算法搜寻x=50000这个元素,得到的平均查找次数如下:
A算法(确定算法),复杂度O(n),查找次数为常数50000;
B算法(确定算法),复杂度O( n \sqrt n n),平均查找次数654.2(10次实验);
C算法(概率算法),复杂度O( n \sqrt n n),平均查找次数720(10次实验);
D算法(概率算法),复杂度O(n),查找次数为常数35933(10次实验)。
可见当n的数量级具有一定规模时,O( n \sqrt n n)算法比O(n)算法效率高得太多。
======================================================
Ex.7(p77)证明:当放置(k+1)th皇后时,若有多个位置是开放的,则算法QueensLV选中其中任意位置的概率相等.
proof:对于最后一个(nb)可以放的皇后来说,其被选中的概率为1/nb;往前递推,前一个被选中的概率为1/(nb-1),但是其后续还有被替换掉的可能性,这个概率为(nb-1)/nb,因此倒数第二个成立元素最终得以保留的概率为1/(nb-1)*(nb-1)/nb=1/nb;反向一直推到第一个成立的元素,其被选中的概率为1,被替换掉的概率为 1 / 2 ∗ 2 / 3 ∗ . . . ∗ ( n b − 1 ) / n b = 1 / n b 1/2*2/3*...*(nb-1)/nb=1/nb 1/2∗2/3∗...∗(nb−1)/nb=1/nb。因此所有的open位置的概率相等,都等于1/nb。
Ex.8(p83)写一算法,求n=12-20时最优的StepVegas值.
time为100次实验每次都找到解的总时间,probability为100次实验得到的success的频率。
N=12(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 186 | 100 |
2 | 139 | 100 |
3 | 90 | 100 |
4 | 83 | 85 |
5 | 54 | 49 |
6 | 78 | 27 |
7 | 119 | 9 |
8 | 178 | 9 |
9 | 228 | 6 |
10 | 257 | 4 |
11 | 232 | 3 |
12 | 271 | 4 |
N=12时,由实验结果,当StepVegas=4 时时间和概率效果较好;
N=13(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 247 | 100 |
2 | 215 | 100 |
3 | 134 | 98 |
4 | 88 | 88 |
5 | 78 | 54 |
6 | 87 | 25 |
7 | 114 | 11 |
8 | 139 | 7 |
9 | 212 | 3 |
10 | 268 | 3 |
11 | 391 | 2 |
12 | 325 | 3 |
13 | 328 | 1 |
N=13时,由实验结果,当StepVegas=4 时时间和概率效果较好;
N=14(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 908 | 100 |
2 | 520 | 100 |
3 | 253 | 97 |
4 | 179 | 94 |
5 | 113 | 92 |
6 | 98 | 59 |
7 | 86 | 32 |
8 | 125 | 16 |
9 | 194 | 10 |
10 | 239 | 6 |
11 | 486 | 6 |
12 | 441 | 5 |
13 | 512 | 3 |
14 | 551 | 4 |
N=14时,由实验结果,当StepVegas=4,5 时时间和概率效果较好;
N=15(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 940 | 100 |
2 | 549 | 100 |
3 | 381 | 100 |
4 | 247 | 100 |
5 | 209 | 97 |
6 | 133 | 87 |
7 | 110 | 57 |
8 | 114 | 41 |
9 | 168 | 12 |
10 | 232 | 5 |
11 | 319 | 4 |
12 | 457 | 6 |
13 | 478 | 2 |
14 | 532 | 2 |
15 | 608 | 4 |
N=15时,由实验结果,当StepVegas=5,6 时时间和概率效果较好;
N=16(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 3993 | 100 |
2 | 1528 | 100 |
3 | 956 | 100 |
4 | 402 | 100 |
5 | 326 | 100 |
6 | 194 | 95 |
7 | 126 | 71 |
8 | 108 | 44 |
9 | 132 | 27 |
10 | 184 | 12 |
11 | 251 | 12 |
12 | 372 | 4 |
13 | 632 | 4 |
14 | 604 | 2 |
15 | 648 | 2 |
16 | 614 | 5 |
N=16时,由实验结果,当StepVegas=6,7 时时间和概率效果较好;
N=17(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 4441 | 100 |
2 | 1732 | 100 |
3 | 1316 | 100 |
4 | 704 | 100 |
5 | 484 | 100 |
6 | 295 | 98 |
7 | 228 | 94 |
8 | 128 | 77 |
9 | 146 | 44 |
10 | 155 | 18 |
11 | 243 | 12 |
12 | 415 | 4 |
13 | 511 | 6 |
14 | 659 | 2 |
15 | 810 | 1 |
16 | 882 | 1 |
17 | 704 | 2 |
N=17时,由实验结果,当StepVegas=7,8 时时间和概率效果较好;
N=18(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 14691 | 100 |
2 | 5718 | 100 |
3 | 3171 | 100 |
4 | 1497 | 100 |
5 | 814 | 100 |
6 | 435 | 100 |
7 | 358 | 97 |
8 | 198 | 82 |
9 | 151 | 65 |
10 | 166 | 31 |
11 | 192 | 19 |
12 | 304 | 7 |
13 | 439 | 5 |
14 | 577 | 8 |
15 | 732 | 5 |
16 | 852 | 3 |
17 | 929 | 4 |
18 | 877 | 1 |
N=18时,由实验结果,当StepVegas=7,8 时时间和概率效果较好;
N=19(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 9290 | 100 |
2 | 5183 | 100 |
3 | 3675 | 100 |
4 | 2893 | 100 |
5 | 1468 | 100 |
6 | 998 | 100 |
7 | 412 | 99 |
8 | 336 | 99 |
9 | 251 | 81 |
10 | 169 | 54 |
11 | 187 | 35 |
12 | 231 | 16 |
13 | 383 | 10 |
14 | 494 | 9 |
15 | 796 | 5 |
16 | 1213 | 7 |
17 | 1204 | 3 |
18 | 1369 | 4 |
19 | 1095 | 2 |
N=19时,由实验结果,当StepVegas=8,9 时时间和概率效果较好;
N=20(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 78801 | 100 |
2 | 27941 | 100 |
3 | 8371 | 100 |
4 | 5370 | 100 |
5 | 2573 | 100 |
6 | 998 | 100 |
7 | 694 | 99 |
8 | 562 | 98 |
9 | 268 | 96 |
10 | 247 | 75 |
11 | 202 | 50 |
12 | 235 | 34 |
13 | 281 | 16 |
14 | 453 | 7 |
15 | 583 | 3 |
16 | 866 | 7 |
17 | 1172 | 6 |
18 | 1128 | 5 |
19 | 1543 | 1 |
20 | 1501 | 2 |
N=20时,由实验结果,当StepVegas=9 时时间和概率效果较好;
综上所述,对于所有的N来说,最好的StepVegas的值位于[N/3,N/2]之间。
Ex.7(p77)证明:当放置(k+1)th皇后时,若有多个位置是开放的,则算法QueensLV选中其中任意位置的概率相等.
proof:对于最后一个(nb)可以放的皇后来说,其被选中的概率为1/nb;往前递推,前一个被选中的概率为1/(nb-1),但是其后续还有被替换掉的可能性,这个概率为(nb-1)/nb,因此倒数第二个成立元素最终得以保留的概率为1/(nb-1)*(nb-1)/nb=1/nb;反向一直推到第一个成立的元素,其被选中的概率为1,被替换掉的概率为 1 / 2 ∗ 2 / 3 ∗ . . . ∗ ( n b − 1 ) / n b = 1 / n b 1/2*2/3*...*(nb-1)/nb=1/nb 1/2∗2/3∗...∗(nb−1)/nb=1/nb。因此所有的open位置的概率相等,都等于1/nb。
Ex.8(p83)写一算法,求n=12-20时最优的StepVegas值.
代码如下:
import time
import random
class Solution:
def __init__(self, n, sv):
self.n = n
self.k = 0
self.diag45 = []
self.diag135 = []
self.col = []
self.cnt = 0
self.stepVegas = sv
self.nb = 0
self.flag = False
self.flag2 = False
def isOk(self, i):
if i not in self.col and i-self.k+1 not in self.diag45 and i+self.k+1 not in self.diag135:
return True
else:
return False
def QueenDFS(self):
if self.flag is True:
return
if self.k >= self.n:
# print(self.col)
self.flag = True
# exit(1)
return
for i in range(self.n):
self.cnt += 1
if self.isOk(i):
self.col.append(i)
self.diag45.append(i-self.k+1)
self.diag135.append(i+self.k+1)
self.k += 1
self.QueenDFS()
self.col.pop()
self.diag45.pop()
self.diag135.pop()
self.k -= 1
def QueenLV(self):
if self.k >= self.n:
print(self.col)
exit(1)
self.nb = 0
j = -1
for i in range(self.n):
if self.isOk(i):
self.nb += 1
r = random.randint(1, self.nb)
if r == 1:
j = i
if self.nb > 0:
self.col.append(j)
self.diag45.append(j-self.k+1)
self.diag135.append(j+self.k+1)
self.k += 1
self.QueenLV()
self.col.pop()
self.diag45.pop()
self.diag135.pop()
self.k -= 1
elif self.nb == 0:
print('error')
exit(1)
def QueenComb(self):
if self.flag2 is True:
return
if self.k >= self.stepVegas:
self.QueenDFS()
return
# print(self.col)
# exit(1)
# print(self.k)
self.nb = 0
j = -1
for i in range(self.n):
if self.isOk(i):
self.nb += 1
r = random.randint(1, self.nb)
if r == 1:
j = i
if self.nb > 0:
self.col.append(j)
self.diag45.append(j-self.k+1)
self.diag135.append(j+self.k+1)
self.k += 1
self.QueenComb()
self.col.pop()
self.diag45.pop()
self.diag135.pop()
self.k -= 1
elif self.nb == 0:
# print('error')
self.flag2 = True
# exit(1)
n = 17
for sv in range(1, n + 1):
t1 = time.time()
cnt = 0
while cnt < 100:
a = Solution(n, sv)
a.QueenComb()
if a.flag is True:
cnt += 1
t2 = time.time()
# print(t2 - t1)
cnt = 0
for i in range(100):
a = Solution(n, sv)
a.QueenComb()
if a.flag is True:
cnt += 1
print('StepVegas={}: time:{} cnt={}'.format(sv, t2-t1, cnt))
time为100次实验每次都找到解的总时间,probability为100次实验得到的success的频率。
N=12(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 186 | 100 |
2 | 139 | 100 |
3 | 90 | 100 |
4 | 83 | 85 |
5 | 54 | 49 |
6 | 78 | 27 |
7 | 119 | 9 |
8 | 178 | 9 |
9 | 228 | 6 |
10 | 257 | 4 |
11 | 232 | 3 |
12 | 271 | 4 |
N=12时,由实验结果,当StepVegas=4 时时间和概率效果较好;
N=13(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 247 | 100 |
2 | 215 | 100 |
3 | 134 | 98 |
4 | 88 | 88 |
5 | 78 | 54 |
6 | 87 | 25 |
7 | 114 | 11 |
8 | 139 | 7 |
9 | 212 | 3 |
10 | 268 | 3 |
11 | 391 | 2 |
12 | 325 | 3 |
13 | 328 | 1 |
N=13时,由实验结果,当StepVegas=4 时时间和概率效果较好;
N=14(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 908 | 100 |
2 | 520 | 100 |
3 | 253 | 97 |
4 | 179 | 94 |
5 | 113 | 92 |
6 | 98 | 59 |
7 | 86 | 32 |
8 | 125 | 16 |
9 | 194 | 10 |
10 | 239 | 6 |
11 | 486 | 6 |
12 | 441 | 5 |
13 | 512 | 3 |
14 | 551 | 4 |
N=14时,由实验结果,当StepVegas=4,5 时时间和概率效果较好;
N=15(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 940 | 100 |
2 | 549 | 100 |
3 | 381 | 100 |
4 | 247 | 100 |
5 | 209 | 97 |
6 | 133 | 87 |
7 | 110 | 57 |
8 | 114 | 41 |
9 | 168 | 12 |
10 | 232 | 5 |
11 | 319 | 4 |
12 | 457 | 6 |
13 | 478 | 2 |
14 | 532 | 2 |
15 | 608 | 4 |
N=15时,由实验结果,当StepVegas=5,6 时时间和概率效果较好;
N=16(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 3993 | 100 |
2 | 1528 | 100 |
3 | 956 | 100 |
4 | 402 | 100 |
5 | 326 | 100 |
6 | 194 | 95 |
7 | 126 | 71 |
8 | 108 | 44 |
9 | 132 | 27 |
10 | 184 | 12 |
11 | 251 | 12 |
12 | 372 | 4 |
13 | 632 | 4 |
14 | 604 | 2 |
15 | 648 | 2 |
16 | 614 | 5 |
N=16时,由实验结果,当StepVegas=6,7 时时间和概率效果较好;
N=17(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 4441 | 100 |
2 | 1732 | 100 |
3 | 1316 | 100 |
4 | 704 | 100 |
5 | 484 | 100 |
6 | 295 | 98 |
7 | 228 | 94 |
8 | 128 | 77 |
9 | 146 | 44 |
10 | 155 | 18 |
11 | 243 | 12 |
12 | 415 | 4 |
13 | 511 | 6 |
14 | 659 | 2 |
15 | 810 | 1 |
16 | 882 | 1 |
17 | 704 | 2 |
N=17时,由实验结果,当StepVegas=7,8 时时间和概率效果较好;
N=18(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 14691 | 100 |
2 | 5718 | 100 |
3 | 3171 | 100 |
4 | 1497 | 100 |
5 | 814 | 100 |
6 | 435 | 100 |
7 | 358 | 97 |
8 | 198 | 82 |
9 | 151 | 65 |
10 | 166 | 31 |
11 | 192 | 19 |
12 | 304 | 7 |
13 | 439 | 5 |
14 | 577 | 8 |
15 | 732 | 5 |
16 | 852 | 3 |
17 | 929 | 4 |
18 | 877 | 1 |
N=18时,由实验结果,当StepVegas=7,8 时时间和概率效果较好;
N=19(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 9290 | 100 |
2 | 5183 | 100 |
3 | 3675 | 100 |
4 | 2893 | 100 |
5 | 1468 | 100 |
6 | 998 | 100 |
7 | 412 | 99 |
8 | 336 | 99 |
9 | 251 | 81 |
10 | 169 | 54 |
11 | 187 | 35 |
12 | 231 | 16 |
13 | 383 | 10 |
14 | 494 | 9 |
15 | 796 | 5 |
16 | 1213 | 7 |
17 | 1204 | 3 |
18 | 1369 | 4 |
19 | 1095 | 2 |
N=19时,由实验结果,当StepVegas=8,9 时时间和概率效果较好;
N=20(100次实验)
StepVegas | time(ms) | probability(%) |
---|---|---|
1 | 78801 | 100 |
2 | 27941 | 100 |
3 | 8371 | 100 |
4 | 5370 | 100 |
5 | 2573 | 100 |
6 | 998 | 100 |
7 | 694 | 99 |
8 | 562 | 98 |
9 | 268 | 96 |
10 | 247 | 75 |
11 | 202 | 50 |
12 | 235 | 34 |
13 | 281 | 16 |
14 | 453 | 7 |
15 | 583 | 3 |
16 | 866 | 7 |
17 | 1172 | 6 |
18 | 1128 | 5 |
19 | 1543 | 1 |
20 | 1501 | 2 |
N=20时,由实验结果,当StepVegas=9 时时间和概率效果较好;
综上所述,对于所有的N来说,最好的StepVegas的值位于[N/3,N/2]之间。
Ex1. 与确定性算法相比较,并给出100-10000以内错误的比例。
代码:
import math
import random
class Certain:
def __init__(self):
self.res = []
self.n = 10000
def isPrime(self, x):
s = 2
e = int(math.sqrt(x))
for i in range(s, e+1):
if int(x) % int(i) == 0:
return False
return True
def printPrimes(self):
# self.res.append(2)
i = 101
while i < 10000:
if self.isPrime(i):
self.res.append(i)
i += 2
print(self.res)
class Uncertain:
def __init__(self):
self.res = []
self.n = 10000
def Btest(self, a, n):
s, t = 0, n-1
while t % 2 == 1:
s += 1
t /= 2
x = a**t % n
if x == 1 or x == n-1:
return True
for i in range(1, s):
x = x ** 2 % n
if x == n-1:
return True
return False
def MillRob(self, n):
a = random.randint(2, n-2)
return self.Btest(a, n)
def repeatMillRab(self, n, k):
for i in range(1, k+1):
if self.MillRob(n) is False:
return False
return True
def printPrimes(self):
self.res.append(2)
self.res.append(3)
i = 101
while i < 10000:
k = int(math.log(i, 2))
if self.repeatMillRab(i, k):
self.res.append(i)
i += 2
print(self.res)
a = Certain()
a.printPrimes()
print(len(a.res))
b = Uncertain()
b.printPrimes()
print(len(b.res))
答案:确定性算法是1204个,Monte Carlo算法得出的结果基本落在1204-1206之间(进行了30次实验)。
Ex2. 给出与图的独立集问题相关的判定问题的形式化描述,并证明它是NP完全的(提示:根据团问题进行规约)。
答:独立集问题:给定一个图G=(V,E),假设V‘表示图G的一个子集,对于I中的任意两个不同的顶点u,v,都不存在(u,v)属于E,则集合V‘是G的一个独立集。判定问题即给定V的一个子集V’作为证书,验证该子集之间任意两个顶点u,v,都不存在(u,v)属于E,如是则返回yes,否则返回no。
NPC证明:
(1)先证明独立集问题属于NP问题:根据上述形式化表示,可给定一个独立集V‘作为图G的证书,可以在多项式时间内验证:对于V’中的任意两点u,v,都不存在(u,v)属于E。
(2)再证明 Clique ≤ p \le_{p} ≤pIndependent-Set:设G‘=(V,E’)表示图G的补图,从团V‘中任取不同的两点u,v,都存在(u,v)属于E‘,即(u,v)不属于E,因此V‘属于图G的独立集。所以团问题可以规约到独立集问题。
综和(1)和(2),独立集问题属于NPC问题。
Ex3. 证明G中的最大团size为 α \alpha α等价于Gm中的最大团size为m α \alpha α.
证明:(1)充分性:根据幂图的特征,可知若图G的最大团size为 α \alpha α,则幂图Gm中必然存在一个大小为m α \alpha α的最大团。此时需要考虑的是是否有大于m α \alpha α的团存在。假设幂图Gm中存在大于m α \alpha α的团,此时必然会有某一个子图G贡献至少 α \alpha α+1的结点用于构建团,显然矛盾。因此充分性证毕;
(2)必要性:若Gm的最大团size为m α \alpha α,若每一个子图G贡献的结点数(最大团)大于 α \alpha α,则幂图Gm的最大团size必然要大于m α \alpha α;若每一个子图G的最大团size小于 α \alpha α,则幂图Gm的最大团size必然要小于m α \alpha α,因此图G的最大团size只能在等于 α \alpha α时,Gm中的最大团size为m α \alpha α。
Ex4. 当最优调度在任何机器上至多包含两个作业时,LPT也是最优的。
答:设n=2m,若n<2m,则令 J n + 1 , . . . , J 2 m J_{n+1},...,J_{2m} Jn+1,...,J2m的时间均设为0,并将其加入I,设 P 1 ≥ P 2 ≥ . . . ≥ P 2 m P_{1}\ge P_{2}\ge ... \ge P_{2m} P1≥P2≥...≥P2m。设最优调度使得每台机器恰有两个作业: J i 和 J j J_{i}和J_{j} Ji和Jj,则必有i ≤ \le ≤m, j > \gt >m,
否则若有最优调度O有i,j ≤ \le ≤m,则一定有某台机器上有 J s J_{s} Js和 J t J_{t} Jt,使得s,t>m。因为 P i , P j ≥ P s , P t P_{i},P_{j}\ge P_{s},P_{t} Pi,Pj≥Ps,Pt,交换 P j P_{j} Pj和 P t P_{t} Pt,则 P i + P t ≤ P s + P j P_{i}+P_{t}\le P_{s}+P_{j} Pi+Pt≤Ps+Pj,且 P i + P t ≤ P i + P j P_{i}+P_{t}\le P_{i}+P_{j} Pi+Pt≤Pi+Pj,所以交换后的调度O‘的最迟完成时间只可能减少,故O并不是最优调度,矛盾。
若有某调度算法O,有i,j > \gt >m,交换 J s J_{s} Js和 J t J_{t} Jt,使得s,t ≤ \le ≤m,此时 P i , P j ≤ P s , P t P_{i},P_{j}\le P_{s},P_{t} Pi,Pj≤Ps,Pt,交换 P j P_{j} Pj和 P t P_{t} Pt,则有 P i + P t ≤ P s + P t P_{i}+P_{t}\le P_{s}+P_{t} Pi+Pt≤Ps+Pt,且 P j + P s ≤ P s + P t P_{j}+P_{s}\le P_{s}+P_{t} Pj+Ps≤Ps+Pt,所以交换后的调度O‘的最迟完成时间只可能减少,故O并不是最优调度,矛盾。
因此必有最优调度使 J 1 , . . . , J m J_{1},...,J_{m} J1,...,Jm分别分配到 M 1 , . . . , M m M_{1},...,M_{m} M1,...,Mm上,当将 J n + 1 , . . . , J 2 m J_{n+1},...,J_{2m} Jn+1,...,J2m分配到M台机器上时,LPT是将长时间的作业分配到轻负载上,必于该最优调度结果相同。
即: A ( I ) O P T ( I ) ≤ 4 3 − 1 3 m \frac{A(I)}{OPT(I)}\le \frac{4}{3}-\frac{1}{3m} OPT(I)A(I)≤34−3m1
对于紧确界的证明如下:现假设每个作业的时间( P 1 , P 2 , . . . , P 2 m + 1 P_{1},P_{2},...,P_{2m+1} P1,P2,...,P2m+1)=(2m-1,2m-1,2m-2,2m-2,…,m+1,m+1,m,m,m),即 P k = 2 m − [ k + 1 2 ] , k = 1 , . . . , 2 m , P 2 m + 1 = m P_{k}=2m-[\frac{k+1}{2}], k=1,...,2m ,P_{2m+1}=m Pk=2m−[2k+1],k=1,...,2m,P2m+1=m,所以OPT(I)=3m(对应下图1),A(I)最坏的情况为前2m个作业在m个不同机器上同时完成,此时A(I)=4m-1(对应下图2,图中的n均为上述公式的m),此时可证明上确界的紧致性。