2024 年高教社杯全国大学生数学建模竞赛 C 题 农作物的种植策略(完整代码)

第一问代码:

(1) 

import pandas as pd
import numpy as np
from scipy.optimize import linprog
import random

# 读取四个表格的数据
file_1 = '2023年的种植数据与销售量.xlsx'
file_2 = '各作物聚合后销售量与价格.xlsx'
file_3 = '各作物适合种植的地块类型与季别.xlsx'
file_4 = '乡村的现有耕地.xlsx'

# 加载表格
df1 = pd.read_excel(file_1)
df2 = pd.read_excel(file_2)
df3 = pd.read_excel(file_3)
df4 = pd.read_excel(file_4)

# 提取2023年各作物的销售量
sales_2023 = df2.set_index('作物名称')['销售量/斤'].to_dict()

# 提取地块和作物信息
land_types = df4['地块名称'].unique().tolist()

# 根据df3筛选适合第一季和第二季的作物
def get_suitable_crops(season):
    if season == '第一季':
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'平旱地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'梯田'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'山坡地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'水浇地'] == 1]['作物名称'].tolist()
    else:
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist()
    
    return suitable_crops

suitable_crops_first_season = get_suitable_crops('第一季')
suitable_crops_second_season = get_suitable_crops('第二季')

# 过滤不在suitable_crops中的作物
crops_first_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_first_season]
crops_second_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_second_season]

# 第二季地块
land_types_second_season = ['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 
                            'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'E10', 'E11', 'E12', 'E13', 'E14', 'E15', 'E16', 
                            'F1', 'F2', 'F3', 'F4']

# 随机选择作物的数量,减少计算量
num_crops_to_select = 9

# 为第一季和第二季创建地块与作物的映射
def create_land_crop_mapping(land_types, crops):
    land_crop_mapping = {}
    for land in land_types:
        if len(crops) > num_crops_to_select:
            selected_crops = random.sample(crops, num_crops_to_select)
        else:
            selected_crops = crops  # 如果作物少于9种,全部选中
        land_crop_mapping[land] = selected_crops
    return land_crop_mapping

# 第一季
land_crop_mapping_first_season = create_land_crop_mapping(land_types, crops_first_season)

# 第二季
land_crop_mapping_second_season = create_land_crop_mapping(land_types_second_season, crops_second_season)

