2025年MathorCup数学应用挑战赛【B题解题思路】|附可运行代码参考(无偿分享)

注:该内容由“数模加油站”原创,无偿分享,可以领取参考但不要利用该内容倒卖,谢谢!

B   音智策引迁程,老城焕新颜

问题1:请根据当前情况,充分考虑住户房屋 的朝向、面积、布局、心理价位、住宿舒适度等因素,设计合理的搬 迁补偿方案,能根据住户情况给出合理的面积补偿、采光补偿和修缮 补偿范围。除了文中提及的因素外,还有哪些因素可能会影响住户是 否同意搬迁?作为规划局/开发商,应如何应对?请详细列出并定性/ 定量探讨(比如迁入迁出地块离街道的距离,地块周边的房屋密集程 度等)。

问题搬迁补偿建模分析

在老城街区更新中,设计合理的搬迁补偿机制是推动“平移置换”策略顺利实施的关键。本问题旨在构建一个综合评估模型,根据居民当前的居住情况,量化他们在搬迁过程中对面积、采光与生活舒适度等因素的敏感程度,从而提供个性化的搬迁补偿方案。具体而言,居民是否愿意搬迁主要受到三个核心变量的影响:其一是面积的变化,通常居民更愿意搬入面积不小于原居地块的新住所,开发商最多可提供30%的面积提升补偿;其二是采光条件,采光舒适度与地块的朝向密切相关,应确保搬迁后采光不劣于原居所;其三是住宅修缮情况,在面积与采光无法提供足够吸引力时,房屋的翻新可作为提升补偿的重要手段。此外,居民搬迁意愿还受到多种外部因素影响,例如新居地块与街道的距离、院落的人口密度、周边环境的清静程度等,这些因素也应作为建模参数纳入考虑。在构建模型时,可设定一个总体搬迁接受阈值函数,将面积、采光、修缮补偿与环境因子加权整合,通过多指标决策或效用函数打分的方式,判定每个地块对特定住户是否具有吸引力,从而输出匹配优先级排序表,为后续的搬迁优化提供基础。

解题思路:

一、问题重述与建模目标

本问题旨在针对老城街区中尚未搬迁的113户居民,构建一个可量化的“搬迁接受度模型”,用于判定某户居民是否愿意在补偿条件下搬迁至某个空置地块。该模型需要综合考虑原居地块与候选地块的面积差异、采光条件、修缮情况等因素,同时引入与居住舒适度、心理预期相关的额外因子,构建一个能够输出“可搬迁匹配对”及对应最小化成本补偿方案的决策系统。

二、符号定义与模型变量

三、模型核心约束条件构建
1. 面积补偿约束

开发商需保证新地块面积不小于原地块,且最多补偿30%面积。即:

2. 采光补偿约束

采光评级定义如下:正南= 4,正北= 4,东= 3,西= 2,设S(O),设 S(O) 表示朝向评分函数。

我们定义采光补偿函数:

.

3. 修缮补偿策略

若面积和采光均无法完全满足居民期望,可使用修缮作为补偿,最大金额为20 万元。

4. 居住环境与心理偏好因素

我们引入以下两个因素:

上述两个函数均越大表示居民更倾向搬入。

四、搬迁接受度评分模型

可通过专家经验、打分调查或遗传算法优化等方式进行权重学习。

五、搬迁成本计算模型

六、可接受迁移集合判定

七、模型扩展与实际可行性考虑

在实际应用中,可引入:

Python代码:

import pandas as pd
import numpy as np
from itertools import product

# ----------- 读取数据 -----------
file_path = "附件一:老城街区地块信息.xlsx"
df = pd.read_excel(file_path)

# 提取住户和空置地块
residents = df[df["是否有人"] == 1].copy()
vacants = df[df["是否有人"] == 0].copy()

# ----------- 定义朝向评分 -----------
def orientation_score(o):
    if o == "正南" or o == "正北":
        return 4
    elif "东" in o:
        return 3
    elif "西" in o:
        return 2
    else:
        return 1  # fallback

# 应用朝向评分
residents["采光评分"] = residents["朝向"].apply(orientation_score)
vacants["采光评分"] = vacants["朝向"].apply(orientation_score)

