2023年中国研究生数学建模竞赛C题 大规模创新类竞赛评审方案研究。
问题一 在每个评审阶段,作品通常都是随机分发的,每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性,不同专家评审的作品集合之间应有一些交集。但有的交集大了,则必然有交集小了,则可比性变弱。请针对3000支参赛队和125位评审专家,每份作品由5位专家评审的情况,建立数学模型确定最优的“交叉分发”方案,并讨论该方案的有关指标(自己定义)和实施细节。
这一问我们使用组合优化进攻:
import coptpy as cp
from coptpy import COPT
import math
import itertools
#第一问
# 定义评审专家数量和作品数量
num_experts = 125
num_works = 3000
# 定义每位评审专家最多评审的作品数量和每份作品需要被评审的专家数量
k = 400 # 最多评审的作品数量
m = 5 # 每份作品需要被评审的专家数量
env=cp.Envr()
# 创建线性规划问题
model = env.createModel("CrossDistribution")
# 创建二进制变量x(i, j)
x = model.addVars(num_experts, num_works, vtype=cp.COPT.BINARY, nameprefix="x")
# 定义目标函数:最大化交叉评审数量
model.setObjective(cp.quicksum(x[i, j] for i in range(num_experts) for j in range(num_works)), cp.COPT.MAXIMIZE)
# 添加约束条件
# 每位评审专家最多评审k份作品的约束
for i in range(num_experts):
model.addConstr(cp.quicksum(x[i, j] for j in range(num_works)) <= k)
# 每份作品需要被评审m位专家的约束
for j in range(num_works):
model.addConstr(cp.quicksum(x[i, j] for i in range(num_experts)) == m)
# 求解线性规划问题
model.solve()
# 打印结果
print("Status:", model.status)
if model.status == cp.COPT.OPTIMAL:
# 打印每位评审专家评审的作品列表
for i in range(num_experts):
selected_works = [j for j in range(num_works) if x[i, j].X == 1]
print(f"评审专家 {i+1} 评审的作品列表:{selected_works}")
# 打印最大化的交叉评审数量
print("最大化的交叉评审数量:", model.objVal)
else:
print("模型没有找到最优解")
这段代码轻松简单解决了这个问题,我们来看看节选的运行结果:
Cardinal Optimizer v7.1.3. Build date Apr 29 2024
Copyright Cardinal Operations 2024. All Rights Reserved
Model fingerprint: d6debe07
Using Cardinal Optimizer v7.1.3 on Windows
Hardware has 4 cores and 8 threads. Using instruction set X86_AVX512_E1 (14)
Maximizing a MIP problem
The original problem has:
3125 rows, 375000 columns and 750000 non-zero elements
375000 binaries
Starting the MIP solver with 8 threads and 32 tasks
Presolving the problem
The presolved problem has:
3125 rows, 375000 columns and 750000 non-zero elements
375000 binaries
Nodes Active LPit/n IntInf BestBound BestSolution Gap Time
0 1 -- 0 3.750000e+05 -- Inf 1.70s
H 0 1 -- 0 3.750000e+05 1.500000e+04 96.0% 2.65s
0 1 -- 0 1.500000e+04 1.500000e+04 0.00% 5.85s
1 0 0.0 0 1.500000e+04 1.500000e+04 0.00% 5.90s
1 0 0.0 0 1.500000e+04 1.500000e+04 0.00% 5.90s
Best solution : 15000.000000000
Best bound : 15000.000000000
Best gap : 0.0000%
Solve time : 5.93
Solve node : 1
MIP status : solved
Solution status : integer optimal (relative gap limit 0.0001)
Violations : absolute relative
bounds : 0 0
rows : 0 0
integrality : 0
Status: 1
评审专家 1 评审的作品列表:[2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999]
这段运行结果可以直接丢到附件去,至此第一问被我们秒杀了。下面我们看看后面的问题吧!
问题二 在评审中采用标准分(附件1)为基础的排序方法,其假设是不同评审专家评审的作品集合的学术水平分布相同。但在大规模创新类竞赛评审中,通常任意两位专家评审的作品只有小部分是共同的,绝大多数作品是不同的(见问题一),而且每位专家只看到作品集合的很小部分,因此标准分评审方案的假设可能不成立,需要探索新的评审方案。请选择两种或两种以上现有或自己设计的评审方案和题目附件数据,分析每位专家、每份作品原始成绩、调整之后(如取标准分)成绩的分布特点,按不同方案进行排序,并设法比较这些方案的优劣。进而针对大规模创新类竞赛的评审,设计新的标准分(公式)计算模型。另外,一般认为经多位专家协商一致的获奖论文具有最大的可信度,附件2提供的数据1,其第二评审阶段评选出的一等奖作品排序是经专家协商取得一致的,请利用这批数据,改进你们的标准分计算模型。
这一问又是一个统计的问题,不过没有优化,没关系,我们SPSSPRO进攻:
在进行这部操作之前,我们先看看怎么预处理这个数据,其实三个数据长的差不多,不过,我们要修改一下列名,方便spsspro和python读取。
强特征是最终成绩和第二次评审成绩专家二原始分。
这个结论就已经可以说明一些问题了。
最后是问题三和问题四,我们上代码吧:
import pandas as pd
import numpy as np
## 绘图函数库
import matplotlib.pyplot as plt
import seaborn as sns
data = pd.read_excel(r'D:\桌面\华为杯资料合集\题目\C题\预处理数据\已经处理数据1.xlsx')
# In[3]:
data.head()
# In[4]:
data.describe()
# In[5]:
data.info()
# In[6]:
import pandas as pd
# 提取专家编码列
expert_codes_first_review = data[['第一次评审成绩专家一专家编码', '第一次评审成绩专家二专家编码',
'第一次评审成绩专家三专家编码']]
expert_codes_second_review = data[['第二次评审成绩专家一专家编码', '第二次评审成绩专家二专家编码',
'第二次评审成绩专家三专家编码']]
# 统计每列的唯一专家编码个数
unique_experts_first_review = pd.unique(expert_codes_first_review.values.ravel())
unique_experts_second_review = pd.unique(expert_codes_second_review.values.ravel())
print(f'第一次评审中的唯一专家编码个数: {len(unique_experts_first_review)}')
print(f'第二次评审中的唯一专家编码个数: {len(unique_experts_second_review)}')
# 检查是否三次评审使用的是同一批专家
common_experts = set(unique_experts_first_review) & set(unique_experts_second_review)
print(f'三次评审中共同的专家编码个数: {len(common_experts)}')
print(f'共同的专家编码: {common_experts}')
# In[15]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 创建一个新的列,用于标记不同的奖项类别
data['奖项类别'] = data['奖项'].map({
'一等奖': '一等奖',
'二等奖': '二等奖',
'三等奖': '三等奖',
'未获奖': '未获奖'
})
# 设置绘图风格
sns.set(style="whitegrid")
# 创建一个绘图窗口
plt.figure(figsize=(14, 10))
# 绘制一等奖的最终成绩分布图
plt.subplot(2, 2, 1)
sns.histplot(data[data['奖项类别'] == '一等奖']['最终成绩'], bins=30, kde=True)
plt.title('一等奖最终成绩分布')
# 绘制二等奖的最终成绩分布图
plt.subplot(2, 2, 2)
sns.histplot(data[data['奖项类别'] == '二等奖']['最终成绩'], bins=30, kde=True)
plt.title('二等奖最终成绩分布')
# 绘制三等奖的最终成绩分布图
plt.subplot(2, 2, 3)
sns.histplot(data[data['奖项类别'] == '三等奖']['最终成绩'], bins=30, kde=True)
plt.title('三等奖最终成绩分布')
# 绘制未获奖的最终成绩分布图
plt.subplot(2, 2, 4)
sns.histplot(data[data['奖项类别'] == '未获奖']['最终成绩'], bins=30, kde=True)
plt.title('未获奖最终成绩分布')
# 调整布局并显示图形
plt.tight_layout()
plt.show()
plt.figure(figsize=(14, 10))
sns.boxplot(x='奖项类别', y='最终成绩', data=data)
plt.title('不同奖项类别最终成绩的箱线图')
plt.show()
# In[18]:
import pandas as pd
# 提取每轮评审的评委列
first_round_experts = data[['第一次评审成绩专家一专家编码', '第一次评审成绩专家二专家编码',
'第一次评审成绩专家三专家编码', '第一次评审成绩专家四专家编码',
'第一次评审成绩专家五专家编码']]
second_round_experts = data[['第二次评审成绩专家一专家编码', '第二次评审成绩专家二专家编码',
'第二次评审成绩专家三专家编码']]
# 合并所有评委信息到一个列表中
all_experts = pd.concat([first_round_experts, second_round_experts], axis=1)
# 将所有评委信息合并到一个长格式的数据框中
all_experts_long = all_experts.melt(value_name='Expert').dropna()['Expert']
# 统计每个评委的评选次数
expert_counts = all_experts_long.value_counts()
# 打印每个评委的评选次数
print(expert_counts)
# In[19]:
import pandas as pd
# 提取每轮评审的评委列
first_round_experts = data[['第一次评审成绩专家一专家编码', '第一次评审成绩专家二专家编码',
'第一次评审成绩专家三专家编码']]
second_round_experts = data[['第二次评审成绩专家一专家编码', '第二次评审成绩专家二专家编码',
'第二次评审成绩专家三专家编码']]
# 合并所有评委信息到一个列表中
all_experts = pd.concat([first_round_experts, second_round_experts], axis=1)
# 将所有评委信息合并到一个长格式的数据框中
all_experts_long = all_experts.melt(value_name='Expert').dropna()['Expert']
# 统计每个评委的评选次数
expert_counts = all_experts_long.value_counts().reset_index()
expert_counts.columns = ['Expert', 'Count']
# 保存到 Excel 文件
output_file = r'D:\桌面\华为杯资料合集\题目\C题\预处理数据\expert_counts.xlsx'
expert_counts.to_excel(output_file, index=False)
print(f'统计结果已保存到 {output_file}')
# In[23]:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 绘图
plt.figure(figsize=(14, 7))
# 原始分数的分布图
plt.subplot(1, 2, 1)
sns.histplot(data[['第一次评审成绩专家一原始分', '第二次评审成绩专家一原始分']], kde=True, palette='husl', binwidth=2)
plt.title('Distribution of Original Scores')
plt.xlabel('Original Score')
plt.ylabel('Frequency')
plt.legend(title='Evaluation Rounds', labels=['First Round', 'Second Round'])
# 标准化分数的分布图
plt.subplot(1, 2, 2)
sns.histplot(data[['第一次评审成绩专家一标准分', '第二次评审成绩专家一标准分']], kde=True, palette='husl', binwidth=0.5)
plt.title('Distribution of Standardized Scores')
plt.xlabel('Standardized Score')
plt.ylabel('Frequency')
plt.legend(title='Evaluation Rounds', labels=['First Round', 'Second Round'])
plt.tight_layout()
plt.show()
# In[29]:
import pandas as pd
import scipy.stats as stats
# 正态分布检验函数
def normality_test(column_data):
stat, p_value = stats.shapiro(column_data)
return {'Statistic': stat, 'P-Value': p_value}
# 对每个专家在每次评审中的分数进行正态分布检验
# 专家一
print("专家一 - 第一次评审:")
result = normality_test(data['第一次评审成绩专家一原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
print("\n专家一 - 第二次评审:")
result = normality_test(data['第二次评审成绩专家一原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
# 专家二
print("\n专家二 - 第一次评审:")
result = normality_test(data['第一次评审成绩专家二原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
print("\n专家二 - 第二次评审:")
result = normality_test(data['第二次评审成绩专家二原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
# 专家三
print("\n专家三 - 第一次评审:")
result = normality_test(data['第一次评审成绩专家三原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
print("\n专家三 - 第二次评审:")
result = normality_test(data['第二次评审成绩专家三原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
# 专家四
print("\n专家四 - 第一次评审:")
result = normality_test(data['第一次评审成绩专家四原始分'])
print(f" Statistic: {result['Statistic']:.4f}")
print(f" P-Value: {result['P-Value']:.4f}")
if result['P-Value'] < 0.05:
print(" The data is likely not normally distributed.")
else:
print(" The data is likely normally distributed.")
最后是两段杉数求解器优化的代码
import coptpy as cp
from coptpy import COPT
import math
import itertools
#第四问
env=cp.Envr()
# 创建模型
model = env.createModel("Optimization")
# 定义决策变量
x = model.addVars(2, vtype=cp.COPT.CONTINUOUS, nameprefix="x")
# 定义目标函数:最小化 x[0]^2 + x[1]^2
model.setObjective(x[0]**2 + x[1]**2, cp.COPT.MINIMIZE)
# 添加约束条件:x[0] + x[1] = 1
model.addConstr(x[0] + x[1] == 1)
# 求解模型
model.solve()
# 输出结果
if model.status == cp.COPT.OPTIMAL:
optimal_solution = [x[i].X for i in range(2)]
optimal_value = model.objVal
print("最优解:", optimal_solution)
print("最优值:", optimal_value)
else:
print("模型没有找到最优解")
Cardinal Optimizer v7.1.3. Build date Apr 29 2024
Copyright Cardinal Operations 2024. All Rights Reserved
Model fingerprint: 183fdc56
Using Cardinal Optimizer v7.1.3 on Windows
Hardware has 4 cores and 8 threads. Using instruction set X86_AVX512_E1 (14)
Minimizing a QP problem
The original problem has:
1 rows, 2 columns and 2 non-zero elements
2 quadratic objective elements
The presolved problem has:
1 rows, 2 columns and 2 non-zero elements
2 quadratic objective elements
Starting barrier solver using 4 threads
Problem info:
Dualized in presolve: No
Range of matrix coefficients: [1e+00,1e+00]
Range of rhs coefficients: [1e+00,1e+00]
Range of bound coefficients: [0e+00,0e+00]
Range of cost coefficients: [0e+00,0e+00]
Range of quadcost coefficients: [1e+00,1e+00]
Factor info:
Number of free columns: 0
Number of dense columns: 0
Number of matrix entries: 1.000e+00
Number of factor entries: 1.000e+00
Number of factor flops: 0.000e+00
Iter Primal.Obj Dual.Obj Compl Primal.Inf Dual.Inf Time
0 +9.68000000e+00 -8.68000000e+00 4.73e+01 3.40e+00 7.35e+00 0.02s
1 +5.12016885e-01 -5.90836971e+00 6.51e+00 1.19e-02 2.58e-02 0.02s
2 +5.00000031e-01 +4.99086847e-01 9.13e-04 3.09e-08 6.68e-08 0.02s
3 +5.00000000e-01 +4.99999999e-01 9.13e-10 3.09e-14 6.69e-14 0.02s
Barrier status: OPTIMAL
Primal objective: 5.00000000e-01
Dual objective: 4.99999999e-01
Duality gap (abs/rel): 9.13e-10 / 9.13e-10
Primal infeasibility (abs/rel): 3.09e-14 / 3.09e-14
Dual infeasibility (abs/rel): 6.69e-14 / 6.69e-14
Postsolving
Solving finished
Status: Optimal Objective: 5.0000000000e-01 Iterations: 3 Time: 0.03s
最优解: [0.5000000000000154, 0.5000000000000154]
最优值: 0.5000000000000309
这一段代码求解的是优化过后的评委评选的数量
import coptpy as cp
from coptpy import COPT
import math
import itertools
# 示例数据:每轮的论文数量和评委数量
num_papers_round1 = 2015 # 示例数量
num_papers_round2 = 352
num_papers_round3 = 352
num_experts = 10 # 假设有10个评委
env=cp.Envr()
# 创建模型
m = env.createModel('review_allocation')
# 变量:评委i在轮次j上的评审次数
x = {}
for i in range(num_experts):
for j in range(3): # 0: 第一轮, 1: 第二轮, 2: 第三轮
x[i, j] = m.addVar(vtype=COPT.INTEGER, name=f'x_{i}_{j}')
# 目标函数:最小化每个评委三轮阅卷总和的方差和极差
mean_review = num_papers_round1 + num_papers_round2 + num_papers_round3
# 添加目标函数
objective = 0
for i in range(num_experts):
total_reviews = sum(x[i, j] for j in range(3))
mean = mean_review / num_experts
variance = (total_reviews - mean) ** 2
objective += variance
m.setObjective(objective, COPT.MINIMIZE)
# 添加约束:每轮评审的总论文数量
for j in range(3):
m.addConstr(sum(x[i, j] for i in range(num_experts)) == [num_papers_round1, num_papers_round2, num_papers_round3][j])
# 求解模型
m.solve()
# 输出结果
if m.status == COPT.OPTIMAL:
for i in range(num_experts):
print(f'评委{i}的评分分配:')
for j in range(3):
print(f' 第{j+1}轮: {x[i, j].x}')
print('优化完成。')
else:
print('没有找到最优解。')
Cardinal Optimizer v7.1.3. Build date Apr 29 2024
Copyright Cardinal Operations 2024. All Rights Reserved
Model fingerprint: e2a91c70
Using Cardinal Optimizer v7.1.3 on Windows
Hardware has 4 cores and 8 threads. Using instruction set X86_AVX512_E1 (14)
Minimizing a MIQP problem
The original problem has:
3 rows, 30 columns and 30 non-zero elements
30 integers
60 quadratic objective elements
Starting the MIP solver with 8 threads and 32 tasks
Presolving the problem
The presolved problem has:
13 rows, 50 columns and 70 non-zero elements
10 SOC rows and 30 non-zero elements
30 integers
Nodes Active LPit/n IntInf BestBound BestSolution Gap Time
0 1 -- 0 -1.404663e+07 -- Inf 0.02s
H 0 1 -- 0 -1.404663e+07 6.653665e+06 147.4% 0.02s
0 1 -- 11 9.000000e-01 6.653665e+06 100.0% 0.05s
H 0 1 -- 11 9.000000e-01 1.600835e+06 100.0% 0.06s
H 0 1 -- 11 9.000000e-01 6.131485e+04 100.0% 0.06s
0 1 -- 8 9.000000e-01 6.131485e+04 100.0% 0.06s
0 1 -- 10 9.000000e-01 6.131485e+04 100.0% 0.06s
0 1 -- 10 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 2 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 11 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 10 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 8 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 3 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 0 9.000000e-01 6.131485e+04 100.0% 0.07s
0 1 -- 5 9.000000e-01 6.131485e+04 100.0% 0.07s
Nodes Active LPit/n IntInf BestBound BestSolution Gap Time
0 1 -- 4 9.000000e-01 6.131485e+04 100.0% 0.08s
0 1 -- 4 9.000000e-01 6.131485e+04 100.0% 0.08s
0 1 -- 4 9.000000e-01 6.131485e+04 100.0% 0.08s
* 0 1 -- 0 9.000000e-01 9.000000e-01 0.00% 0.08s
0 1 -- 0 9.000000e-01 9.000000e-01 0.00% 0.08s
1 0 89.0 0 9.000000e-01 9.000000e-01 0.00% 0.08s
1 0 89.0 0 9.000000e-01 9.000000e-01 0.00% 0.08s
Best solution : 0.900000000
Best bound : 0.900000000
Best gap : 0.0000%
Solve time : 0.08
Solve node : 1
MIP status : solved
Solution status : integer optimal (relative gap limit 0.0001)
Violations : absolute relative
bounds : 0 0
rows : 0 0
integrality : 0
SOC rows : 0
评委0的评分分配:
第1轮: 271.99999999999636
第2轮: 0.0
第3轮: 0.0
评委1的评分分配:
第1轮: 192.0000000000166
第2轮: 80.00000000000193
第3轮: 0.0
评委2的评分分配:
第1轮: 0.0
第2轮: 271.99999999999807
第3轮: 0.0
评委3的评分分配:
第1轮: 192.00000000000165
第2轮: 0.0
第3轮: 80.00000000000773
评委4的评分分配:
第1轮: 271.99999999999636
第2轮: 0.0
第3轮: 0.0
评委5的评分分配:
第1轮: 271.99999999999636
第2轮: 0.0
第3轮: 0.0
评委6的评分分配:
第1轮: 0.0
第2轮: 0.0
第3轮: 271.99999999999227
评委7的评分分配:
第1轮: 270.99999999999994
第2轮: 0.0
第3轮: 0.0
评委8的评分分配:
第1轮: 271.99999999999636
第2轮: 0.0
第3轮: 0.0
评委9的评分分配:
第1轮: 271.99999999999636
第2轮: 0.0
第3轮: 0.0
优化完成。
#修改一处报错,字体显示不完全,感谢学弟的贡献
import pandas as pd
import numpy as np
## 绘图函数库
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties
# 设置我们需要用到的中文字体(字体文件地址)
my_font = FontProperties(fname=r"c:\windows\fonts\SimHei.ttf", size=12)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel(r'已经处理数据1.xlsx')
# 创建一个新的列,用于标记不同的奖项类别
data['奖项类别'] = data['奖项'].map({
'一等奖': '一等奖',
'二等奖': '二等奖',
'三等奖': '三等奖',
'未获奖': '未获奖'
})
# 设置绘图风格
sns.set(style="whitegrid")
# 创建一个绘图窗口
plt.figure(figsize=(14, 10))
# 绘制一等奖的最终成绩分布图
plt.subplot(2, 2, 1)
sns.histplot(data[data['奖项类别'] == '一等奖']['最终成绩'], bins=30, kde=True)
plt.title('一等奖最终成绩分布',fontproperties=my_font)
plt.xlabel('最终成绩', fontproperties=my_font)
# 绘制二等奖的最终成绩分布图
plt.subplot(2, 2, 2)
sns.histplot(data[data['奖项类别'] == '二等奖']['最终成绩'], bins=30, kde=True)
plt.title('二等奖最终成绩分布',fontproperties=my_font)
plt.xlabel('最终成绩', fontproperties=my_font)
# 绘制三等奖的最终成绩分布图
plt.subplot(2, 2, 3)
sns.histplot(data[data['奖项类别'] == '三等奖']['最终成绩'], bins=30, kde=True)
plt.title('三等奖最终成绩分布',fontproperties=my_font)
plt.xlabel('最终成绩', fontproperties=my_font)
# 绘制未获奖的最终成绩分布图
plt.subplot(2, 2, 4)
sns.histplot(data[data['奖项类别'] == '未获奖']['最终成绩'], bins=30, kde=True)
plt.title('未获奖最终成绩分布',fontproperties=my_font)
plt.xlabel('最终成绩', fontproperties=my_font)
# 调整布局并显示图形
plt.tight_layout()
plt.show()