# 定义优化函数
def optimize_land_crop(land_crop_mapping, crops, season, year):
    # 初始化决策变量和目标函数:优化目标是最大化净收入,并最小化因超产导致的滞销损失。
    decision_vars = {}
    objective_coeffs = []

    for land, selected_crops in land_crop_mapping.items():
        for crop in selected_crops:
            decision_vars[(crop, land)] = 0

            land_type = df4[df4['地块名称'] == land]['地块类型'].values[0]
            yield_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['亩产量/斤'].values
            price_data = df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values
            cost_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['种植成本/(元/亩)'].values

            if len(yield_data) > 0 and len(price_data) > 0 and len(cost_data) > 0:
                yield_per_acre = yield_data[0]
                price_per_unit = price_data[0]
                cost_per_acre = cost_data[0]
                
                # 获取2023年作物销售量
                sales_2023_volume = sales_2023.get(crop, 0)
                
                # 计算实际销售收入
                net_revenue = (yield_per_acre * price_per_unit) - cost_per_acre
                
                # 计算滞销损失
                excess_volume = max(0, yield_per_acre - sales_2023_volume)
                wastage_loss = excess_volume * price_per_unit
                
                # 将净收入和滞销损失合并到目标函数中
                objective_coeffs.append(net_revenue - wastage_loss)
            else:
                objective_coeffs.append(0)

    objective_coeffs = np.array(objective_coeffs) * -1

    # 重新构建约束条件
    A_ub = []
    b_ub = []

    # 约束条件1:总面积约束
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land:
                constraint[i] = 1
        A_ub.append(constraint)
        b_ub.append(df4[df4['地块名称'] == land]['地块面积/亩'].values[0])

    # 约束条件2:最小种植面积约束
    for land in land_crop_mapping.keys():
        min_area = 0.1 * df4[df4['地块名称'] == land]['地块面积/亩'].values[0]
        for crop in land_crop_mapping[land]:
            constraint = np.zeros(len(decision_vars))
            for i, (crop_name, land_name) in enumerate(decision_vars.keys()):
                if crop_name == crop and land_name == land:
                    constraint[i] = -1
            A_ub.append(constraint)
            b_ub.append(-min_area)

    # 约束条件3:三年内至少种植一次豆类作物
    beans_crops = df3[df3['作物类型'].str.contains('粮食(豆类)')]['作物名称'].tolist()
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land and crop in beans_crops:
                constraint[i] = -1
        A_ub.append(constraint)
        b_ub.append(0)  # 三年内种植豆类作物的约束(具体实施时可能需要调整)

    A_ub = np.array(A_ub)
    b_ub = np.array(b_ub)

    # 优化模型
    result = linprog(c=objective_coeffs, A_ub=A_ub, b_ub=b_ub, method='highs')

    # 构建优化结果的表格输出
    if result.success:
        optimal_areas = result.x
        solution = {}
        
        for i, (crop, land) in enumerate(decision_vars.keys()):
            if land not in solution:
                solution[land] = {}
            solution[land][crop] = optimal_areas[i]

        # 确保结果表格中包含所有作物
        all_crops = sorted(set(df2['作物名称'].to_list()))  # 所有作物的集合(去重并排序)
        
        # 构建结果表格
        results = pd.DataFrame(columns=['年', '季别', '地块名'] + all_crops)
        
        for land, crop_areas in solution.items():
            season_data = {'年': year, '季别': season, '地块名': land}
            for crop in all_crops:
                season_data[crop] = crop_areas.get(crop, 0)  # 如果该作物不在该地块中,则面积为0
            
            results = results._append(season_data, ignore_index=True)

        return results
    else:
        print(f"{year}年{season}优化失败,无法生成结果表格。")
        return None

# 迭代计算 2024~2030 年的结果
years = list(range(2024, 2031))
all_results = []

for year in years:
    # 第一季
    results_first_season = optimize_land_crop(land_crop_mapping_first_season, crops_first_season, '第一季', year)
    # 第二季
    results_second_season = optimize_land_crop(land_crop_mapping_second_season, crops_second_season, '第二季', year)

    # 合并结果
    if results_first_season is not None and results_second_season is not None:
        combined_results = pd.concat([results_first_season, results_second_season], ignore_index=True)
        all_results.append(combined_results)

# 将所有结果写入Excel文件
if all_results:
    final_results = pd.concat(all_results, ignore_index=True)
    final_results.to_excel('2024至2030年农作物种植方案.xlsx', index=None)

(2) 

import pulp
import pandas as pd
import numpy as np
from scipy.optimize import linprog
import random

# 读取四个表格的数据
file_1 = '2023年的种植数据与销售量.xlsx'
file_2 = '各作物聚合后销售量与价格.xlsx'
file_3 = '各作物适合种植的地块类型与季别.xlsx'
file_4 = '乡村的现有耕地.xlsx'

# 加载表格
df1 = pd.read_excel(file_1)
df2 = pd.read_excel(file_2)
df3 = pd.read_excel(file_3)
df4 = pd.read_excel(file_4)

# 提取地块和作物信息
land_types = df4['地块名称'].unique().tolist()

# 根据df3筛选适合第一季和第二季的作物
def get_suitable_crops(season):
    if season=='第一季':
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist()+ \
                    df3[df3[f'平旱地'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'梯田'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'山坡地'] == 1]['作物名称'].tolist()+ \
                    df3[df3[f'水浇地'] == 1]['作物名称'].tolist()
    else:
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                     df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist()   
    
    return suitable_crops

suitable_crops_first_season = get_suitable_crops('第一季')
suitable_crops_second_season = get_suitable_crops('第二季')