# ----------- 地块租金计算函数(简化) -----------
def rent_price(o):
    if "南" in o or "北" in o:
        return 15
    else:
        return 8

residents["租金"] = residents["朝向"].apply(rent_price)
vacants["租金"] = vacants["朝向"].apply(rent_price)

# ----------- 模型参数 -----------
weights = {
    "面积": 0.3,
    "采光": 0.25,
    "修缮": 0.15,
    "距离": 0.15,
    "密度": 0.15
}
theta = 0.75  # 接受度阈值
T_days = 30 * 12 * 10
fixed_cost = 3  # 沟通协调费(万元)

# 模拟环境因子(示意)
vacants["距离街道"] = np.random.uniform(0, 1, len(vacants))
vacants["周边密度"] = np.random.uniform(0.3, 0.9, len(vacants))

# ----------- 核心函数:计算得分和成本 -----------
def compute_score_cost(row_r, row_v):
    area_r, area_v = row_r["面积"], row_v["面积"]
    orient_r, orient_v = row_r["采光评分"], row_v["采光评分"]
    rent_r, rent_v = row_r["租金"], row_v["租金"]

    # 面积补偿评分
    if area_v < area_r or area_v > 1.3 * area_r:
        return None  # 不可行
    f1 = (area_v - area_r) / (0.3 * area_r)

    # 采光补偿评分
    f2 = 1 if orient_v >= orient_r else orient_v / orient_r

    # 修缮评分(当 f1 或 f2 < 1 时引入修缮)
    needs_repair = f1 < 1 or f2 < 1
    repair_cost = np.random.randint(0, 21) if needs_repair else 0
    f3 = repair_cost / 20

    # 距离与密度评分
    f4 = 1 / (1 + row_v["距离街道"])
    f5 = np.exp(-2 * row_v["周边密度"])

    # 综合得分
    R = weights["面积"] * f1 + weights["采光"] * f2 + weights["修缮"] * f3 + weights["距离"] * f4 + weights["密度"] * f5

    # 成本计算(单位万元)
    area_diff = area_v - area_r
    c3 = area_diff * rent_v * T_days / 10000
    c4 = (area_r * rent_r + area_v * rent_v) * 120 / 10000
    total_cost = fixed_cost + repair_cost + c3 + c4

    return R, total_cost

# ----------- 匹配计算 -----------
results = []
for i, row_r in residents.iterrows():
    for j, row_v in vacants.iterrows():
        out = compute_score_cost(row_r, row_v)
        if out:
            R, cost = out
            if R >= theta:
                results.append({
                    "居民ID": row_r["地块编号"],
                    "搬入ID": row_v["地块编号"],
                    "搬入院落": row_v["杂院编号"],
                    "得分": round(R, 3),
                    "成本(万元)": round(cost, 2)
                })

# ----------- 输出结果 -----------
match_df = pd.DataFrame(results)
match_df = match_df.sort_values(by="得分", ascending=False)
match_df.to_excel("问题一_搬迁可行匹配表.xlsx", index=False)

print("搬迁匹配对数量:", len(match_df))
display(match_df.head(10))

问题2:利用问题一的结果,设计针对每户住 户的搬迁决策,使得最终搬迁后空出的完整院落最多,在此基础上完 整院落尽可能相互毗邻,且总面积最大。这个过程中要注意搬迁住户 数应尽量少。请通过计算回答:应该如何搬迁?搬了哪些院子的居民, 从哪个地块搬到哪个地块,搬迁腾出的整院是哪些,并结算共投入多 少成本,最终的整院面积和最终的收入及盈利(请注意尽量在保底规 划成本内完成,如果实在不满足再使用备用金)。

问题 2:整院面积最大化策略

