跳转至

代码模板

每天学完对应专题,就把这里的骨架跑一遍、换成自己的数据。比赛当天不要现学语法,只改数字和变量名。

熵权法 + TOPSIS · 评价类

import numpy as np

def entropy_weight(X):
    # X: n个方案 x m个指标,已做正向化+标准化到[0,1]
    X = X + 1e-12
    P = X / X.sum(axis=0)
    k = 1 / np.log(len(X))
    e = -k * (P * np.log(P)).sum(axis=0)
    d = 1 - e
    return d / d.sum()          # 各指标权重

def topsis(X, w):
    Z = X / np.sqrt((X**2).sum(axis=0))     # 标准化
    Zw = Z * w
    best, worst = Zw.max(axis=0), Zw.min(axis=0)
    d_best  = np.sqrt(((Zw - best )**2).sum(axis=1))
    d_worst = np.sqrt(((Zw - worst)**2).sum(axis=1))
    return d_worst / (d_best + d_worst)     # 得分,越大越优

AHP 层次分析法(一致性检验)· 评价类

import numpy as np

def ahp_weight(A):
    # A: 判断矩阵 (n x n)
    n = A.shape[0]
    eigvals, eigvecs = np.linalg.eig(A)
    idx = np.argmax(eigvals.real)
    w = eigvecs[:, idx].real
    w = w / w.sum()
    lam_max = eigvals[idx].real
    CI = (lam_max - n) / (n - 1)
    RI = {1:0,2:0,3:0.58,4:0.9,5:1.12,6:1.24,7:1.32,8:1.41,9:1.45}[n]
    CR = CI / RI if RI else 0
    return w, CR   # CR < 0.1 才算通过一致性检验

灰色预测 GM(1,1) · 预测类

import numpy as np

def gm11(x0, forecast=5):
    x1 = np.cumsum(x0)
    z1 = (x1[:-1] + x1[1:]) / 2
    B = np.column_stack((-z1, np.ones(len(z1))))
    Y = x0[1:].reshape(-1, 1)
    a, b = np.linalg.lstsq(B, Y, rcond=None)[0].flatten()
    def x1_hat(k): return (x0[0] - b/a) * np.exp(-a*k) + b/a
    pred = [x1_hat(0)] + [x1_hat(k) - x1_hat(k-1) for k in range(1, len(x0)+forecast)]
    return np.array(pred)

整数规划 · 优化类

import pulp

prob = pulp.LpProblem("demo", pulp.LpMaximize)
x = [pulp.LpVariable(f"x{i}", lowBound=0, cat="Integer") for i in range(3)]

prob += 5*x[0] + 4*x[1] + 3*x[2]          # 目标函数
prob += 2*x[0] + 3*x[1] +   x[2] <= 5     # 约束
prob += 4*x[0] +   x[1] + 2*x[2] <= 11
prob.solve()
print([v.varValue for v in x], pulp.value(prob.objective))

遗传算法骨架 · 优化类

import numpy as np

def genetic_algorithm(fitness_fn, dim, bounds, pop=50, gens=200, pc=0.8, pm=0.05):
    lo, hi = bounds
    population = lo + (hi - lo) * np.random.rand(pop, dim)
    for _ in range(gens):
        fit = np.array([fitness_fn(ind) for ind in population])
        parents = population[np.argsort(-fit)[:pop//2]]           # 选择:保留前50%
        kids = []
        while len(kids) < pop - len(parents):
            p1, p2 = parents[np.random.randint(len(parents), size=2)]
            mask = np.random.rand(dim) < 0.5
            child = np.where(mask, p1, p2) if np.random.rand() < pc else p1.copy()
            if np.random.rand() < pm:
                child += np.random.normal(0, 0.1, dim)
            kids.append(np.clip(child, lo, hi))
        population = np.vstack([parents, kids])
    fit = np.array([fitness_fn(ind) for ind in population])
    return population[np.argmax(fit)], fit.max()   # 换掉 fitness_fn 即可复用

图论最短路 · 图论

import networkx as nx

G = nx.Graph()
G.add_weighted_edges_from([("A","B",4), ("B","C",2), ("A","C",9)])
path = nx.shortest_path(G, "A", "C", weight="weight")
length = nx.shortest_path_length(G, "A", "C", weight="weight")
mst = nx.minimum_spanning_tree(G)   # 最小生成树同样一行搞定