# 过滤不在suitable_crops中的作物
crops_first_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_first_season]
crops_second_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_second_season]

# 第二季地块
land_types_second_season = ['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 
                            'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'E10', 'E11', 'E12', 'E13', 'E14', 'E15', 'E16', 
                            'F1', 'F2', 'F3', 'F4']

# 随机选择作物的数量,减少计算量
num_crops_to_select = 9

# 为第一季和第二季创建地块与作物的映射
def create_land_crop_mapping(land_types, crops):
    land_crop_mapping = {}
    for land in land_types:
        if len(crops) > num_crops_to_select:
            selected_crops = random.sample(crops, num_crops_to_select)
        else:
            selected_crops = crops  # 如果作物少于9种,全部选中
        land_crop_mapping[land] = selected_crops
    return land_crop_mapping

# 第一季
land_crop_mapping_first_season = create_land_crop_mapping(land_types, crops_first_season)

# 第二季
land_crop_mapping_second_season = create_land_crop_mapping(land_types_second_season, crops_second_season)

# 定义优化函数
def optimize_land_crop(land_crop_mapping, crops, season, year):
    # 初始化决策变量和目标函数
    decision_vars = {}
    objective_coeffs = []
    slack_vars = {}  # 存储超出部分的滞销收入
    '''目标函数调整:计算超出部分的收入,考虑按50%降价处理。

    计算每种作物的总净收入。
    计算超出部分的滞销收入(按2023年销售价格的50%)。
    目标函数是总净收入加上滞销收入。'''
    for land, selected_crops in land_crop_mapping.items():
        for crop in selected_crops:
            decision_vars[(crop, land)] = 0

            land_type = df4[df4['地块名称'] == land]['地块类型'].values[0]
            yield_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['亩产量/斤'].values
            price_data = df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values
            cost_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['种植成本/(元/亩)'].values
            sale_2023 = df2[df2['作物名称'] == crop]['销售量/斤'].values
            if len(sale_2023) > 0:
                sale_2023 = sale_2023[0]
            else:
                sale_2023 = 0

            if len(yield_data) > 0 and len(price_data) > 0 and len(cost_data) > 0:
                yield_per_acre = yield_data[0]
                price_per_unit = price_data[0]
                cost_per_acre = cost_data[0]
                reduced_price = price_per_unit * 0.5
                net_revenue = (yield_per_acre * price_per_unit - cost_per_acre)
                reduced_revenue = max(0, (yield_per_acre - sale_2023) * reduced_price)  # 滞销收入
                objective_coeffs.append(net_revenue + reduced_revenue)  # 目标函数:总净收入加上滞销收入
            else:
                objective_coeffs.append(0)

    objective_coeffs = np.array(objective_coeffs) * -1

    # 重新构建约束条件
    A_ub = []
    b_ub = []

    # 约束条件1:总面积约束
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land:
                constraint[i] = 1
        A_ub.append(constraint)
        b_ub.append(df4[df4['地块名称'] == land]['地块面积/亩'].values[0])

    # 约束条件2:最小种植面积约束
    for land in land_crop_mapping.keys():
        min_area = 0.1 * df4[df4['地块名称'] == land]['地块面积/亩'].values[0]
        for crop in land_crop_mapping[land]:
            constraint = np.zeros(len(decision_vars))
            for i, (crop_name, land_name) in enumerate(decision_vars.keys()):
                if crop_name == crop and land_name == land:
                    constraint[i] = -1
            A_ub.append(constraint)
            b_ub.append(-min_area)

    # 约束条件3:三年内至少种植一次豆类作物
    beans_crops = df3[df3['作物类型'].str.contains('粮食(豆类)')]['作物名称'].tolist()
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land and crop in beans_crops:
                constraint[i] = -1
        A_ub.append(constraint)
        b_ub.append(0)  # 三年内种植豆类作物的约束(具体实施时可能需要调整)

    A_ub = np.array(A_ub)
    b_ub = np.array(b_ub)

    # 优化模型
    result = linprog(c=objective_coeffs, A_ub=A_ub, b_ub=b_ub, method='highs')

    # 构建优化结果的表格输出
    if result.success:
        optimal_areas = result.x
        solution = {}
        
        for i, (crop, land) in enumerate(decision_vars.keys()):
            if land not in solution:
                solution[land] = {}
            solution[land][crop] = optimal_areas[i]

        # 确保结果表格中包含所有作物
        all_crops = sorted(set(df2['作物名称'].to_list()))  # 所有作物的集合(去重并排序)
        
        # 构建结果表格
        results = pd.DataFrame(columns=['年', '季别', '地块名'] + all_crops)
        
        for land, crop_areas in solution.items():
            season_data = {'年': year, '季别': season, '地块名': land}
            for crop in all_crops:
                season_data[crop] = crop_areas.get(crop, 0)  # 如果该作物不在该地块中,则面积为0
            
            results = results._append(season_data, ignore_index=True)

        return results
    else:
        print(f"{year}年{season}优化失败,无法生成结果表格。")
        return None