在完成搬迁意愿建模之后,问题二的核心任务是在保证补偿方案可接受的基础上,合理安排搬迁住户,实现整院腾空面积的最大化。在建模过程中,应从整个街区的空间结构出发,首先建立住户与可迁入地块之间的可行匹配网络,其中每一条边代表一个可接受的搬迁方案,并带有相关的搬迁成本与收益指标。在此基础上,我们可以引入整数规划或图论优化模型,通过设置目标函数最大化“可完整腾退院落的总面积”,并辅以约束条件限制搬迁成本不得超过既定预算、每户只能搬一次、每地块仅可容纳一户等。为提升开发效益,优先考虑腾空具有高商业潜力的院落,尤其是那些彼此毗邻的整院区域,从而形成集中开发带,提升单位面积的租金收益。与此同时,搬迁户数应尽量控制在最小范围,以降低沟通、时间与修缮成本,实现高效的空间腾挪与资源释放。最终输出应包含详细的搬迁对照表(住户迁出地块与迁入地块的对应关系)、腾空的整院编号及其总面积、总投入成本与预期租金收益,为开发商提供清晰的更新执行路径。

解题思路:

老城区整院腾空搬迁规划模型

基于老城区“平移置换更新”问题背景,我们建立一个搬迁规划优化模型,以腾出完整院落的总面积最大化为目标,在尊重住户搬迁意愿的前提下,安排住户从原地块迁入空置地块。模型旨在确定应搬迁哪些院落的居民、迁往哪些空地块,以及由此腾空的整院(完整院落)有哪些,同时评估所需成本和开发商收益。下面详细定义模型的决策变量、参数、目标函数与约束条件,并说明整院腾空的判定方法、与问题一结果的衔接以及求解策略。

决策变量与模型参数定义

目标函数

规划的目标是最大化开发商的总体收益(等价于腾空整院总面积及其租金收益最大化减去搬迁成本)。目标函数由腾空院落的租金收入和搬迁成本两部分构成,其中租金收入还包括毗邻院落同时腾空带来的增益。目标函数可表示为:

约束条件

在实现上述目标的同时,需要满足一系列约束条件以确保方案可行:

整院腾空的识别与面积计算

搬迁方案生成: 基于上述约束,模型的可行解实际上对应一份详细的搬迁方案清单,包括:哪些院落的居民被搬迁、每户搬迁从原地块(所属院落)到哪个新地块,以及腾空了哪些院落。这正是问题二要求回答的内容。本模型求解

求解策略与模型特征

  • 整数规划求解: 综合考虑毗邻增益这种非局部效应,直接使用整数规划求解更为稳妥。可采用商业求解器求解上述MILP模型,或者设计启发式算法提高效率。例如,可先忽略邻接增益求解一个最大收益腾空方案,再在此基础上局部搜索调整,促使更多相邻院落一起腾空以获取1.2倍收益;或者反过来先寻找能够连片腾空的一组院落作为候选,再检查预算可行性并安置方案。这些策略都可以缩小搜索空间。由于本问题规模适中,我们推荐直接用数学规划求解获取全局最优解。

模型扩展: 如果需要进一步分析投资回报率拐点(对应问题三)或开发不同预算水平下的策略,可以在此模型基础上做参数调优或多目标扩展。例如,逐步放宽预算约束,观察最优解中收益与成本的变化,以计算性价比m的拐点;或者在目标函数中加入对成本的惩罚项以模拟不同投资意愿等。整个模型也可以嵌入一个决策支持软件(对应问题四),通过输入院落地块数据、居民意愿参数和预算等,自动求解出最佳搬迁方案和收益评估,实现智能决策支持。

Python代码:

import pandas as pd
from pulp import LpProblem, LpMaximize, LpVariable, lpSum, LpStatus

# 读取数据(假设 Excel 文件已存在于工作目录)
df = pd.read_excel("附件一:老城街区地块信息.xlsx")

# 分离出有住户的地块和空置地块
occupied = df[df["是否有住户"] == 1].copy()
empty = df[df["是否有住户"] == 0].copy()

# 定义采光方位的舒适度排名(数值越大表示采光越好)
orientation_rank = {"正南": 3, "正北": 3, "南": 3, "北": 3, "东厢": 2, "东": 2, "西厢": 1, "西": 1}
# 如果数据中存在其他方位描述,进行适配
for ori in df["地块方位"].unique():
    if ori not in orientation_rank:
        if ori.startswith("东"):
            orientation_rank[ori] = 2
        elif ori.startswith("西"):
            orientation_rank[ori] = 1
        elif ori in ["正南", "南", "正北", "北"]:
            orientation_rank[ori] = 3

