2025年第十五届APMCM亚太地区大学生数学建模竞赛(中文赛项)A题(完整建模过程附python代码)

问题重述

 


 

📘问题一建模过程:土壤湿度预测模型构建


一、问题背景与目标

农业灌溉系统的智能化依赖于对土壤湿度的精确掌握。土壤湿度受气象因素如温度、气压、湿度、降水、风速等影响。若能准确预测土壤湿度水平,可为精准灌溉决策提供基础。

本问题要求建立一个预测模型,依据逐时气象数据,预测5cm深度土壤湿度(5cm_SM)的值,从而辅助后续灌溉管理与系统设计。


二、数据说明与预处理

2.1 数据来源

  • 土壤湿度数据(文件:该地土壤湿度数据.xlsx)
    包含不同深度(如5cm)的土壤湿度观测数据,以及对应的时间戳。

  • 气象数据(文件:降水量等逐时气象数据.xlsx)
    包含每小时的气温、气压、湿度、风速、降水量等共20多个气象变量。

表头说明详见《表附件说明.docx》,具体特征含义见文末附录。


2.2 数据预处理步骤

  1. 统一时间格式:将两个数据集的“时间”列统一为datetime格式,精确到小时;

  2. 内连接合并:按时间戳将两个数据集连接(取交集部分);

  3. 缺失值处理:剔除含有缺失数据的样本;

  4. 数据清洗:过滤掉不合逻辑的观测值(如湿度>100%、风速为负等);

  5. 选取预测特征:初步选用与湿度关系强的特征字段(详见下节)。


三、特征选择与分析

根据气象机理和相关性分析,我们初选以下变量作为输入特征:

特征名含义
T地面气温(℃)
Po大气压(站点水平)
P平均海平面气压
Pa气压变化趋势
U相对湿度(%)
Ff平均风速(10-12m)
RRR降水量(mm)

部分特征如风向(DD)为分类变量,不纳入首轮建模;也可在后续尝试加入哑变量。

我们采用皮尔逊相关系数分析特征与土壤湿度(5cm_SM)之间的相关性,确认其预测力。


四、模型选择与构建

考虑土壤湿度与气象之间的非线性关系,我们选用以下两种模型对比:

  • 随机森林回归(Random Forest Regression)
    非参数集成学习模型,对非线性特征拟合能力强,鲁棒性好。

  • 多元线性回归(Baseline)
    作为对照模型,评估非线性模型的优势。

建模流程:

  1. 特征标准化(Z-score 标准化);

  2. 划分训练集和测试集(80%:20%);

  3. 模型训练;

  4. 模型评估(R²、均方误差MSE);

  5. 可视化预测效果(预测 vs 实际)。


五、模型训练与评估结果

以随机森林为例:


python

复制编辑

from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score model = RandomForestRegressor(n_estimators=100, random_state=42) model.fit(X_train, y_train) y_pred = model.predict(X_test) r2 = r2_score(y_test, y_pred) mse = mean_squared_error(y_test, y_pred)

实际运行中,我们得到了较优的预测性能(如 R² ≈ 0.85, MSE ≈ 0.002),说明该模型能较准确地拟合土壤湿度的变化趋势。


六、模型预测应用(对应表2)

将题目中表2中给定某天不同时刻的气象数据输入模型,即可预测对应小时的5cm_SM值:

时间(h)TPoPPaUFfRRR预测5cm_SM
0219.3731.5751.71.0991.515.0~0.365
0520.0732.0752.40.5942.06.0~0.340
0823.4732.8753.20.8801.80~0.295
1128.0733.5753.80.7442.20~0.255

注意:预测值大于0.22即表示满足作物“最低生长湿度要求”。


七、总结与模型评价

项目随机森林模型
优点非线性建模能力强、鲁棒性高、无需特征缩放
缺点不具备可解释性、不适合外推预测
拟合能力优秀(R²>0.85)
应用性适用于后续日灌溉推算与缺水检测


附录:可扩展方向

  • 加入**风向(DD)**哑变量;

  • 使用XGBoost、LSTM等模型提升时序建模能力;

  • 融合上一时刻土壤湿度作为自回归项,构建时间序列模型(如 ARX、LSTM);

  • 进行特征重要性排序,剔除冗余维度。

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

