2025MathorCup数学应用挑战赛B题
目录
模型建立与求解
1.问题一的模型建立与求解
1.1 搬迁补偿模型设计
1.2 住户是否搬迁的应对策略与分析
1.3 定量讨论
2.问题二的模型建立与求解
2.1 搬迁方案模型的优化介绍
2.2 模型的评估
2.3 模型结果
3.问题三的模型建立与求解
3.1 拐点存在性分析模型的建立
3.2 模型的评估
3.2 结果计算
4.问题四的模型建立与求解
4.1 智能计算“平移置换”决策模型建立
4.2 算法优化介绍
4.3 算法评价
4.4 结果说明
模型建立与求解
1.问题一的模型建立与求解
1.1 搬迁补偿模型设计
1.依据面积补偿,前提条件居民搬迁迁入地块面积S新需要满足So≤Sn≤1.3×So。补偿范围依据问题介绍:若Sn>So,开发商需要承担面积差对应的潜在租金损失。即面积补偿:
Sn∈[So,1.3×So]
2.依据采光补偿,我们将问题的舒适等级按照正南=正北(等级为1)>东厢(等级为2)>西厢(等级为3)划分。为了有效推动居民搬迁。迁入条件设置为:迁入地块的舒适度等级需≥原地块。设计补偿策略,若迁入地块舒适度等级提升(如从西厢迁入东厢),可以减少修缮费用;若等级相同,需要通过修缮来进行补偿。即R(i) ∈ {1,2,3} ,R('南')=R('北')=1,R('东')=2,R('西')=3,补光补偿:
R(o) ≤ R(n)
3.针对修缮补偿,从问题已知每户修缮的费用上限为20万元。第一种情况若迁入地块条件显著优于原地块,可以不修缮。第二种情况若迁入地块于原地块相近,需要按照修缮费用上限补偿。修缮费用与舒适度差值挂钩。即修缮补偿:
Snew_cost = max(0, 20 × (1 - (r - 1)/0.3 - ΔR × 0.2))
其中:r = Sn/So (面积比);ΔR = R(o) - R(n) (朝向等级差)
4.将面积补偿、采光补偿以及修缮补偿加合得出一次搬迁的总费用:
Stotal_cost = 3 + Snew_cost + (Sn - So) × p × 365 × 10 / 10000
其中:p = 15(当朝向为南/北)或 8(其他朝向)万元/平方米·年
1.2 住户是否搬迁的应对策略与分析
结合现实情况分析,决定住户是否搬迁的其他影响因素分别为迁入地块的位置,房屋的密集度,社区的归属感,以及搬迁的成本。
- 依据实际情况进行分析,靠近主街区可能噪音大但交通便利,我们需要对噪音敏感的住户,优先分配远离街道的地块;可以选择对交通便利需求高的住户,并进行补偿提供交通补贴。
- 房屋在高密集度区域采光、隐私较差,倘若住户能够搬迁,我们可以为能够搬迁的住户提供额外的修缮或者面积补偿。
- 搬迁可能会导致住户的原有社交网络断裂。尽量将同一院落的住户集中搬迁至同一院中,或者为能够搬迁的住户提供社区活动经费,增进住户之间的交流使得新住户能够更好的适应新居住区。
1.3 定量讨论
对问题一的策略进行定量讨论,我们通过补偿方案需要综合面积、采光、修缮以及其他环境因素,通过定量模型计算每户的搬迁成本,并结合住户心理和社区关系优化决策。
问题一通过面积进行考虑,对附件1的前五为住户的搬迁结果进行定量分析通过计算原来住户的地块ID转到迁入地块ID的成本。结果表如下:
表1 定量结果表
地块ID | 迁入地块ID | 搬迁成本(万元) |
3 | 227 | 3.00 |
5 | 410 | 3.18 |
7 | 112 | 3.18 |
9 | 442 | 3.48 |
14 | 98 | 3.00 |
通过对问题的定量分析,检验了搬迁补偿模型范围的可行性。同时通过模型进行检验出当前住户数量有113户,可搬迁住户数为112户,搬迁比例为99.1%,因此“平移置换”搬迁规划很有必要。
2.问题二的模型建立与求解
2.1 搬迁方案模型的优化介绍
我们在问题一的范围条件内,为模型设计目标条件,需要同时满足搬迁决策对腾出完整院落数量最大,腾出的完整院落需要尽可能毗邻。通过分别计算面积补偿、采光补偿、沟通成本、面积损失以及修缮成本,通过搬迁规划模型尝试将其搬迁到空置地块,顺序优化包括,优先不修缮尽量的避免修缮成本,以降低成本;另一方面在预算允许的情况下,修缮部分地块以满足搬迁需求,同时限制了最多的修缮成本为20万元。最终使得投入的Stotal_cost目标成本最小,达到的最终收入以及W盈利最大。
通过附件2提供的老城街区详细图示观察可知,毗邻的院落ID大部分是连续的,因此将院落的毗邻情况我们可以近似于相邻院落ID差1。
2.2 模型的评估
我们通过回答的问题进行分析,设计评价指标,我们对搬迁质量进行评估。首先我们对搬迁成本分布,面积补偿与成本关系,采光改善情况,院落完整化效果进行可视化分析如图1:
图1模型各变量可视化效果评估
通过可视化结果显示,搬迁成本花费少的频率较大,同时我们发现随着面积补偿的增多成本也在逐渐增多,采光补偿的趋势大部分比较分布于零采光补偿,能够腾出完整院落的数量占比大于50%。因此该模型有很好的应用价值。
通过模型可视化,我们也对搬迁的质量进行评价。搬迁质量的结果如下表所示:
表 2 问题二搬迁质量结果表
面积补偿占比 | 采光补偿占比 | 平均每平方米成本 |
100% | 100% | 4694.86 元/平方米 |
通过模型的搬迁质量结果,以及可视化结果显示,该模型在解决问题二有着很好的使用价值,能够帮助解决类似于问题二的实际问题。
2.3 模型结果
通过模型建立以及验证了模型的在问题二中的可行性,我们对问题二的结果进行计算。我们通过将居民的搬迁方式的结果通过分析,最终结果统计在下表(只展示部分结果,完整结果表如附件表1采光负值含义是产生采光补偿,数值越小,采光补偿程度越大):
表3 搬迁最终结果统计表
原地块ID | 新地块ID | 面积补偿 | 采光补偿 | 成本消耗 | 是否修缮 |
241 | 52 | 4 | -2 | 146800 | FALSE |
242 | 56 | 0 | 0 | 30000 | FALSE |
243 | 79 | 0 | 0 | 30000 | FALSE |
385 | 419 | 5 | 0 | 176000 | FALSE |
38 | 46 | 1 | 0 | 84750 | FALSE |
39 | 10 | 0 | 0 | 30000 | FALSE |
41 | 51 | 3 | -2 | 117600 | FALSE |
452 | 63 | 5 | 0 | 176000 | FALSE |
49 | 123 | 3 | 0 | 194250 | FALSE |
5 | 68 | 2 | 0 | 139500 | FALSE |
通过统计结果显示腾出完整院落总面积为11225.0平方米,总的拆迁成本为25998500.0万元,历经十年后的盈利8515278900万元。
3.问题三的模型建立与求解
3.1 拐点存在性分析模型的建立
在问题一的范围模型基础上,我们首先对原始数据进行了全面的处理。这一阶段的目标是将数据按照一定的标准进行分类,以便后续建模时能够更高效地利用信息。具体我们将数据划分为两类:一是有住户的院子,另一类是空闲的院子。通过引入目标与评估指标m:
m = 总收益 / 总成本
再对模型利用最大化“性价比(m)”≤20进行限制;其中总收益:腾出的土地面积×30元/平方米/天×年;总成本:包括搬迁成本(3万元/户)、装修补贴(30万元/户)和面积差价补偿。
我们再对模型使用模拟退火算法进行全局优化,模拟退火(simulated annealing, SA)算法是一种基于固体退火过程来搜索全局最优解的算法[2],用于在求解空间中寻找近似最优解,使用模型退火辅助对目标模型的计算。模拟退火用于拐点存在性分析模型的具体流程如下图:
图2 模拟退火应用该模型流程
初始化参数包括初始温度T=1000,最低温度Tmin=1,温度衰减系数alpha=0.95;主循环通过随机改变院落的顺序,计算新解的总成本和总收益,同时依据温度衰减系数降低温度,最终输出结果。
3.2 模型的评估
我们为了能够评估上述模型的性能,我们通过结果可视化,关键指标计算,模型稳定性以及搬迁方案合理性检查。
通过设计收敛性分析绘制性价比与迭代次数的关系变化曲线,在通过关键指标的稳定性评分,对迁移方案的验证等角度对模型进行的分析。下面是结果可视化包括变化曲线,标记最大性价比点以及计算收敛速度如下图:
图 3 可视化收敛性分析
通过对结果的可视化收敛性进行分析判断,我们通过退火算法辅助模型寻找拐点,利用退火算法的特点,充分的体现出了模型的稳定性,通过搬迁成本的分布体现出模型的有利性。
我们再通过对模型稳定性进行评分和对迁移方案的验证两个角度,对模型结果提出检验,评估详细的结果如下表:
表4 稳定性评分和迁移方案检验表
稳定性评分(1.0表示最稳定) | 总移动次数 | 重复的目标图 | 约束违规 |
1.00 | 111 | 19 | 0 |
通过可视化以及各个指标的验证充分体现出模型的稳定性和可靠性,再使用退火算法的辅助,能够解决大部分类似于问题三的现实情况。
3.2 结果计算
依据对建立模型的分析,验证了模型的稳定性和可靠性,我们使用模型进行计算得出问题三的结果。依据结果显示,问题存在增益的拐点,拐点的m值为39.19,通过计算最终的成本为3687.53万元,最终收益为144529.05万元,最终结果显示收益达到拐点收终止通过计算,搬迁方案结果表(只展示部分结果,完整结果表如附录表2)如下:
表5 搬迁规划结果
原地块ID | 搬入地块ID | 搬迁成本 |
210 | 27 | 33.216 |
211 | 11 | 33.072 |
29 | 11 | 33.024 |
30 | 27 | 33.12 |
31 | 4 | 33.288 |
376 | 27 | 33.168 |
224 | 1 | 33.24 |
225 | 6 | 33.432 |
通过使用该模型能够给出很好的搬迁方案。
4.问题四的模型建立与求解
4.1 智能计算“平移置换”决策模型建立
结合问题二和问题三的模型计算,我们将两个问题的模型总结在一起。基于搬迁方案模型和拐点存在性分析模型,我们将使用拐点存在性以及优化后的搬迁方案模型对问题四的智能计算决策模型进行设计。
在问题二和问题三的基础上结合现实考虑,我们对每个居民的资源进行限制,每个居民只能参与搬迁一次。再对下面新的问题四的结果进行说明。
4.2 算法优化介绍
我们通过增加约束条件对问题模型进行升级,在文章最后我们对问题模型使用多种优化算法进行检验,我们通过对不同算法的评价,能够为智能计算设计提出有效的方案。下面我们对问题四用到的所有优化算法进行介绍。
(1)模拟退火算法
我们通过继续使用问题三的模拟退火算法,结合问题四的模型进行计算,初始解生成,我们将修改问题三的初始解为随机选择不冲突的搬迁对构成初始可行解,并确保每个居民和空地块最多被选择一次。退火过程控制随着温度降低,接受劣解的概率减小,在高温阶段广泛探索,低温阶段精细探索的方式,对问题进行求解。
(2)灰狼算法
灰狼算法优化实现了灰狼的社会等级,模拟了灰狼的狩猎行为;通过位置更新机制,每只狼的位置根据等级进行更新,使用线性递减的参数来控制探索和开发;适应度函数通过考虑腾空院落的收益情况以及搬迁的总成本和性价比约束。我们通过显示每次狼的等级变化来改变住户的舒适度,通过这种方式计算问题。
(3)量子群优化算法
首先我们通过每个粒子代表一个可能搬迁的方案,使用量子旋转门来更新粒子状态,同时考虑到了问题的约束条件。计算函数通过计算院落的总收益,总成本以及确保解决方案满足性价比阈值要求。更新机制依据当前解、个人最优和全局最优来调整量子为,同时使用概率来决定是否选择某个搬迁对。最终计算出问题解。
(4)遗传算法
遗传算法(genetic algorithm,GA)的基本思想是通过逐代进化的方式来优化一个种群,根据自然选择的原则,优秀个体被筛选并传递到后代中[3]。遗传算法的个体表示,每个个体是一个二进制串,长度等于有效搬迁对的数量,1表示选择该搬迁对,0表示不选择。计算函数检查解的有效性,计算腾出院落的总收益,确保性价比的准确约束。遗传算子约束,选择最为竞标赛选择,交叉方式是两点交叉,变异属于是位翻转变异。参数设置,我们将种群大小设为100,进化代数为50,交叉概率0.7,变异概率设置为0.2。最终计算出问题答案。
(5)鲸鱼优化算法
鲸鱼优化算法模拟了座头鲸在捕食过程中的行为,参考了座头鲸具有独特的"气泡网捕食”技术,即鲸鱼在捕捉猎物的过程中,通过围绕猎物做出螺旋上升的运动,最终捕捉猎物。鲸鱼优化算法利用这种捕猎模式,通过模拟鲸鱼在捕食过程中对猎物的搜索与包围来解决复杂的优化问题,鲸鱼优化算法的基本思想是通过鲸鱼个体的围捕行为(局部搜索)和螺旋上升运动(全局搜索),在解空间中找到最优解[4]。我们通过模拟鲸鱼的行为进行实现代码,包括包围猎物鲸鱼通过识别猎物位置并包围它们;使用气泡网攻击,鲸鱼以螺旋方式接近猎物;鲸鱼通过随机搜索猎物。求解的表示每个鲸鱼代表一组搬迁对的集合,并确保每个居民和空地块最多被选择一次。参数控制我们将参数从2线性减小到0,控制探索与开发;或者将参数从2到1再减小到0,控制随机搜索概率;最终概率决定选择哪种更新策略。优化过程,在早期迭代中更倾向于全局探索,在后期迭代中更倾向于局部开发,通过三种行为模式的动态切换平衡探索与开发。
4.3 算法评价
我们通过使用五种优化算法对问题的结果进行对比以及检验,通过每个算法的结果正确的反映出适合智能计算软件框架的算法与模型的结合,下面我们将每种算法的总收益、搬迁总成本以及约束条件的结果以及评价表如下
表6 算法评估表
算法 | 总收益(万元) | 总成本(万元) | 总性价比 | 主要特点 |
模拟退火算法 | 137411.55 | 3617.26 | 37.99 | 中等收益,成本控制较好,性价比高 |
灰狼算法 | 141506.85 | 3621.55 | 39.07 | 高收益,成本控制优秀,性价比高 |
量子群优化算法 | 141506.85 | 3619.54 | 39.10 | 与灰狼算法相当,性能略优 |
遗传算法 | 142472.45 | 42037.42 | 3.39 | 收益最高但成本失控,性价比不达标 |
鲸鱼优化算法 | 141506.85 | 3655.58 | 38.71 | 与灰狼算法和量子群相当,性价比略低 |
通过结果分析我们再对每个算法的性能进行评判,通过设计综合评分对每个算法的性能进行评判。综合评分计算评分方式如下:
综合评分 = 0.5×收益标准化 + 0.3×成本标准化 + 0.2×性价比标准化
红色虚线表示性价比的最低阈值要求(20),同时通过可视化直观展示每个算法之间的优缺点。可视化结果如下图:
图4 算法性能对比图
结合五种优化算法的结果和评价,对问题四进行说明。最佳选择算法是:灰狼算法,它的效果最优稳定性强,实用性强,并且参数调节相对简单;次选量子群优化和鲸鱼算法,量子群的性能和灰狼算法性能相同但效果略弱,鲸鱼算法结果略逊可以作为备选;不推荐遗传算法虽然收益最高但成本失控,性价比不达标,模拟退火收益相对较低。
4.4 结果说明
该问题通过模型求解,以及模型评价。最终结论使用灰狼算法最为本问题的最佳选择,其在收益、成本和性价比三个关键指标上取得了最佳平衡,且算法稳定性好,并且实现难度适中。灰狼算法的应用给出软件实现的构架。
图5软件实现架构
问题二代码 import pandas as pd# 读取数据
data = pd.read_excel('附件一:老城街区地块信息.xlsx')
# 预处理数据
data['地块面积'] = data['地块面积'].astype(float)
data['是否有住户'] = data['是否有住户'].astype(int)
# 分离有住户和无住户的地块
occupied = data[data['是否有住户'] == 1].copy()
vacant = data[data['是否有住户'] == 0].copy()
# 定义采光舒适度等级
light_comfort = {'南': 1, '北': 1, '东': 2, '西': 3}
# 计算每个院落的统计信息(假设院落ID连续)
max_yard_id = data['院落ID'].max()
yard_stats = pd.DataFrame(index=range(1, max_yard_id + 1))
yard_stats['total_plots'] = data.groupby('院落ID')['地块ID'].count()
yard_stats['occupied_plots'] = data.groupby('院落ID')['是否有住户'].sum()
yard_stats['vacant_plots'] = yard_stats['total_plots'] - yard_stats['occupied_plots']
yard_stats['yard_area'] = data.groupby('院落ID')['地块面积'].sum()
yard_stats = yard_stats.fillna(0).reset_index().rename(columns={'index': '院落ID'})
# 找出可以成为完整院落的候选(当前有住户但有空置地块的院落)
candidate_yards = yard_stats[(yard_stats['occupied_plots'] > 0) & (yard_stats['vacant_plots'] > 0)].copy()
candidate_yards['potential_full_area'] = candidate_yards['yard_area']
# 找出可以作为搬迁目标的院落(当前空置地块较多的院落)
target_yards = yard_stats[yard_stats['occupied_plots'] == 0].copy()
target_yards = target_yards.sort_values('vacant_plots', ascending=False)
# 搬迁补偿策略
def can_relocate(source_plot, target_plot):# 面积补偿:迁入地块面积 ≥ 原地块面积,且 ≤ 原面积的130%area_ok = (target_plot['地块面积'] >= source_plot['地块面积']) and \(target_plot['地块面积'] <= 1.3 * source_plot['地块面积'])# 采光补偿:迁入地块采光等级 <= 原地块light_ok = light_comfort[target_plot['地块方位']] <= light_comfort[source_plot['地块方位']]return area_ok and light_ok
# 搬迁成本计算
def calculate_cost(source_plot, target_plot, repair=False):cost = 30000 # 沟通成本# 面积损失成本area_diff = target_plot['地块面积'] - source_plot['地块面积']if area_diff > 0:rent = 15 if source_plot['地块方位'] in ['南', '北'] else 8cost += area_diff * rent * 365 * 10 # 按10年计算# 修缮成本if repair:cost += 200000return cost
# 搬迁规划算法(优化版)
def relocation_plan(occupied, vacant, budget=20000000, max_repair=20):relocated = []total_cost = 0repair_count = 0# 按院落潜在完整面积排序candidate_yards_sorted = candidate_yards.sort_values('potential_full_area', ascending=False)for yard_id in candidate_yards_sorted['院落ID']:yard_plots = data[data['院落ID'] == yard_id]occupied_in_yard = yard_plots[yard_plots['是否有住户'] == 1]for _, source_plot in occupied_in_yard.iterrows():# 在空置地块中寻找合适的搬迁目标for _, target_plot in vacant.iterrows():if can_relocate(source_plot, target_plot):# 尝试不修缮cost = calculate_cost(source_plot, target_plot, repair=False)if total_cost + cost <= budget * 1.3:relocated.append({'source_plot_id': source_plot['地块ID'],'source_yard_id': yard_id,'target_plot_id': target_plot['地块ID'],'target_yard_id': target_plot['院落ID'],'area_diff': target_plot['地块面积'] - source_plot['地块面积'],'light_improvement': light_comfort[target_plot['地块方位']] - light_comfort[source_plot['地块方位']],'cost': cost,'repair': False})vacant = vacant[vacant['地块ID'] != target_plot['地块ID']]total_cost += costbreak# 尝试修缮elif repair_count < max_repair:cost = calculate_cost(source_plot, target_plot, repair=True)if total_cost + cost <= budget * 1.3:relocated.append({'source_plot_id': source_plot['地块ID'],'source_yard_id': yard_id,'target_plot_id': target_plot['地块ID'],'target_yard_id': target_plot['院落ID'],'area_diff': target_plot['地块面积'] - source_plot['地块面积'],'light_improvement': light_comfort[target_plot['地块方位']] - light_comfort[source_plot['地块方位']],'cost': cost,'repair': True})vacant = vacant[vacant['地块ID'] != target_plot['地块ID']]total_cost += costrepair_count += 1breakelse:continuereturn pd.DataFrame(relocated), total_cost
# 执行搬迁规划
relocation_df, total_cost = relocation_plan(occupied, vacant)
# 计算腾出的完整院落
def calculate_full_yards(data, relocation_df):updated_data = data.copy()for _, row in relocation_df.iterrows():updated_data.loc[updated_data['地块ID'] == row['source_plot_id'], '是否有住户'] = 0updated_data.loc[updated_data['地块ID'] == row['target_plot_id'], '是否有住户'] = 1yard_status = updated_data.groupby('院落ID')['是否有住户'].sum().reset_index()full_yards = yard_status[yard_status['是否有住户'] == 0]full_yards_area = updated_data[updated_data['院落ID'].isin(full_yards['院落ID'])]['地块面积'].sum()return full_yards, full_yards_area
full_yards, full_yards_area = calculate_full_yards(data, relocation_df)# 计算收益(简化版)
def calculate_revenue(full_yards, data):# 原分散出租收益original_vacant = data[data['是否有住户'] == 0]original_rent = sum(plot['地块面积'] * (15 if plot['地块方位'] in ['南', '北'] else 8)for _, plot in original_vacant.iterrows())# 新整院出租收益full_yards_rent = sum(data[data['院落ID'] == yard_id]['地块面积'].sum() * 30for yard_id in full_yards['院落ID'])# 毗邻效益(假设院落ID连续,相邻院落ID差为1)adjacent_pairs = 0full_yard_ids = set(full_yards['院落ID'])for yard_id in full_yard_ids:if (yard_id + 1) in full_yard_ids:adjacent_pairs += 1if (yard_id - 1) in full_yard_ids:adjacent_pairs += 1adjacent_pairs = adjacent_pairs // 2 # 避免重复计数full_yards_rent *= (1 + 0.2 * adjacent_pairs)return original_rent * 365 * 10, full_yards_rent * 365 * 10original_revenue, new_revenue = calculate_revenue(full_yards, data)
profit = new_revenue - original_revenue - total_cost# 输出结果
print("问题二搬迁规划结果:")
print(relocation_df)
relocation_df.to_excel('问题二搬迁规划结果.xlsx', index=False)
print("\n腾出的完整院落ID:", full_yards['院落ID'].tolist())
print("腾出的完整院落总面积:", full_yards_area)
print("总搬迁成本:", total_cost)
print("十年租金收益(新):", new_revenue)
print("十年租金收益(原):", original_revenue)
print("十年盈利:", profit)问题三代码import pandas as pd
import random
import math# 加载数据
data = pd.read_excel(r'附件一:老城街区地块信息.xlsx')
rate_map = {'东': 2, '西': 3, '南': 1, '北': 1}
data['单价'] = data['地块方位'].map(rate_map)residents = data[data['是否有住户'] == 1].copy()
vacants = data[data['是否有住户'] == 0].copy()# 初始化
yard_ids = data['院落ID'].unique()
total_cost = 0
total_benefit = 0
overall_m = [] # 性价比列表
m_step = [] # 推进轮数
moves = []
vacated_yards = []# 模拟退火的初始化
T = 1000 # 初始温度
T_min = 1 # 最低温度
alpha = 0.95 # 温度衰减系数
step = 1# 初始化一个初始解
current_yards = list(yard_ids) # 当前解是所有院落ID的顺序
current_cost = total_cost
current_benefit = total_benefit
current_m = current_benefit / current_cost if current_cost != 0 else 0while T > T_min:# 在当前解的邻域内随机选择一个新解new_yards = current_yards.copy()random.shuffle(new_yards) # 随机改变院落顺序作为邻域解new_total_cost = 0new_total_benefit = 0new_moves = []new_vacated_yards = []new_m = 0# 计算新解的总成本和总收益for yard in new_yards:yard_residents = residents[residents['院落ID'] == yard]if len(yard_residents) == 0 or yard in new_vacated_yards:continueyard_moves = []yard_cost = 0for _, r in yard_residents.iterrows():r_ok = Falsefor _, v in vacants.iterrows():if (v['地块面积'] >= r['地块面积'] andv['地块面积'] <= r['地块面积'] * 1.3 andrate_map[v['地块方位']] <= rate_map[r['地块方位']]):area_diff = max(0, v['地块面积'] - r['地块面积'])cost = 3 + 30 + area_diff * rate_map[v['地块方位']] * 240 / 10000yard_moves.append((r['地块ID'], v['地块ID'], cost))yard_cost += costr_ok = Truebreakif not r_ok:breakif len(yard_moves) == len(yard_residents):area = data[data['院落ID'] == yard]['地块面积'].sum()yard_benefit = area * 30 * 3650 / 10000new_total_cost += yard_costnew_total_benefit += yard_benefitnew_moves.extend(yard_moves)new_vacated_yards.append(yard)if new_total_cost > 0:new_m = new_total_benefit / new_total_costelse:new_m = 0# 判断是否接受新解new_cost = new_total_cost - current_costif new_m > current_m or random.random() < math.exp((current_m - new_m) / T):current_yards = new_yardscurrent_cost = new_total_costcurrent_benefit = new_total_benefitcurrent_m = new_mvacated_yards = new_vacated_yardsmoves = new_moves# 温度衰减T *= alpha# 记录性价比overall_m.append(current_m)m_step.append(step)step += 1# 输出结果
df_moves = pd.DataFrame(moves, columns=['原地块ID', '搬入地块ID', '搬迁成本'])
df_moves.to_excel('问题三搬迁规划结果.xlsx', index=False)
print(f"推进院落数: {len(vacated_yards)}")
print(f"最终收益: {round(current_benefit, 2)}")
print(f"最终成本: {round(current_cost, 2)}")
print(f"最终性价比 m: {round(current_benefit / current_cost, 2)}")
print(f"收益拐点出现后终止: {True}")
print(f"推进院落ID: {vacated_yards}")问题四代码 灰狼算法import pandas as pd
import numpy as np
import random
import math
from collections import defaultdict# 读取数据
data = pd.read_excel(r'附件一:老城街区地块信息.xlsx')
residents = data[data['是否有住户'] == 1].copy()
vacants = data[data['是否有住户'] == 0].copy()# 参数设定
rate_map = {'东': 2, '西': 3, '南': 1, '北': 1}
data['单价'] = data['地块方位'].map(rate_map)
m_threshold = 20 # 性价比阈值
rent_days = 3650
rent_price = 30 # 每㎡每天收益# 计算院落收益(按整院)
b_k = {}
for k in data['院落ID'].unique():area = data[data['院落ID'] == k]['地块面积'].sum()b_k[k] = area * rent_price * rent_days / 10000 # 万元# 计算所有合法搬迁对 (i,j) 的成本
c_ij = {}
valid_pairs = []
for i in residents.index:for j in vacants.index:ri = residents.loc[i]vj = vacants.loc[j]if vj['地块面积'] >= ri['地块面积'] and vj['地块面积'] <= 1.3 * ri['地块面积']:if rate_map[vj['地块方位']] <= rate_map[ri['地块方位']]:diff = max(0, vj['地块面积'] - ri['地块面积'])cost = 3 + 30 + diff * rate_map[vj['地块方位']] * 240 / 10000 # 万元c_ij[(i, j)] = costvalid_pairs.append((i, j))# 灰狼优化算法实现
class GreyWolfOptimizer:def __init__(self, n_wolves, valid_pairs, residents, vacants, b_k, c_ij, m_threshold, max_iter=100):self.n_wolves = n_wolvesself.valid_pairs = valid_pairsself.residents = residentsself.vacants = vacantsself.b_k = b_kself.c_ij = c_ijself.m_threshold = m_thresholdself.max_iter = max_iter# 创建居民到院落的映射self.resident_to_yard = {i: residents.loc[i]['院落ID'] for i in residents.index}# 初始化狼群self.wolves = []for _ in range(n_wolves):wolf = self.create_random_wolf()self.wolves.append(wolf)# 记录alpha, beta, delta狼self.alpha = Noneself.alpha_fitness = -float('inf')self.beta = Noneself.beta_fitness = -float('inf')self.delta = Noneself.delta_fitness = -float('inf')def create_random_wolf(self):# 随机选择一个有效的搬迁方案solution = {}used_residents = set()used_vacants = set()# 随机打乱有效对shuffled_pairs = random.sample(self.valid_pairs, len(self.valid_pairs))for i, j in shuffled_pairs:if i not in used_residents and j not in used_vacants:solution[(i, j)] = 1used_residents.add(i)used_vacants.add(j)else:solution[(i, j)] = 0return solutiondef evaluate_fitness(self, solution):# 计算总收益moved_residents = set()for (i, j), val in solution.items():if val > 0.5: # 认为大于0.5表示选择了这个搬迁对moved_residents.add(i)# 计算腾空的院落yard_residents = defaultdict(list)for i in self.residents.index:yard_residents[self.resident_to_yard[i]].append(i)vacant_yards = []for yard, residents in yard_residents.items():if all(r in moved_residents for r in residents):vacant_yards.append(yard)total_benefit = sum(self.b_k[yard] for yard in vacant_yards)# 计算总成本total_cost = sum(self.c_ij[pair] for pair, val in solution.items() if val > 0.5)# 如果总成本为0,避免除以0if total_cost == 0:return -float('inf')# 检查性价比约束m = total_benefit / total_costif m < self.m_threshold:return -float('inf') # 不满足约束的解决方案给予极低适应度return total_benefitdef update_hierarchy(self):# 评估所有狼并更新alpha, beta, deltafitnesses = [self.evaluate_fitness(wolf) for wolf in self.wolves]# 找到前三名sorted_indices = np.argsort(fitnesses)[::-1] # 降序排列# 更新alphaif fitnesses[sorted_indices[0]] > self.alpha_fitness:self.alpha = self.wolves[sorted_indices[0]].copy()self.alpha_fitness = fitnesses[sorted_indices[0]]# 更新betaif len(self.wolves) > 1 and fitnesses[sorted_indices[1]] > self.beta_fitness:self.beta = self.wolves[sorted_indices[1]].copy()self.beta_fitness = fitnesses[sorted_indices[1]]# 更新deltaif len(self.wolves) > 2 and fitnesses[sorted_indices[2]] > self.delta_fitness:self.delta = self.wolves[sorted_indices[2]].copy()self.delta_fitness = fitnesses[sorted_indices[2]]def update_position(self, wolf, a):new_wolf = {}for pair in self.valid_pairs:# 获取alpha, beta, delta的决策alpha_decision = self.alpha.get(pair, 0)beta_decision = self.beta.get(pair, 0)delta_decision = self.delta.get(pair, 0)# 计算A1, A2, A3A1 = 2 * a * random.random() - aC1 = 2 * random.random()D_alpha = abs(C1 * alpha_decision - wolf.get(pair, 0))X1 = alpha_decision - A1 * D_alphaA2 = 2 * a * random.random() - aC2 = 2 * random.random()D_beta = abs(C2 * beta_decision - wolf.get(pair, 0))X2 = beta_decision - A2 * D_betaA3 = 2 * a * random.random() - aC3 = 2 * random.random()D_delta = abs(C3 * delta_decision - wolf.get(pair, 0))X3 = delta_decision - A3 * D_delta# 新位置是三个领导狼决策的平均new_position = (X1 + X2 + X3) / 3# 转换为二进制决策if random.random() < 1 / (1 + math.exp(-new_position)):new_wolf[pair] = 1else:new_wolf[pair] = 0return new_wolfdef optimize(self):# 初始化alpha, beta, deltaself.update_hierarchy()for iter in range(self.max_iter):# 线性递减的a值a = 2 - iter * (2 / self.max_iter)# 更新每只狼的位置new_wolves = []for wolf in self.wolves:new_wolf = self.update_position(wolf, a)new_wolves.append(new_wolf)self.wolves = new_wolves# 更新等级self.update_hierarchy()print(f"Iteration {iter + 1}, Alpha Fitness: {self.alpha_fitness}")return self.alpha, self.alpha_fitness# 运行灰狼优化算法
gwo = GreyWolfOptimizer(n_wolves=30,valid_pairs=valid_pairs,residents=residents,vacants=vacants,b_k=b_k,c_ij=c_ij,m_threshold=m_threshold,max_iter=100
)best_solution, best_fitness = gwo.optimize()# 解析最优解
moves = [pair for pair, val in best_solution.items() if val > 0.5]# 计算腾空的院落
moved_residents = set(i for (i, j) in moves)
yard_residents = defaultdict(list)
for i in residents.index:yard_residents[residents.loc[i]['院落ID']].append(i)vacant_yards = []
for yard, residents_list in yard_residents.items():if all(r in moved_residents for r in residents_list):vacant_yards.append(yard)# 计算总收益和总成本
total_benefit = sum(b_k[yard] for yard in vacant_yards)
total_cost = sum(c_ij[pair] for pair in moves)print(f"\n腾空完整院落数:{len(vacant_yards)}")
print(f"腾空院落 ID 列表:{vacant_yards}")
print(f"\n总收益:{round(total_benefit, 2)} 万元")
print(f"总成本:{round(total_cost, 2)} 万元")
print(f"总体性价比 m:{round(total_benefit / total_cost, 2)}")