# 提取每个院落的总面积(仅针对最初有住户的院落)
courtyard_area = occupied.groupby("院落ID")["院落面积"].first().to_dict()

# 建立原住户地块ID到院落ID的映射,以及空置地块ID到院落ID的映射
orig_courtyard = occupied.set_index("地块ID")["院落ID"].to_dict()
dest_courtyard = empty.set_index("地块ID")["院落ID"].to_dict()

# 建立地块ID到地块面积的映射
block_area = df.set_index("地块ID")["地块面积"].to_dict()

# 列出所有原住户和所有可供迁入的空地块
occupant_ids = list(orig_courtyard.keys())
empty_ids = list(dest_courtyard.keys())

# 构建可行的搬迁方案列表 (i -> j) 以及对应成本 C[i,j]
feasible_moves = []
for i in occupant_ids:
    ori_orientation = df.loc[df["地块ID"] == i, "地块方位"].values[0]
    required_rank = orientation_rank.get(ori_orientation, 0)
    area_i = block_area[i]
    for j in empty_ids:
        # 不考虑迁入同一院落的情形(迁入原院落无法腾空该院)
        if dest_courtyard[j] == orig_courtyard[i]:
            continue
        area_j = block_area[j]
        new_orientation = df.loc[df["地块ID"] == j, "地块方位"].values[0]
        # 检查面积与采光条件
        if area_j >= area_i and area_j <= 1.3 * area_i:
            if orientation_rank.get(new_orientation, 0) >= required_rank:
                # 计算搬迁成本(这里简单地使用面积差作为补偿成本的近似)
                cost_ij = area_j - area_i
                feasible_moves.append((i, j, cost_ij))

# 定义线性规划问题
prob = LpProblem("MaximizeVacatedCourtyardArea", LpMaximize)

# 定义决策变量:
# x[i,j] = 1表示选择将住户i迁入空地块j
x = {(i, j): LpVariable(f"x_{i}_{j}", lowBound=0, upBound=1, cat='Binary')
     for (i, j, cost) in feasible_moves}
# y[k] = 1表示院落k的原有住户全部搬迁腾空
y = {k: LpVariable(f"y_{k}", lowBound=0, upBound=1, cat='Binary')
     for k in courtyard_area.keys()}

# 目标函数:最大化腾空院落的总面积
prob += lpSum(courtyard_area[k] * y[k] for k in courtyard_area), "TotalVacatedArea"

# 约束1:每户居民最多搬迁一次
for i in occupant_ids:
    prob += lpSum(x[(i, j)] for (ii, j, c) in feasible_moves if ii == i) <= 1, f"MoveLimit_house_{i}"

# 约束2:每个目标地块最多安置一户居民
for j in empty_ids:
    prob += lpSum(x[(i, j)] for (i, jj, c) in feasible_moves if jj == j) <= 1, f"Capacity_block_{j}"

# 约束3:定义院落腾空条件——只有当院落k内所有原住户都搬迁后,y[k]才能为1
for k, area in courtyard_area.items():
    original_households_k = [i for i, cid in orig_courtyard.items() if cid == k]
    prob += lpSum(x[(i, j)] for (i, j, c) in feasible_moves if i in original_households_k) >= y[k] * len(original_households_k), f"VacateCondition_{k}"

# 约束4:如果院落k腾空(y[k]=1),则不能有新的住户迁入该院落
for k in courtyard_area:
    empties_in_k = [j for j, cid in dest_courtyard.items() if cid == k]
    for j in empties_in_k:
        prob += lpSum(x[(i, j)] for (i, jj, c) in feasible_moves if jj == j) <= 1 - y[k], f"NoNewInto_{k}_{j}"

# 约束5:总搬迁成本不超过 2600 万元(预算2000万,可超出30%至2600万)
prob += lpSum(cost * x[(i, j)] for (i, j, cost) in feasible_moves) <= 2600, "BudgetLimit"

# 求解线性规划模型
prob.solve()

# 输出求解状态
print("Status:", LpStatus[prob.status])

# 提取最优解中的搬迁对 (i -> j)
selected_moves = [(i, j) for (i, j), var in x.items() if var.value() == 1]
# 提取腾空的院落ID列表
vacated_courtyards = [k for k, var in y.items() if var.value() == 1]