# 迭代计算 2024~2030 年的结果
years = list(range(2024, 2031))
all_results = []

for year in years:
    # 第一季
    results_first_season = optimize_land_crop(land_crop_mapping_first_season, crops_first_season, '第一季', year)
    # 第二季
    results_second_season = optimize_land_crop(land_crop_mapping_second_season, crops_second_season, '第二季', year)

    # 合并结果
    if results_first_season is not None and results_second_season is not None:
        combined_results = pd.concat([results_first_season, results_second_season], ignore_index=True)
        all_results.append(combined_results)

第二问代码:

import pulp
import pandas as pd
import numpy as np
from scipy.optimize import linprog
import random

# 读取四个表格的数据
file_1 = '2023年的种植数据与销售量.xlsx'
file_2 = '各作物聚合后销售量与价格.xlsx'
file_3 = '各作物适合种植的地块类型与季别.xlsx'
file_4 = '乡村的现有耕地.xlsx'

# 加载表格
df1 = pd.read_excel(file_1)
df2 = pd.read_excel(file_2)
df3 = pd.read_excel(file_3)
df4 = pd.read_excel(file_4)

# 定义随机生成函数
def random_range(value, percent):
    return value * (1 + np.random.uniform(-percent, percent))

# 生成销售量、亩产量、种植成本和销售价格的随机值
def generate_random_parameters(crop, year, crop_type):
    # 获取2023年的数据
    yield_data = df1[(df1['作物名称_x'] == crop)]['亩产量/斤'].values[0]
    price_data = df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values[0]
    cost_data = df1[(df1['作物名称_x'] == crop)]['种植成本/(元/亩)'].values[0]
    sales_volume_2023 = df2[df2['作物名称'] == crop]['销售量/斤'].values[0]

    # 计算未来年份的销售量、亩产量、种植成本和销售价格
    if crop_type == '粮食':
        sales_volume = sales_volume_2023 * (1 + np.random.uniform(0.05, 0.1)) ** (year - 2023)
    else:
        sales_volume = sales_volume_2023 * (1 + np.random.uniform(-0.05, 0.05)) ** (year - 2023)

    yield_per_acre = random_range(yield_data, 0.1)
    cost_per_acre = cost_data * (1 + 0.05) ** (year - 2023)
    
    if crop_type == '粮食':
        price_per_unit = price_data
    elif crop_type == '蔬菜':
        price_per_unit = price_data * (1 + 0.05) ** (year - 2023)
    else:
        price_decrease = 0.01 * np.random.uniform(1, 5) if crop != '羊肚菌' else 0.05
        price_per_unit = price_data * (1 - price_decrease) ** (year - 2023)
    
    return sales_volume, yield_per_acre, cost_per_acre, price_per_unit