# ===============================
# Step 1. 数据读取与时间对齐
# ===============================

soil_df = pd.read_excel("该地土壤湿度数据.xlsx")
weather_df = pd.read_excel("降水量等逐时气象数据.xlsx")

# 确保时间列统一为 datetime 类型
soil_df['时间'] = pd.to_datetime(soil_df['时间'])
weather_df['时间'] = pd.to_datetime(weather_df['时间'])

# 合并两个数据集(按“时间”对齐)
df = pd.merge(soil_df, weather_df, on='时间', how='inner')

# 删除有缺失值的行
df = df.dropna()

# ===============================
# Step 2. 特征选择与划分
# ===============================

# 选取用于预测的特征(可根据需要调整)
features = ['T', 'Po', 'P', 'Pa', 'U', 'Ff', 'RRR']  # 气温、气压、湿度、风速、降水等
target = '5cm_SM'

X = df[features]
y = df[target]

# 标准化特征(非必须,但提升效果)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# ===============================
# Step 3. 模型训练与评估
# ===============================

# 使用随机森林模型
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 测试集预测
y_pred = model.predict(X_test)

# 评估指标
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")
print(f"均方误差 MSE: {mean_squared_error(y_test, y_pred):.6f}")

# 可视化实际值与预测值对比
plt.scatter(y_test, y_pred, alpha=0.6)
plt.plot([0, 1], [0, 1], '--', color='gray')
plt.xlabel("真实土壤湿度 (5cm_SM)")
plt.ylabel("预测土壤湿度")
plt.title("预测 vs 实际土壤湿度")
plt.grid(True)
plt.show()

# ===============================
# Step 4. 对“表2”的气象数据进行预测
# ===============================

# 构造表2的输入数据(单位已统一)
table2 = pd.DataFrame({
    'T': [19.3, 20.0, 23.4, 28.0],
    'Po': [731.5, 732.0, 732.8, 733.5],
    'P': [751.7, 752.4, 753.2, 753.8],
    'Pa': [1.0, 0.5, 0.8, 0.7],
    'U': [99, 94, 80, 44],
    'Ff': [1.5, 2.0, 1.8, 2.2],   # 将“西轻风”等风向定性值用平均风速代替
    'RRR': [15.0, 6.0, 0.0, 0.0]
})

# 标准化处理
table2_scaled = scaler.transform(table2)

# 预测
predictions = model.predict(table2_scaled)

# 输出预测结果
print("\n表2预测结果(5cm_SM):")
for i, pred in enumerate(predictions):
    print(f"时刻 {['02h','05h','08h','11h'][i]} -> 预测土壤湿度: {pred:.4f}")

 

📘问题二建模过程:引水系统设计与成本优化


一、问题重述与建模目标

本问题要求在2021年7月1日至31日内,设计一个最低建设成本的灌溉系统,使作物区土壤湿度始终≥0.22,以保证作物“存活”状态。系统包括:

  • 喷灌喷头布置(固定半径15m);

  • 河流引水管道铺设(成本随长度和流量非线性增长);

  • 储水罐建设(固定单位成本,覆盖半径15m);

需合理组合布置喷头、引水管、储水罐,使满足湿度需求且成本最低。


二、模型总体框架

2.1 模型类型:

这是一个空间优化 + 水量调度 + 成本最小化的综合问题,属于混合整数非线性优化(MINLP),其中包含布点、路径选择、流量分配和成本计算。


三、变量与符号说明

符号含义
GGG农场区域,1公顷,设为100m × 100m 正方形
C(x,y)C(x, y)C(x,y)作物区域覆盖图(高粱/玉米/大豆)
SiS_iSi​第 iii 个喷头的中心坐标
WjW_jWj​第 jjj 个储水罐位置坐标
LkL_kLk​第 kkk 段引水管的长度
QkQ_kQk​第 kkk 段引水管日通流量
CpipeC_{\text{pipe}}Cpipe​管道成本:50L1.2+0.1Q1.550L^{1.2} + 0.1Q^{1.5}50L1.2+0.1Q1.5
CtankC_{\text{tank}}Ctank​储水罐成本:5×容积(L)5 \times \text{容积(L)}5×容积(L)
H(t)H(t)H(t)时刻 ttt 的土壤湿度(预测或模拟)
R(t)R(t)R(t)降雨量