# 计算总搬迁成本和腾空总面积
total_cost = sum(cost for (i, j, cost) in feasible_moves if x[(i, j)].value() == 1)
total_vacated_area = sum(courtyard_area[k] for k in vacated_courtyards)

# 打印结果
print("Optimal relocation pairs (i -> j):")
for i, j in sorted(selected_moves):
    print(f"{i} -> {j}")
print("Vacated courtyard ID list:", sorted(vacated_courtyards))
print("Total relocation cost:", total_cost)
print("Total vacated area:", total_vacated_area)

问题3:在不考虑保底规划成本约 束时,计算投资回报率:开发商往往希望以十年为期限,使搬迁十年 的租金收益相比于不搬迁的增量/实际搬迁投入(称为性价比m)大 于等于 20。假定十年内租金没有明显变化,那么在搬迁进程中,是 否存在性价增益的拐点?即达到某个搬迁的平稳状态,再搬迁带来的 性价比开始变低了?如有,请计算出该拐点是何种情况:搬了哪些院 子的居民,从哪个地块搬到哪个地块,搬迁腾出的整院是哪些,并结 算共投入多少成本,最终的整院面积和最终的收入及盈利。如没有, 请讨论性价比m降低到至少多少就能存在拐点?

问题性价比拐点分析与搬迁策略评估

第三问题聚焦于城市更新项目中的“性价增益拐点”分析,即在不设成本预算限制的前提下,评估开发商在不同搬迁规模下的租金收益增长趋势与投入成本之间的平衡点。为此,我们需设定一个明确的性价比指标,例如十年内新增租金收益与搬迁实际投入的比值(记为$m$),并要求m≥20作为基本盈利阈值。模型运行中应采用递进式策略,逐步拓展搬迁范围,在每一步扩展后记录新增成本与收益,形成收益曲线图。若存在搬迁至某一临界规模后,单位收益开始边际递减、性价比逐步跌破盈利阈值,则该点即为“性价增益拐点”。该分析不仅能为开发商明确最优的搬迁规模,也有助于精准识别“高价值腾退院落”,避免资源浪费与过度搬迁。若模型结果显示始终无明显拐点,还应反向求解在何种性价比阈值下才能形成拐点,为政策制定者或投资者提供策略性调整的参考。

解题思路:

3. 性价增益的搬迁拐点计算
3.1 问题背景与建模目标

在完成问题二的基础上,我们已获得一组可行的居民搬迁方案,腾空了一批整院地块供商业开发。为了衡量搬迁的经济合理性,开发商进一步希望分析在“十年收益期”内,搬迁所带来的收益提升与实际成本投入之间的比例关系,即投资回报率(性价比):

  • 若搬迁计划性价比高于某阈值(题设为 m≥20),则该搬迁是值得投资的;
  • 如果继续搬迁带来的性价比不断降低,说明收益边际递减,可能需要停止搬迁。

本问题的目标是计算搬迁的性价比演化过程,寻找收益递减的搬迁拐点,即“搬到这个点为止划算,继续搬则不如不搬”的关键决策节点。

3.2 模型符号定义与变量说明

我们引入以下变量与集合定义:

3.3 不搬迁时的基础收益模型

原始收益来源为:

  • 所有空置房屋按其朝向出租;
  • 租金单价设定如下:

3.4 搬迁后的收益模型

搬迁后将带来两部分收益:

1)整院收益:

若院落k被腾空,整院出租价值提升为 30元/㎡/天,若与相邻院落组成连片区块,则总价值提升20%。

2)未被整合的空地收益:

将剩余空地继续以普通方式出租:

3)搬迁后总收益:

3.5 搬迁投入成本模型

搬迁成本为以下四项之和:

1)沟通协调成本:

2)修缮翻新成本(可选项):

3.6 性价比指标与拐点定义

我们定义搬迁方案的性价比m为:

3.7 算法设计与求解流程

算法思想:递增式贪心搬迁优化

我们使用启发式算法逐步添加居民搬迁项,并实时监控性价比:

步骤如下:

可视化辅助分析:

绘制:

  • 横轴为累计搬迁户数;
  • 纵轴为当前m值;

观察曲线是否存在拐点变化趋势。

3.8 特殊情况处理与拓展

Python代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 假设我们有以下DataFrame:
# residents_df: 包含居民信息(ID, 当前地块ID, 面积, 朝向)
# blocks_df: 包含地块信息(地块ID, 所属院落ID, 面积, 朝向, 是否空置)

# 参数设置
T = 3650  # 10年天数
R_dict = {"南": 15, "北": 15, "东": 8, "西": 8}
r整 = 30
r连片 = 30 * 1.2
alpha = 0.3
C_gou = 3e4
C_xiu = 2e5
T_month = 4


# 示例函数:收益计算(不搬迁)
def calculate_no_move_income(blocks_df):
    blocks_df = blocks_df[blocks_df['occupied'] == 0]
    income = 0
    for _, row in blocks_df.iterrows():
        rent = R_dict[row['direction']]
        income += row['area'] * rent * T
    return income


# 示例函数:计算搬迁方案收益与成本
def calculate_move_metrics(move_plan, residents_df, blocks_df):
    income整院 = 0
    income散地 = 0
    total_cost = 0
    moved_blocks = []

    for move in move_plan:
        res_id, from_block, to_block, 修缮 = move
        res = residents_df.loc[residents_df['id'] == res_id].iloc[0]
        to = blocks_df.loc[blocks_df['id'] == to_block].iloc[0]
        from_area, to_area = res['area'], to['area']
        rent_to = R_dict[to['direction']]
        rent_from = R_dict[res['direction']]

        # 收益:地块空出可能组成整院或出租(这里简化处理)
        moved_blocks.append(from_block)

        # 成本
        cost = 0
        cost += C_gou  # 沟通成本
        if 修缮:
            cost += C_xiu
        if to_area > from_area:
            cost += (to_area - from_area) * rent_to * T
        cost += (to_area * rent_to + from_area * rent_from) * T_month / 12
        total_cost += cost

    # 假设我们整院是 id 100~105,若全部空了就算整院收益
    # 实际应根据 move_plan 统计每个院落是否全空
    for院 in [100, 101, 102]:
    if院 in blocks_df['yard_id'].values:
    mask = (blocks_df['yard_id'] == 院)
    yard_blocks = blocks_df[mask]
    if all(b in moved_blocks for b in yard_blocks['id']):
        area_sum = yard_blocks['area'].sum()
        income整院 += r整 * area_sum * T
    else:
        income散地 += sum([
            row['area'] * R_dict[row['direction']] * T
            for _, row in yard_blocks.iterrows()
            if row['occupied'] == 0
        ])


income_move = income整院 + income散地
return income_move, total_cost


# 示例:构造贪心搬迁计划(简化版)
def greedy_plan(residents_df, blocks_df):
    plan = []
    available_blocks = blocks_df[blocks_df['occupied'] == 0].copy()
    used_blocks = set()

    for _, res in residents_df.iterrows():
        from_area = res['area']
        from_dir = res['direction']
        res_id = res['id']

        # 候选地块满足面积和朝向条件
        candidates = available_blocks[
            (available_blocks['area'] >= from_area) &
            (available_blocks['area'] <= from_area * (1 + alpha)) &
            (available_blocks['direction'].map(lambda x: R_dict[x]) >= R_dict[from_dir])
            ]

        if not candidates.empty:
            best = candidates.iloc[0]
            to_id = best['id']
            修缮 = 0  # 暂不修缮
            plan.append((res_id, res['block_id'], to_id, 修缮))
            used_blocks.add(to_id)
            available_blocks = available_blocks[~available_blocks['id'].isin(used_blocks)]

    return plan