# 根据df3筛选适合第一季和第二季的作物
def get_suitable_crops(season):
    if season == '第一季':
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'平旱地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'梯田'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'山坡地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'水浇地'] == 1]['作物名称'].tolist()
    else:
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist()
    
    return suitable_crops

suitable_crops_first_season = get_suitable_crops('第一季')
suitable_crops_second_season = get_suitable_crops('第二季')

# 过滤不在suitable_crops中的作物
crops_first_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_first_season]
crops_second_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_second_season]

# 提取地块和作物信息
land_types = df4['地块名称'].unique().tolist()

# 第二季地块
land_types_second_season = ['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 
                            'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'E10', 'E11', 'E12', 'E13', 'E14', 'E15', 'E16', 
                            'F1', 'F2', 'F3', 'F4']

# 随机选择作物的数量,减少计算量
num_crops_to_select = 9

# 为第一季和第二季创建地块与作物的映射
def create_land_crop_mapping(land_types, crops):
    land_crop_mapping = {}
    for land in land_types:
        if len(crops) > num_crops_to_select:
            selected_crops = random.sample(crops, num_crops_to_select)
        else:
            selected_crops = crops  # 如果作物少于9种,全部选中
        land_crop_mapping[land] = selected_crops
    return land_crop_mapping

# 第一季
land_crop_mapping_first_season = create_land_crop_mapping(land_types, crops_first_season)

# 第二季
land_crop_mapping_second_season = create_land_crop_mapping(land_types_second_season, crops_second_season)

# 定义目标函数和约束条件
def optimize_land_crop(land_crop_mapping, crops, season, year):
    # 初始化决策变量和目标函数
    decision_vars = {}
    objective_coeffs = []
    A_ub = []
    b_ub = []

    for land, selected_crops in land_crop_mapping.items():
        for crop in selected_crops:
            decision_vars[(crop, land)] = 0

            # 获取当前作物的参数
            crop_type = df3[df3['作物名称'] == crop]['作物类型'].values[0]
            sales_volume, yield_per_acre, cost_per_acre, price_per_unit = generate_random_parameters(crop, year, crop_type)
            
            # 计算超产部分按50%降价的销售收入
            sales_volume_2023 = df2[df2['作物名称'] == crop]['销售量/斤'].values[0]
            excess_volume = sales_volume - sales_volume_2023
            if excess_volume > 0:
                discounted_price = 0.5 * df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values[0]
                net_revenue = (sales_volume_2023 * price_per_unit - cost_per_acre) + (excess_volume * discounted_price - cost_per_acre)
            else:
                net_revenue = sales_volume * price_per_unit - cost_per_acre

            objective_coeffs.append(-net_revenue)  # 目标函数是最大化净利润

    objective_coeffs = np.array(objective_coeffs)
    
    # 重新构建约束条件
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land:
                constraint[i] = 1
        A_ub.append(constraint)
        b_ub.append(df4[df4['地块名称'] == land]['地块面积/亩'].values[0])
    
    for land in land_crop_mapping.keys():
        min_area = 0.1 * df4[df4['地块名称'] == land]['地块面积/亩'].values[0]
        for crop in land_crop_mapping[land]:
            constraint = np.zeros(len(decision_vars))
            for i, (crop_name, land_name) in enumerate(decision_vars.keys()):
                if crop_name == crop and land_name == land:
                    constraint[i] = -1
            A_ub.append(constraint)
            b_ub.append(-min_area)
    
    beans_crops = df3[df3['作物类型'].str.contains('粮食(豆类)')]['作物名称'].tolist()
    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars.keys()):
            if land_name == land and crop in beans_crops:
                constraint[i] = -1
        A_ub.append(constraint)
        b_ub.append(0)
    
    A_ub = np.array(A_ub)
    b_ub = np.array(b_ub)

    # 优化模型
    result = linprog(c=objective_coeffs, A_ub=A_ub, b_ub=b_ub, method='highs')

    # 构建优化结果的表格输出
    if result.success:
        optimal_areas = result.x
        solution = {}
        
        for i, (crop, land) in enumerate(decision_vars.keys()):
            if land not in solution:
                solution[land] = {}
            solution[land][crop] = optimal_areas[i]
        
        all_crops = sorted(set(df2['作物名称'].to_list()))
        
        results = pd.DataFrame(columns=['年', '季别', '地块名'] + all_crops)
        
        for land, crop_areas in solution.items():
            season_data = {'年': year, '季别': season, '地块名': land}
            for crop in all_crops:
                season_data[crop] = crop_areas.get(crop, 0)
            
            results = results._append(season_data, ignore_index=True)

        return results
    else:
        print(f"{year}年{season}优化失败,无法生成结果表格。")
        return None