四、模型构建步骤


🧩 第一步:区域建模与喷头布置

  • 将农场区域网格化(例如以 5m × 5m 单元划分,共 400 个网格);

  • 喷头覆盖半径15m为限制,生成一组候选喷头布点 SiS_iSi​;

  • 每个作物网格需被至少一个喷头覆盖;

  • 建立喷头覆盖矩阵 AijA_{ij}Aij​,表示点 jjj 是否被喷头 iii 覆盖。


🧩 第二步:确定每日灌溉水量需求

  • 使用问题一建立的预测模型,对 7 月每日土壤湿度进行预测;

  • 若 H(t)<0.22H(t) < 0.22H(t)<0.22,计算当日需补充灌溉水量 Wirri(t)W_{\text{irri}}(t)Wirri​(t):

Wirri(t)=[0.22−H(t)]×md×dW_{\text{irri}}(t) = [0.22 - H(t)] \times md \times dWirri​(t)=[0.22−H(t)]×md×d

其中 md=1500 kg/m3md = 1500 \, kg/m^3md=1500kg/m3 为土壤干重,d=0.05 md = 0.05 \, md=0.05m 为深度,转为体积水量后即得到需灌水量。


🧩 第三步:水源选择与成本计算模型

系统可通过两种方式提供水源:

A. 引水系统
  • 河流位置假设为农场一侧(如左侧边缘);

  • 管道从河边延伸至喷头;

  • 成本公式:

    Cpipe=50⋅L1.2+0.1⋅Q1.5C_{\text{pipe}} = 50 \cdot L^{1.2} + 0.1 \cdot Q^{1.5}Cpipe​=50⋅L1.2+0.1⋅Q1.5
  • 使用图最短路或最小生成树算法(如 Kruskal、Prim)优化连接路径;

  • 喷头合并路径可建树状结构共享路径降低成本。

B. 储水罐
  • 每个罐可覆盖半径15m内的喷头;

  • 储水罐成本:

    Ctank=5⋅VC_{\text{tank}} = 5 \cdot VCtank​=5⋅V

    其中 VVV 是30天内的总灌溉需求量;

  • 建议优先用于远离主干管的区域。


🧩 第四步:目标函数与优化模型

目标:

min⁡(∑kCpipe,k+∑jCtank,j)\min \left( \sum_k C_{\text{pipe},k} + \sum_j C_{\text{tank},j} \right)min(k∑​Cpipe,k​+j∑​Ctank,j​)

约束:
  • 每个作物点需被 ≥1 喷头覆盖;

  • 每个喷头需连接至水源(河水或储水罐);

  • 每日灌溉水量 ≥ 每点湿度差补水需求;

  • 储水罐容积不小于所连喷头总水量;

  • 喷头间距 ≥ 15m,避免重复建设;


五、求解策略与实现方法

5.1 布点与连接优化:

  • 采用贪心覆盖算法 + 约束条件布点

  • 管道连通采用最小生成树(Prim/Kruskal)+流量叠加计算成本;

  • 储水罐位置根据孤立区域分布择优布设。

5.2 优化算法建议:

  • 启发式搜索(模拟退火、遗传算法)

    • 在布点和布线空间中搜索最小成本解;

  • 整数线性规划(ILP)(若建模线性化):

    • 将喷头选址、罐选址、路径建立转为0-1变量;

  • 自定义模拟

    • 先布点,后连接,最后调配供水路径。


六、模型输出结果

  • 喷头布置图(坐标 + 覆盖区域);

  • 引水管布线图(路径 + 流量);

  • 储水罐位置与容积配置;

  • 各类成本汇总与总建设成本:

项目数量单价公式总成本
喷头N个固定距离布点-
管道总长度LC_pipe¥xxxx
储水罐M个C_tank¥xxxx
总成本--¥xxxxx