# 主流程:逐步加入搬迁对,绘制m曲线
def simulate_m_curve(residents_df, blocks_df):
    base_income = calculate_no_move_income(blocks_df)
    m_list = []
    plans = []
    current_plan = []

    # 模拟逐步搬迁
    greedy = greedy_plan(residents_df, blocks_df)
    for move in greedy:
        current_plan.append(move)
        move_income, move_cost = calculate_move_metrics(current_plan, residents_df, blocks_df)
        if move_cost == 0:
            m_list.append(0)
        else:
            m = (move_income - base_income) / move_cost
            m_list.append(m)
        plans.append(current_plan.copy())

    # 绘图
    plt.figure(figsize=(10, 5))
    plt.plot(range(1, len(m_list) + 1), m_list, marker='o')
    plt.xlabel("搬迁户数")
    plt.ylabel("性价比 m")
    plt.title("搬迁数量与性价比关系曲线")
    plt.grid(True)
    plt.axhline(y=20, color='red', linestyle='--', label='m=20临界线')
    plt.legend()
    plt.tight_layout()
    plt.show()

    return m_list, plans

# 用法示意(数据应预加载)
# m_list, best_plans = simulate_m_curve(residents_df, blocks_df)

问题4:规划局希望这个案例 能起到示范作用,推广到全国的老旧街区更新搬迁中,请你们设计一 个软件框架,能够智能计算老城区平移置换决策,指出该软件应该设 定哪些人工输入的参数,通过怎样的计算步骤,可以融合你们的模型 设计,自动计算出问题二和问题三的答案。

问题 4老城区智能搬迁规划软件设计

考虑到“平移置换”策略在全国范围内的可推广性与复杂性,问题四要求设计一套具备通用性与智能性的决策支持软件系统,能自动完成从数据读取到搬迁优化全流程的决策计算。该软件应以图形化地块信息与住户数据为基础,构建完整的搬迁信息库,并允许用户输入各类参数(如搬迁预算、补偿上限、优先开发区域等)。在核心模块设计上,应包括以下功能组件:数据预处理模块用于清洗地块与院落信息;搬迁意愿判定模块依据问题一中的效用函数模型评估搬迁可行性;搬迁优化模块使用问题二与三中的算法框架求解最优搬迁方案并动态展示腾空情况;可视化模块以地图叠图、热力图、动态租金图等形式,直观展示搬迁成果与经济效益。整个系统应支持方案对比、搬迁路径回溯、性价比曲线分析等功能,具备较强的交互性和适配性,从而实现“数据驱动+政策辅助”的智慧搬迁决策,真正服务于全国老城区城市更新的大局战略。

解题思路:

4. 老城区平移置换决策软件设计
4.1 问题理解与软件目标

本问题要求将问题一至问题三中的建模成果整合进一个可执行的、智能化的软件系统,使其能够:

  • 接收用户输入(如街区地块信息、搬迁限制、预算参数);
  • 自动计算合理的搬迁补偿策略;
  • 优化整院腾退出租计划;
  • 判断搬迁收益的性价比与收益拐点;
  • 输出搬迁方案与预估收益成本评估;
  • 支持人机交互、可视化搬迁结果。
4.2 输入参数设计

软件系统需设置以下主要输入参数(人工输入或表格导入):

4.3 软件核心模型模块

将问题1–3形成的模型整合为软件核心模块:

4.4 搬迁软件计算流程

步骤一:输入信息初始化

4.5 可视化与交互模块

建议采用 PyQt、Flask 或 Streamlit 等框架实现图形界面功能:

  • 地块分布热力图;
  • 居民搬迁流向箭头图;
  • 整院腾退结果图;
  • 性价比演化曲线图。
4.6 可拓展能力分析
  • 多区域适配:可根据不同城市老旧街区导入地块图层与建筑属性;
  • 预算可调:支持规划局不同预算限度测试;
  • 多目标优化:兼顾整院面积、连片程度、搬迁数量的加权目标函数;
  • 可嵌入 GIS 平台:增强地块空间可视化与交互。
4.7 建议输出结构

系统自动生成如下文件:

Python代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# === 参数设置 ===
R_dict = {"南": 15, "北": 15, "东": 8, "西": 8}
r整 = 30  # 整院租金
r连片 = 30 * 1.2
alpha = 0.3
C_gou = 3e4  # 沟通成本
C_xiu = 2e5  # 修缮成本(可选)
T = 3650     # 十年天数
T_month = 4

# === 功能函数定义 ===

def direction_level(d):
    return {"南": 3, "北": 3, "东": 2, "西": 1}[d]