# 迭代计算 2024~2030 年的结果
years = list(range(2024, 2031))
all_results = []

for year in years:
    results_first_season = optimize_land_crop(land_crop_mapping_first_season, crops_first_season, '第一季', year)
    results_second_season = optimize_land_crop(land_crop_mapping_second_season, crops_second_season, '第二季', year)

    if results_first_season is not None and results_second_season is not None:
        combined_results = pd.concat([results_first_season, results_second_season], ignore_index=True)
        all_results.append(combined_results)

# 将所有结果写入Excel文件
if all_results:
    final_results = pd.concat(all_results, ignore_index=True)
    final_results.to_excel('2024至2030年农作物种植方案Q2.xlsx', index=None)

第三问代码:

import pulp
import pandas as pd
import numpy as np
from scipy.optimize import linprog
import random

# 读取四个表格的数据
file_1 = '2023年的种植数据与销售量.xlsx'
file_2 = '各作物聚合后销售量与价格.xlsx'
file_3 = '各作物适合种植的地块类型与季别.xlsx'
file_4 = '乡村的现有耕地.xlsx'

# 加载表格
df1 = pd.read_excel(file_1)
df2 = pd.read_excel(file_2)
df3 = pd.read_excel(file_3)
df4 = pd.read_excel(file_4)

# 提取地块和作物信息
land_types = df4['地块名称'].unique().tolist()