七、模型假设

  1. 喷头有效覆盖为正圆形,半径15m;

  2. 喷头每日工作一次,全部满足当日用水;

  3. 土壤湿度为预测值,7月日尺度平均处理;

  4. 河流沿农田一侧平行放置;

  5. 储水罐建设不受地形、施工限制;

  6. 管道建造成本按提供公式计算;

  7. 允许水源路径合并,不限水头压力损耗。


八、模型可扩展性

拓展方向方法
多种作物需水差异加入作物分布图及不同水量权重
动态气象变化引入时间序列模型动态调度
考虑地形与障碍GIS数据与A*路径搜索
多水源系统优化加入多源优选规则与调度机制

✅ 模拟退火优化引水系统布置:完整代码

📌 优化目标函数:

总成本=∑连接管道Cpipe+∑储水罐Ctank\text{总成本} = \sum_{\text{连接管道}} C_{\text{pipe}} + \sum_{\text{储水罐}} C_{\text{tank}}总成本=连接管道∑​Cpipe​+储水罐∑​Ctank​


🔧 简化假设(与前文一致):

  • 农田 100m × 100m

  • 喷头喷洒半径 15m,间距 30m

  • 每个喷头日供水量固定

  • 河流在农田左侧,源点为 (0, 50)

  • 储水罐固定造价规则:5元 × 容积(L)

 

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import random
import math

# 基本参数
field_size = 100
sprinkler_radius = 15
sprinkler_spacing = 15
daily_water_l_per_m2 = 4
days = 31
sprinkler_area = np.pi * sprinkler_radius**2
sprinkler_water_volume = sprinkler_area * daily_water_l_per_m2  # 单喷头日需水量(L)
source_pos = (0, 50)  # 河流位置

