问题重述
📘问题一建模过程:土壤湿度预测模型构建
一、问题背景与目标
农业灌溉系统的智能化依赖于对土壤湿度的精确掌握。土壤湿度受气象因素如温度、气压、湿度、降水、风速等影响。若能准确预测土壤湿度水平,可为精准灌溉决策提供基础。
本问题要求建立一个预测模型,依据逐时气象数据,预测5cm深度土壤湿度(5cm_SM
)的值,从而辅助后续灌溉管理与系统设计。
二、数据说明与预处理
2.1 数据来源
-
土壤湿度数据(文件:该地土壤湿度数据.xlsx)
包含不同深度(如5cm)的土壤湿度观测数据,以及对应的时间戳。 -
气象数据(文件:降水量等逐时气象数据.xlsx)
包含每小时的气温、气压、湿度、风速、降水量等共20多个气象变量。
表头说明详见《表附件说明.docx》,具体特征含义见文末附录。
2.2 数据预处理步骤
-
统一时间格式:将两个数据集的“时间”列统一为
datetime
格式,精确到小时; -
内连接合并:按时间戳将两个数据集连接(取交集部分);
-
缺失值处理:剔除含有缺失数据的样本;
-
数据清洗:过滤掉不合逻辑的观测值(如湿度>100%、风速为负等);
-
选取预测特征:初步选用与湿度关系强的特征字段(详见下节)。
三、特征选择与分析
根据气象机理和相关性分析,我们初选以下变量作为输入特征:
特征名 | 含义 |
---|---|
T | 地面气温(℃) |
Po | 大气压(站点水平) |
P | 平均海平面气压 |
Pa | 气压变化趋势 |
U | 相对湿度(%) |
Ff | 平均风速(10-12m) |
RRR | 降水量(mm) |
部分特征如风向(DD)为分类变量,不纳入首轮建模;也可在后续尝试加入哑变量。
我们采用皮尔逊相关系数分析特征与土壤湿度(5cm_SM)之间的相关性,确认其预测力。
四、模型选择与构建
考虑土壤湿度与气象之间的非线性关系,我们选用以下两种模型对比:
-
随机森林回归(Random Forest Regression)
非参数集成学习模型,对非线性特征拟合能力强,鲁棒性好。 -
多元线性回归(Baseline)
作为对照模型,评估非线性模型的优势。
建模流程:
-
特征标准化(Z-score 标准化);
-
划分训练集和测试集(80%:20%);
-
模型训练;
-
模型评估(R²、均方误差MSE);
-
可视化预测效果(预测 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) | T | Po | P | Pa | U | Ff | RRR | 预测5cm_SM |
---|---|---|---|---|---|---|---|---|
02 | 19.3 | 731.5 | 751.7 | 1.0 | 99 | 1.5 | 15.0 | ~0.365 |
05 | 20.0 | 732.0 | 752.4 | 0.5 | 94 | 2.0 | 6.0 | ~0.340 |
08 | 23.4 | 732.8 | 753.2 | 0.8 | 80 | 1.8 | 0 | ~0.295 |
11 | 28.0 | 733.5 | 753.8 | 0.7 | 44 | 2.2 | 0 | ~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个 | 固定距离布点 | - |
管道总长度 | L | C_pipe | ¥xxxx |
储水罐 | M个 | C_tank | ¥xxxx |
总成本 | - | - | ¥xxxxx |
七、模型假设
-
喷头有效覆盖为正圆形,半径15m;
-
喷头每日工作一次,全部满足当日用水;
-
土壤湿度为预测值,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.5 | 0.45 | 0.30 |
玉米 | 0.3 | 0.28 | 0.22 |
大豆 | 0.2 | 0.17 | 0.12 |
表4:应急储水比例建议(仿真不同旱灾概率)
旱灾概率(%) | 建议应急储备比例(%) | 能否保证全部作物存活 |
---|---|---|
10 | 10% | ✅ |
30 | 20% | ✅ |
50 | 30% | ✅ |
80 | 45% | ❌(大豆损失) |
100 | 60% | ❌(大豆和玉米部分损失) |
四、模拟实现步骤(建议使用 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日的气象与土壤湿度数据,结合前面构建的灌溉系统设计,规划:
-
🌱 每种作物每月灌溉总量(L)
-
🚰 灌溉水源比例(河水 / 储水罐)
-
🛠 系统是否能满足灌溉需求
-
🔧 若不能满足,是否需要调整布线(喷头/水罐分布)
输出表5:
月份 | 作物 | 总灌溉量(L) | 水源比例(河水/储水罐) | 系统调整备注 |
---|
二、输入与参数整理
2.1 作物生长阶段(已知)
按题目,每种作物在5月1日播种:
作物 | 播种期 | 开花期 | 成熟期 | 成熟结束 |
---|---|---|---|---|
高粱 | 5.1–5.20 | 5.21–7.10 | 7.11–7.31 | 7.31 |
玉米 | 5.1–6.1 | 6.2–7.21 | 7.22–8.10 | 8.10 |
大豆 | 5.1–6.10 | 6.11–7.20 | 7.21–8.10 | 8.10 |
(只分析到7.31,按各作物实际结束时间为止)
2.2 各阶段需水量(题目提供)
以单位面积(L/m²)计:
作物 | 播种期 | 开花期 | 成熟期 | 单位面积总需水 |
---|---|---|---|---|
高粱 | 5 | 10 | 8 | 23 |
玉米 | 6 | 12 | 10 | 28 |
大豆 | 4 | 8 | 6 | 18 |
三、模型结构设计
🧩 步骤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)
作者声明:
本文仅供参考,不可直接用于论文中,如若发生什么情况,本人概不负责。