def calculate_no_move_income(blocks_df):
    available = blocks_df[blocks_df['occupied'] == 0]
    return sum(available['area'] * available['direction'].map(R_dict) * T)

def check_feasible(res_row, blk_row):
    a1, a2 = res_row['area'], blk_row['area']
    if a2 < a1 or a2 > a1 * (1 + alpha):
        return False
    if direction_level(blk_row['direction']) < direction_level(res_row['direction']):
        return False
    return True

def generate_feasible_plan(residents_df, blocks_df):
    plan = []
    available = blocks_df[blocks_df['occupied'] == 0].copy()
    used_blocks = set()

    for _, res in residents_df.iterrows():
        for _, blk in available.iterrows():
            if blk['id'] in used_blocks:
                continue
            if check_feasible(res, blk):
                plan.append((res['id'], res['block_id'], blk['id'], 0))  # 不修缮
                used_blocks.add(blk['id'])
                break
    return plan

def evaluate_plan(plan, residents_df, blocks_df):
    income整 = 0
    income散 = 0
    total_cost = 0
    moved_blocks = set()
    moved_yards = set()

    for res_id, from_id, to_id, 修缮 in plan:
        res = residents_df[residents_df['id'] == res_id].iloc[0]
        to = blocks_df[blocks_df['id'] == to_id].iloc[0]
        a1, a2 = res['area'], to['area']
        d1, d2 = res['direction'], to['direction']
        moved_blocks.add(from_id)
        yid = blocks_df[blocks_df['id'] == from_id]['yard_id'].values[0]
        moved_yards.add(yid)

        cost = C_gou
        if 修缮:
            cost += C_xiu
        if a2 > a1:
            cost += (a2 - a1) * R_dict[d2] * T
        cost += (a1 * R_dict[d1] + a2 * R_dict[d2]) * T_month / 12
        total_cost += cost

    # 整院判断(全部住户搬走)
    full_yards = []
    for yid in blocks_df['yard_id'].unique():
        yard = blocks_df[blocks_df['yard_id'] == yid]
        occ_ids = yard[yard['occupied'] == 1]['id'].tolist()
        if occ_ids and all(b in moved_blocks for b in occ_ids):
            area = yard['area'].sum()
            income整 += r整 * area * T
            full_yards.append(yid)

    # 剩余零散
    others = blocks_df[(blocks_df['yard_id'].isin(full_yards) == False) & (blocks_df['occupied'] == 0)]
    income散 = sum(others['area'] * others['direction'].map(R_dict) * T)

    total_income = income整 + income散
    return total_income, total_cost, full_yards

def plot_m_curve(m_list):
    plt.figure(figsize=(10, 5))
    plt.plot(range(1, len(m_list)+1), m_list, marker='o')
    plt.xlabel("搬迁户数")
    plt.ylabel("性价比 $m$")
    plt.title("搬迁性价比随搬迁规模变化")
    plt.axhline(20, linestyle='--', color='red', label='临界线 $m=20$')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.savefig('111.png')

# === 主执行流程 ===
def run_decision_software(residents_file, blocks_file):
    residents_df = pd.read_excel(residents_file)
    blocks_df = pd.read_excel(blocks_file)
    base_income = calculate_no_move_income(blocks_df)
    plan = generate_feasible_plan(residents_df, blocks_df)

    m_list = []
    plan_seq = []

    for k in range(1, len(plan)+1):
        cur_plan = plan[:k]
        income, cost, yards = evaluate_plan(cur_plan, residents_df, blocks_df)
        if cost == 0:
            m = 0
        else:
            m = (income - base_income) / cost
        m_list.append(m)
        plan_seq.append((cur_plan, yards))

    plot_m_curve(m_list)

    # 输出部分搬迁方案
    print("最终搬迁户数:", len(plan_seq[-1][0]))
    print("性价比:", round(m_list[-1], 2))
    print("腾出的整院编号:", plan_seq[-1][1])

    return m_list, plan_seq

# === 调用示例 ===
if __name__ == "__main__":
    # 替换为你实际的文件路径
    residents_file = "residents.xlsx"
    blocks_file = "blocks.xlsx"
    m_list, all_plans = run_decision_software(residents_file, blocks_file)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值