Archive for the ‘modeling’ tag
沒有見過比這個更丑的Python程序了
可以大言不慚地吼著說:“我寫的!”
複用不好,很多冗餘代碼。設計不好,接口不明。寫法丑,不夠Pythonic。
唯一的優點是它確實能解決我的問題。數學建模一個題目“最佳陣容”,要算出所有得分會大于某個特定分數的出場陣容。
其實是一個0-1背包問題,但是約束條件比較多,算法自己又不在行,用回溯剪枝寫不出來。Lingo的規劃又只能做出一個解。
還好,動手算了一下,這個組合數也不過百萬級別,這對於現代的電腦完全是小case。所以用最丑的辦法寫了一個出來,當然,還是有點優化的。
程序我也不打算別人看懂,自己以后估計也不會再看,所以就不多解釋了。放這里做個留念,看看自己寫的程序有多丑。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Liu Wei
def combination(items, n=None):
if n is None:
n = len(items)
for i in xrange(len(items)):
v = items[i:i+1]
if n == 1:
yield v
else:
rest = items[i+1:]
for c in combination(rest, n-1):
yield v + c
def permutation(items, n=None):
if n is None:
n = len(items)
for i in xrange(len(items)):
v = items[i:i+1]
if n == 1:
yield v
else:
rest = items[:i] + items[i+i:]
for p in permutation(rest, n-1):
yield v + p
# highest score for each player
scores = [
[9.4, 9.8, 10, 9.5, 9.4, 9.9, 10, 10, 9.4, 9.7],
[10, 9.4, 9.5, 9.9, 9.7, 9.9, 10, 10, 9.8, 9.5],
[9.8, 10, 9.4, 9.7, 9.3, 9.1, 9.3, 9.9, 10, 9.6],
[9.9, 9.6, 10, 10, 9.9, 9.4, 9.8, 9.8, 9.9, 9.8]
]
# final array
array = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
# sparse array for 6 cols
sparse_array = [
[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
]
def __sparse_array_check_valid():
global sparse_array
# 6 cols
for i in xrange(6):
sum = 0
for j in xrange(4):
sum += sparse_array[j][i]
if sum > 3:
return False
return True
def __sparse_array_init():
global sparse_array
sparse_array = [[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
[0, 0, 0, 0, 0, 0], \
]
def __sparse_array_set_row(p, r):
global sparse_array
a, b = p
sparse_array[r][a] = 1
sparse_array[r][b] = 1
def __sparse_array_clear_row(r):
global sparse_array
for i in xrange(len(sparse_array[r])):
sparse_array[r][i] = 0
def sparse_array_output():
global sparse_array
print sparse_array
# generator for sparse arrays
def sparse_array_generator():
global sparse_array
# 4 rows
__sparse_array_init()
for r0 in combination(range(6), 2):
__sparse_array_clear_row(0)
__sparse_array_set_row(r0, 0)
for r1 in combination(range(6), 2):
__sparse_array_clear_row(1)
__sparse_array_set_row(r1, 1)
for r2 in combination(range(6), 2):
__sparse_array_clear_row(2)
__sparse_array_set_row(r2, 2)
for r3 in combination(range(6), 2):
__sparse_array_clear_row(3)
__sparse_array_set_row(r3, 3)
if __sparse_array_check_valid():
yield sparse_array
# sparse_array_output()
def __array_set_col(c):
global array
for i in xrange(len(array)):
array[i]1 = 1
def __array_clean_col(c):
global array
for i in xrange(len(array)):
array[i]1 = 0
def __array_init():
global array
array = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
def set_allround_player(a):
for i in a:
__array_set_col(i)
def set_individual_player(sa, s):
global array
for i in range(4):
for j in range(6):
array[i][s[j]] = sa[i][j]
def array_generator():
global array
for g in combination(range(10), 4):
# select cols for sparse array in big array
s = [i for i in range(10) if i not in g]
__array_init();
# start to manipulate the array
# first select all-round player
set_allround_player(g)
# then cope with individual event player
for sa in sparse_array_generator():
set_individual_player(sa, s)
yield array
def calc_score(a):
sum = 0
for i in range(len(a)):
for j in range(len(a[0])):
sum += a[i][j] * scores[i][j]
return sum
def final_generator():
for a in array_generator():
total_score = calc_score(a)
if total_score >= 236.2:
yield [a, total_score]
import os
os.chdir("d:/liuw/")
f = file("output", 'a')
for solution, total_score in final_generator():
f.write(str(solution))
f.write('\n')
f.write(str(total_score))
f.write('\n\n')
f.close()
用到了大量的generator,因為怕會內存不足。但是總yield一個全局數組總覺得有點別扭。話說我們這次的做題目用到了Lingo、Python、Matlab和C,果然是程序員的命,全部學計算機的人組個隊還是有好處的。
最後在電腦上跑了5分鐘左右,結果就出來了。假如想再快點,還可以做雙核並行計算。不過自己這方面沒什麽研究,程序也要得比較急,就沒有多管。