# 根据df3筛选适合第一季和第二季的作物
def get_suitable_crops(season):
    if season == '第一季':
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'平旱地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'梯田'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'山坡地'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'水浇地'] == 1]['作物名称'].tolist()
    else:
        suitable_crops = df3[df3[f'水浇地{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'普通大棚{season}'] == 1]['作物名称'].tolist() + \
                         df3[df3[f'智慧大棚{season}'] == 1]['作物名称'].tolist()
    return suitable_crops

suitable_crops_first_season = get_suitable_crops('第一季')
suitable_crops_second_season = get_suitable_crops('第二季')

# 过滤不在suitable_crops中的作物
crops_first_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_first_season]
crops_second_season = [crop for crop in df1['作物名称_x'].unique() if crop in suitable_crops_second_season]

# 第二季地块
land_types_second_season = ['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8',
                            'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'E10', 'E11', 'E12', 'E13', 'E14', 'E15', 'E16',
                            'F1', 'F2', 'F3', 'F4']

# 随机选择作物的数量,减少计算量
num_crops_to_select = 9

# 为第一季和第二季创建地块与作物的映射
def create_land_crop_mapping(land_types, crops):
    land_crop_mapping = {}
    for land in land_types:
        if len(crops) > num_crops_to_select:
            selected_crops = random.sample(crops, num_crops_to_select)
        else:
            selected_crops = crops  # 如果作物少于9种,全部选中
        land_crop_mapping[land] = selected_crops
    return land_crop_mapping

# 第一季
land_crop_mapping_first_season = create_land_crop_mapping(land_types, crops_first_season)

# 第二季
land_crop_mapping_second_season = create_land_crop_mapping(land_types_second_season, crops_second_season)

# 相关性矩阵
correlation_matrix = {
    '粮食': {'cost_price': -0.201, 'cost_quantity': 0.231, 'price_quantity': -0.509},
    '粮食(豆类)': {'cost_price': -0.697, 'cost_quantity': 0.428, 'price_quantity': -0.224},
    '蔬菜': {'cost_price': 0.282, 'cost_quantity': -0.224, 'price_quantity': -0.408},
    '蔬菜(豆类)': {'cost_price': 0.520, 'cost_quantity': -0.116, 'price_quantity': 0.166},
    '食用菌': {'cost_price': 0.505, 'cost_quantity': -0.109, 'price_quantity': -0.823}
}

# 定义生成随机参数的函数
def generate_random_parameters(crop, year):
    base_sales_volume = df2[df2['作物名称'] == crop]['销售量/斤'].values[0]
    base_yield = df1[(df1['作物名称_x'] == crop)]['亩产量/斤'].values[0]
    base_cost = df1[(df1['作物名称_x'] == crop)]['种植成本/(元/亩)'].values[0]
    base_price = df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values[0]

    if crop in correlation_matrix:
        correlation = correlation_matrix[crop]
    else:
        correlation = {'cost_price': 0, 'cost_quantity': 0, 'price_quantity': 0}

    # 销售量调整
    sales_volume_growth = np.random.uniform(0.95, 1.05) if crop not in ['小麦', '玉米'] else np.random.uniform(1.05, 1.10)
    sales_volume = base_sales_volume * (1 + sales_volume_growth)

    # 亩产量调整
    yield_variation = np.random.uniform(0.9, 1.1)
    yield_per_acre = base_yield * yield_variation

    # 种植成本调整
    cost_increase = np.random.uniform(0.05, 0.1)
    cost_per_acre = base_cost * (1 + cost_increase)

    # 销售价格调整
    if crop in ['食用菌', '羊肚菌']:
        price_decrease = np.random.uniform(0.01, 0.05) if crop == '食用菌' else 0.05
        price_per_unit = base_price * (1 - price_decrease)
    else:
        price_increase = np.random.uniform(0.05, 0.1)
        price_per_unit = base_price * (1 + price_increase)

    return sales_volume, yield_per_acre, cost_per_acre, price_per_unit

# 定义优化函数
def optimize_land_crop(land_crop_mapping, crops, season, year):
    # 初始化目标函数系数
    objective_coeffs = []
    decision_vars = []

    for land, selected_crops in land_crop_mapping.items():
        for crop in selected_crops:
            decision_vars.append((crop, land))

            land_type = df4[df4['地块名称'] == land]['地块类型'].values[0]
            yield_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['亩产量/斤'].values
            price_data = df2[df2['作物名称'] == crop]['销售单价/(元/斤)'].values
            cost_data = df1[(df1['作物名称_x'] == crop) & (df1['地块类型'] == land_type)]['种植成本/(元/亩)'].values

            if len(yield_data) > 0 and len(price_data) > 0 and len(cost_data) > 0:
                yield_per_acre = yield_data[0]
                price_per_unit = price_data[0]
                cost_per_acre = cost_data[0]
                net_revenue = (yield_per_acre * price_per_unit) - cost_per_acre
                objective_coeffs.append(net_revenue)
            else:
                objective_coeffs.append(0)

    objective_coeffs = np.array(objective_coeffs) * -1

    # 约束条件构建
    A_ub = []
    b_ub = []

    for land in land_crop_mapping.keys():
        constraint = np.zeros(len(decision_vars))
        for i, (crop, land_name) in enumerate(decision_vars):
            if land_name == land:
                constraint[i] = 1
        A_ub.append(constraint)
        b_ub.append(df4[df4['地块名称'] == land]['地块面积/亩'].values[0])

    for land in land_crop_mapping.keys():
        min_area = 0.1 * df4[df4['地块名称'] == land]['地块面积/亩'].values[0]
        for crop in land_crop_mapping[land]:
            constraint = np.zeros(len(decision_vars))
            for i, (crop_name, land_name) in enumerate(decision_vars):
                if crop_name == crop and land_name == land:
                    constraint[i] = -1
            A_ub.append(constraint)
            b_ub.append(-min_area)

    # 运行线性规划
    A_ub = np.array(A_ub)
    b_ub = np.array(b_ub)
    result = linprog(c=objective_coeffs, A_ub=A_ub, b_ub=b_ub, method='highs')

    if result.success:
        optimal_areas = result.x
        solution = {}
        
        for i, (crop, land) in enumerate(decision_vars):
            if land not in solution:
                solution[land] = {}
            solution[land][crop] = optimal_areas[i]

        # 确保结果表格中包含所有作物
        all_crops = sorted(set(df2['作物名称'].to_list()))  # 所有作物的集合(去重并排序)

        # 构建结果表格
        results = pd.DataFrame(columns=['年', '季别', '地块名'] + all_crops)

        for land, crop_areas in solution.items():
            season_data = {'年': year, '季别': season, '地块名': land}
            for crop in all_crops:
                season_data[crop] = crop_areas.get(crop, 0)  # 如果该作物不在该地块中,则面积为0
            
            results = results._append(season_data, ignore_index=True)

        return results
    else:
        print(f"{year}年{season}优化失败,无法生成结果表格。")
        return pd.DataFrame()

# 计算2024~2030年的结果
def calculate_results_for_years(start_year, end_year):
    results = {}
    for year in range(start_year, end_year + 1):
        first_season_result = optimize_land_crop(land_crop_mapping_first_season, crops_first_season, '第一季', year)
        second_season_result = optimize_land_crop(land_crop_mapping_second_season, crops_second_season, '第二季', year)
        combined_result = pd.concat([first_season_result, second_season_result], ignore_index=True)
        results[year] = combined_result
    return results

# 计算结果并保存
results = calculate_results_for_years(2024, 2030)

### 关于2024高教全国大学生数学建模竞赛C农作物种植策略的MATLAB实现 #### 问背景与目标设定 针对2024高教全国大学生数学建模竞赛C中的农作物种植策略,主要探讨如何通过优化模型来提高农业生产效率并减少资源浪费。该目旨在利用历史数据预测未来产量,并基于此制定最优播种计划[^1]。 #### 数据预处理阶段 为了构建有效的数学模型,在开始之前需先对收集到的历史气象条件、土壤肥力以及历收成情况进行清洗和整理。这一步骤通常涉及缺失值填补、异常点检测及标准化转换等工作。可以借助MATLAB内置函数完成这些操作: ```matlab % 假设data是一个包含原始观测记录的数据表 cleanedData = fillmissing(data, 'previous'); % 使用前一时刻数值填充缺省项 zscoredData = zscore(cleanedData); % 对各列执行Z分数变换以消除量纲影响 ``` #### 构建预测模型 接下来建立用于估计不同因素组合下预期产出水平的关系式。考虑到实际场景复杂多变的特点,推荐采用机器学习算法如支持向量机(SVM)或随机森林(Random Forest),它们能够较好地捕捉非线性模式且具备较强的泛化能力。下面给出一段简单的SVM训练过程示例代码片段: ```matlab % X代表输入特征矩阵;Y表示对应的目标变量向量 model = fitcsvm(X,Y,'KernelFunction','rbf'); predictedValues = predict(model,X_test); ``` #### 设计决策规则 最后依据所得出的结果设计具体的耕作方案。这里可以通过求解整数规划问找到使总收益最大化的作物种类搭配方式及其相应的栽种面积分配比例。以下是运用遗传算法(Genetic Algorithm)解决此类离散型最优化难的一个简单实例: ```matlab options = optimoptions('ga', ... 'PopulationSize',50,... 'MaxGenerations',200); [x,fval] = ga(@objectiveFcn,nvars,[],[],[],[],lb,ub,[],options); disp(['Optimal solution found at point ',num2str(x)]); disp(['with objective function value of ', num2str(fval)]); function f = objectiveFcn(x) % 定义适应度计算逻辑... end ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布凯彻-劳斯基

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值