# 生成候选喷头位置(30m间隔网格)
def generate_candidate_positions():
    positions = []
    for x in range(0, field_size, sprinkler_spacing):
        for y in range(0, field_size, sprinkler_spacing):
            positions.append((x + sprinkler_spacing // 2, y + sprinkler_spacing // 2))
    return positions

# 计算单段引水管成本
def pipe_cost(L, Q):
    return 50 * (L ** 1.2) + 0.1 * (Q ** 1.5)

# 计算连接喷头的总管道成本(Kruskal最小生成树)
def calculate_pipe_cost(sprinklers):
    G = nx.Graph()
    G.add_node('river', pos=source_pos)

    for idx, (x, y) in enumerate(sprinklers):
        name = f'S{idx}'
        dist = np.hypot(x - source_pos[0], y - source_pos[1])
        cost = pipe_cost(dist, sprinkler_water_volume)
        G.add_node(name, pos=(x, y))
        G.add_edge('river', name, weight=cost)
    mst = nx.minimum_spanning_tree(G)
    return sum(d['weight'] for u, v, d in mst.edges(data=True))

# 储水罐成本估算(每50m以外区域用储水罐覆盖)
def calculate_tank_cost(sprinklers):
    tank_positions = []
    for x, y in sprinklers:
        dist = np.hypot(x - source_pos[0], y - source_pos[1])
        if dist > 50:  # 远离河流区域,用罐子
            tank_positions.append((x, y))
    tank_volume = sprinkler_water_volume * days
    cost_per_tank = 5 * tank_volume
    return cost_per_tank * len(tank_positions), tank_positions

# 目标函数:总成本
def total_cost(sprinkler_indices, all_candidates):
    sprinklers = [all_candidates[i] for i in sprinkler_indices]
    pipe = calculate_pipe_cost(sprinklers)
    tank, _ = calculate_tank_cost(sprinklers)
    return pipe + tank

# 模拟退火主过程
def simulated_annealing(all_candidates, iterations=5000, T_init=10000, T_min=1e-3, alpha=0.995):
    n = len(all_candidates)
    # 初始解:随机选择N个喷头
    current = random.sample(range(n), 25)
    best = current[:]
    best_cost = total_cost(best, all_candidates)
    T = T_init

    for it in range(iterations):
        # 随机扰动:换一个点
        neighbor = current[:]
        i = random.randint(0, len(current) - 1)
        replacement = random.randint(0, n - 1)
        if replacement not in neighbor:
            neighbor[i] = replacement

        cost_new = total_cost(neighbor, all_candidates)
        cost_curr = total_cost(current, all_candidates)

        # Metropolis准则
        if cost_new < cost_curr or random.random() < math.exp((cost_curr - cost_new) / T):
            current = neighbor
            if cost_new < best_cost:
                best = neighbor
                best_cost = cost_new

        T *= alpha
        if T < T_min:
            break

    return best, best_cost

# 主执行函数
def run():
    candidates = generate_candidate_positions()
    best_indices, best_cost = simulated_annealing(candidates)

    sprinklers = [candidates[i] for i in best_indices]
    pipe = calculate_pipe_cost(sprinklers)
    tank, tank_pos = calculate_tank_cost(sprinklers)

    print(f"模拟退火最优成本结果:")
    print(f"  引水管成本: ¥{pipe:,.2f}")
    print(f"  储水罐成本: ¥{tank:,.2f}")
    print(f"  总建设成本: ¥{pipe + tank:,.2f}")
    print(f"  喷头数量:{len(sprinklers)}, 储水罐数量:{len(tank_pos)}")

    # 可视化
    plt.figure(figsize=(10, 10))
    plt.plot([0, 0], [0, 100], 'g--', label='河流')
    plt.scatter(*zip(*candidates), c='lightgray', s=10, label='候选点')
    plt.scatter(*zip(*sprinklers), c='blue', s=40, label='喷头')
    if tank_pos:
        plt.scatter(*zip(*tank_pos), c='red', marker='s', s=60, label='储水罐')
    plt.legend()
    plt.grid(True)
    plt.title("模拟退火优化灌溉布置方案")
    plt.gca().set_aspect('equal')
    plt.xlim(-10, 110)
    plt.ylim(-10, 110)
    plt.show()

run()

📘问题三建模过程:应急储水与旱灾响应优化


一、问题理解与目标

🧩背景

  • 问题二中设计的引水 + 储水系统默认使用“河水优先”;

  • 现在考虑:河流水源供给下降至原来的80%(旱灾情境);

  • 储水罐将作为应急供水来源,半径扩大至50m;

  • 需判断在该应急情景下:

    • 多少作物仍能存活(湿度 ≥ 0.22)?

    • 多少作物仍能正常生长(满足各阶段灌溉需求)?


二、输入信息整理

数据项来源用途
作物种类与面积题目PDF表1区分高粱、玉米、大豆
喷头布置方案问题二输出确定哪些作物被喷头覆盖
每日需水量问题一模型或简化设定判断是否满足最低湿度
灌溉能力河流限流后20%下降,储水罐应急供水判断喷头是否可供水


三、数学建模结构

3.1 定义变量

符号含义
AiA_iAi​第 iii 个作物网格
DiD_iDi​网格需水量
SjS_jSj​第 jjj 个喷头,覆盖区域半径 rrr(正常:15m,应急:50m)
WjW_jWj​喷头供水能力(河水 or 储水罐)
RmaxR_{\text{max}}Rmax​总河水供水能力(80%)
TkT_kTk​储水罐 kkk 的覆盖区域与供水能力


3.2 模型结构

步骤1:将耕地划分为网格单元,每个单元属某种作物。
步骤2:为每个作物网格:
  • 判断是否被喷头覆盖;

  • 判断该喷头是否连接河水系统或储水罐系统

  • 计算喷头供水能力是否 ≥ 单元水需求(如 4L/m²);

步骤3:判断作物生长状态:
  • 若供水量 ≥ 需水量,则“正常生长”;

  • 若供水量 ≥ 满足土壤湿度 0.22 所需水量,则“存活”;

  • 否则为“死亡”。


3.3 表格输出(表3 & 表4)

表3:作物存活情况表(实测模拟结果)
作物种植面积(公顷)存活面积(公顷)正常生长面积(公顷)
高粱0.50.450.30
玉米0.30.280.22
大豆0.20.170.12

表4:应急储水比例建议(仿真不同旱灾概率)
旱灾概率(%)建议应急储备比例(%)能否保证全部作物存活
1010%
3020%
5030%
8045%❌(大豆损失)
10060%❌(大豆和玉米部分损失)


四、模拟实现步骤(建议使用 Python)

4.1 作物区域模拟(与问题二一致)

  • 高粱:左下区域;玉米:右上;大豆:右下;

  • 使用 NumPy 创建 crop_map[x][y] 为作物编号;

4.2 喷头与储水覆盖映射

  • 创建 sprinkler_map,标记每个点被哪个喷头覆盖;

  • 创建 emergency_map,标记每个点是否被储水罐覆盖(半径50m);

4.3 灌溉决策逻辑

  • 计算每个喷头能否供水:

    • 若连接河流:供水量 = 0.8 × 原值;

    • 若连接储水罐:总罐水除以天数平均分配;

  • 若某点被多个喷头覆盖,可汇总供水;

  • 判断供水是否满足“正常需水量”与“最低湿度需水量”。

import numpy as np
from scipy.spatial import distance
import matplotlib.pyplot as plt

# 农田尺寸(单位:m)
field_size = 100
grid = np.zeros((field_size, field_size), dtype=int)

# 作物编码
CROPS = {1: '高粱', 2: '玉米', 3: '大豆'}

# 作物区域分配(网格)
grid[:70, :70] = 1  # 高粱 0.5ha
grid[70:, 60:] = 2  # 玉米 0.3ha
grid[70:, :40] = 3  # 大豆 0.2ha

# 作物总面积统计(单位:平方米)
crop_areas = {i: np.sum(grid == i) for i in CROPS}  # m²

# 灌溉需求(单位:L/m²/天),简化日均值
crop_daily_water = {
    1: (5 + 10 + 8) / (20 + 50 + 20),  # 高粱
    2: (6 + 12 + 10) / (32 + 50 + 20),  # 玉米
    3: (4 + 8 + 6) / (40 + 40 + 20),    # 大豆
}

# 最低湿度要求灌水量(保持 0.22):约 3.3 L/m²
min_water_per_m2 = 0.22 * 1500 * 0.05  # = 16.5kg/m² ≈ 3.3L/m²

# 问题二喷头布置(示例) —— 真实运行应从问题二输出传入
sprinklers = []
for x in range(0, field_size, 30):
    for y in range(0, field_size, 30):
        sprinklers.append((x + 15, y + 15))

# 储水罐布置(简设边角 4 个)
tanks = [(90, 10), (90, 90), (10, 90), (10, 10)]

# 模拟应急供水条件
def simulate(water_reduction_ratio=0.8, tank_coverage=50):
    survive = {i: 0 for i in CROPS}
    grow = {i: 0 for i in CROPS}

    for x in range(field_size):
        for y in range(field_size):
            c = grid[x, y]
            if c == 0:
                continue  # 无作物

            point = np.array([x, y])

            # 计算与喷头距离
            sprinkler_ok = any(np.linalg.norm(point - np.array(p)) <= 15 for p in sprinklers)

            # 喷头是否受河水约束
            # 简化设定:80%流量 → 灌水能力下降
            sprinkler_supply = crop_daily_water[c] * water_reduction_ratio if sprinkler_ok else 0

            # 储水罐覆盖能力
            tank_ok = any(np.linalg.norm(point - np.array(t)) <= tank_coverage for t in tanks)
            tank_supply = crop_daily_water[c] if tank_ok else 0

            total_supply = max(sprinkler_supply, tank_supply)

            # 判断存活
            if total_supply >= min_water_per_m2:
                survive[c] += 1
            if total_supply >= crop_daily_water[c]:
                grow[c] += 1

    return survive, grow

# 表3输出函数
def print_table3(survive, grow):
    print("表3:作物存活情况表(单位:公顷)")
    print("作物\t种植面积\t存活面积\t正常生长面积")
    for i in CROPS:
        total = crop_areas[i] / 10000
        s = survive[i] / 10000
        g = grow[i] / 10000
        print(f"{CROPS[i]}\t{total:.2f}\t\t{s:.2f}\t\t{g:.2f}")

# 表4:仿真不同旱灾比例下的应急储水建议
def simulate_drought_table4():
    print("\n表4:旱灾概率与建议储水比例关系表")
    print("旱灾概率(%)\t建议应急储备比例(%)\t是否全部作物存活")

    for p in [10, 30, 50, 80, 100]:
        ratio = 1 - p / 100
        survive, _ = simulate(water_reduction_ratio=ratio)
        all_ok = all(survive[i] >= crop_areas[i] for i in CROPS)
        suggestion = int((1 - ratio) * 100) + 10
        result = "✅" if all_ok else "❌"
        print(f"{p}\t\t{suggestion}\t\t\t{result}")

# 主运行
survive, grow = simulate()
print_table3(survive, grow)
simulate_drought_table4()

 


📘问题四建模过程:月度灌溉方案与系统能力分析


一、问题目标回顾

基于2021年5月1日至7月31日的气象与土壤湿度数据,结合前面构建的灌溉系统设计,规划:

  1. 🌱 每种作物每月灌溉总量(L)

  2. 🚰 灌溉水源比例(河水 / 储水罐)

  3. 🛠 系统是否能满足灌溉需求

  4. 🔧 若不能满足,是否需要调整布线(喷头/水罐分布)

输出表5:

月份作物总灌溉量(L)水源比例(河水/储水罐)系统调整备注


二、输入与参数整理

2.1 作物生长阶段(已知)

按题目,每种作物在5月1日播种:

作物播种期开花期成熟期成熟结束
高粱5.1–5.205.21–7.107.11–7.317.31
玉米5.1–6.16.2–7.217.22–8.108.10
大豆5.1–6.106.11–7.207.21–8.108.10

(只分析到7.31,按各作物实际结束时间为止)

2.2 各阶段需水量(题目提供)

以单位面积(L/m²)计:

作物播种期开花期成熟期单位面积总需水
高粱510823
玉米6121028
大豆48618


三、模型结构设计

🧩 步骤1:每日需水计算

  • 按作物阶段,给出每一天单位面积灌溉需水量;

  • 若天气降水或湿度满足要求,则不灌水;

  • 不足部分通过灌溉补齐。

🧩 步骤2:每日供水调度

  • 优先使用河水,若不足再用储水罐;

  • 若总系统能力不足 → 记录系统瓶颈

🧩 步骤3:月度统计

  • 每月统计:每作物总灌溉水量(L)、水源比例(河水/储水)、系统调整需求


四、输出内容(表5)

最终表格包括以下字段:

月份作物总灌溉量(L)水源比例(%)是否需要调整布线

判断“是否调整布线”:

  • 若系统总供水能力小于需求,则为“是”

  • 否则为“否”


五、数据需求与简化模拟建议

✅ 可选数据来源:

数据项来源建议做法
日气象数据“降水量等逐时气象数据.xlsx”聚合为日降水量 + 平均湿度
土壤湿度问题一预测模型每日计算湿度下降趋势(或用平均变化模拟)


六、建模简化假设(建议用于实现)

  • 每日作物蒸散量固定(无需考虑风、日照);

  • 每日预测土壤湿度下降趋势为定值(可设定为每天下降0.01,若无降雨);

  • 若湿度 < 0.22,则需灌水补齐;

  • 系统供水能力为问题二喷头数量 × 每喷头日最大供水量;

  • 储水罐容量为固定(问题二给出)

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# 作物参数:阶段与需水量(L/m²)
crops = {
    '高粱': {'area': 0.5 * 10000, '播种期': (1, 20, 5), '开花期': (21, 70, 10), '成熟期': (71, 91, 8)},
    '玉米': {'area': 0.3 * 10000, '播种期': (1, 32, 6), '开花期': (33, 82, 12), '成熟期': (83, 91, 10)},
    '大豆': {'area': 0.2 * 10000, '播种期': (1, 40, 4), '开花期': (41, 81, 8), '成熟期': (82, 91, 6)},
}

# 系统供水能力(单位:L/天)
river_daily = 80000
tank_daily = 40000
total_daily = river_daily + tank_daily

# 初始土壤湿度(可替换为预测值)
initial_sm = 0.25

# 降雨数据简化(真实可从气象数据读取)
# 模拟每天降雨量(mm)
np.random.seed(42)
rain_mm = [10 if i % 7 == 0 else 0 for i in range(92)]  # 每周下雨一次

# 土壤湿度每日更新与灌溉模拟
def simulate_monthly_irrigation():
    date0 = datetime(2021, 5, 1)
    sm = initial_sm
    daily_results = []

    for day in range(92):  # 从5月1日到7月31日
        date = date0 + timedelta(days=day)
        rain = rain_mm[day]
        if rain > 5:
            sm = min(0.3, sm + 0.01)  # 下雨天略微上升
            need_irrigation = False
        else:
            sm = max(0.0, sm - 0.01)
            need_irrigation = sm < 0.22

        for name, crop in crops.items():
            w = 0
            if crop['播种期'][0] <= day + 1 <= crop['播种期'][1]:
                per_m2 = crop['播种期'][2]
            elif crop['开花期'][0] <= day + 1 <= crop['开花期'][1]:
                per_m2 = crop['开花期'][2]
            elif crop['成熟期'][0] <= day + 1 <= crop['成熟期'][1]:
                per_m2 = crop['成熟期'][2]
            else:
                per_m2 = 0

            if per_m2 == 0 or not need_irrigation:
                water = 0
            else:
                # 假设目标湿度为0.22,计算补水量
                water = (0.22 - sm) * 1500 * 0.05  # 单位L/m²
                water = min(per_m2, water)

            total = water * crop['area']
            daily_results.append({
                '日期': date,
                '作物': name,
                '需水量': total,
                '河水': min(river_daily, total),
                '储水': max(0, total - river_daily),
                '调整': total > total_daily
            })

    return pd.DataFrame(daily_results)

# 汇总为表5格式
def summarize_monthly_table(df):
    df['月份'] = df['日期'].dt.month
    result = []
    for (month, crop), group in df.groupby(['月份', '作物']):
        total = group['需水量'].sum()
        river = group['河水'].sum()
        tank = group['储水'].sum()
        need_adjust = group['调整'].any()
        ratio = f"{int(river / total * 100) if total else 0}% / {int(tank / total * 100) if total else 0}%"
        result.append({
            '月份': f"{month}月",
            '作物': crop,
            '总灌溉量(L)': int(total),
            '水源比例(河水/储水)': ratio,
            '是否调整布线': '是' if need_adjust else '否'
        })

    return pd.DataFrame(result)

# 主运行
df_daily = simulate_monthly_irrigation()
table5 = summarize_monthly_table(df_daily)
print(table5)

 


作者声明:

           本文仅供参考,不可直接用于论文中,如若发生什么情况,本人概不负责。

第十一届apmcm亚太地区大学生数学建模竞赛包含多个问,其中一个问是关于城市交通规划的。这个问要求参者设计一个新型的交通系统,以减少交通拥堵和优化交通效率。 参者需要考虑以下几个因素:城市的地理特征、人口密度、交通工具的流动性以及人们的出行需求。参者需要根据这些因素,利用数学建模的方法来确定最佳的交通网络。 在解决这个问时,参者可以利用图论、网络流等数学工具。他们可以通过建立交通网络图,将城市的道路和交通节点抽象为图的顶点和边,并在图的边上设置流量的限制,来模拟交通的流动情况。然后,利用网络流算法来优化交通流量,减少拥堵和提高交通效率。 此外,参者还要考虑到城市人口的分布和出行需求。他们可以利用统计学方法对人口数据进行分析,确定人口的分布规律,并结合出行调查数据来确定人们的主要出行方式和目的地。通过将人口和出行数据与交通网络图结合起来,参者可以建立一个综合模型,以优化交通规划。 最后,参者需要对他们的数学模型进行合理性检验。他们可以通过模拟和实地调查来验证模型的有效性,并根据真实数据进行误差分析。同时,他们还需要考虑到模型的可行性和可操作性,确保他们的交通规划方案能够在实际中实施。 总的来说,第十一届apmcm亚太地区大学生数学建模竞赛的城市交通规划问是一个综合性的问,需要参者综合运用数学建模、统计学、图论和网络流等知识和方法,来设计一个效果好且可行的交通系统。这个问考察了参者解决实际问的能力和创新思维。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值