diff --git a/problem1.ipynb b/problem1.ipynb index dcfe3fa..ad5f8eb 100644 --- a/problem1.ipynb +++ b/problem1.ipynb @@ -1,235 +1,76 @@ { "cells": [ { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:53.146868Z", - "start_time": "2024-09-07T07:39:52.630439Z" - } - }, "cell_type": "code", - "source": "import pandas as pd", + "execution_count": 1, "id": "e19ec4ae5347c678", + "metadata": {}, "outputs": [], - "execution_count": 1 + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "pd.options.display.max_columns = 100" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:53.919487Z", - "start_time": "2024-09-07T07:39:53.146868Z" - } - }, "cell_type": "code", + "execution_count": 2, + "id": "initial_id", + "metadata": {}, + "outputs": [], "source": [ "\n", "df_crop_details = pd.read_excel('./data/2.xlsx', sheet_name=1)" - ], - "id": "initial_id", - "outputs": [], - "execution_count": 2 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:53.935294Z", - "start_time": "2024-09-07T07:39:53.919487Z" - } - }, "cell_type": "code", + "execution_count": 3, + "id": "1d2a51b3414be94", + "metadata": {}, + "outputs": [], "source": [ "# 去除空格\n", "df_crop_details['cropName'] = df_crop_details['cropName'].apply(lambda x: x.strip())\n", "# CropType = [x.strip() for x in CropType]\n" - ], - "id": "1d2a51b3414be94", - "outputs": [], - "execution_count": 3 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:53.998096Z", - "start_time": "2024-09-07T07:39:53.936656Z" - } - }, "cell_type": "code", + "execution_count": 4, + "id": "514cd9136d9ca341", + "metadata": {}, + "outputs": [], "source": [ "df_crop_planting = pd.read_excel('./data/2.xlsx', sheet_name=0)\n", "# 照例去除一下空格\n", "df_crop_planting['cropName'] = df_crop_planting['cropName'].apply(lambda x: x.strip())\n", "# ffill\n", "df_crop_planting['landName'] = df_crop_planting['landName'].ffill()\n", - "df_crop_planting" - ], - "id": "514cd9136d9ca341", - "outputs": [ - { - "data": { - "text/plain": [ - " landName cropNum cropName cropType plantArea season\n", - "0 A1 6 小麦 粮食 80.0 单季\n", - "1 A2 7 玉米 粮食 55.0 单季\n", - "2 A3 7 玉米 粮食 35.0 单季\n", - "3 A4 1 黄豆 粮食(豆类) 72.0 单季\n", - "4 A5 4 绿豆 粮食(豆类) 68.0 单季\n", - ".. ... ... ... ... ... ...\n", - "82 F3 28 小青菜 蔬菜 0.3 第二季\n", - "83 F3 30 生菜 蔬菜 0.3 第二季\n", - "84 F4 19 芸豆 蔬菜(豆类) 0.6 第一季\n", - "85 F4 34 芹菜 蔬菜 0.3 第二季\n", - "86 F4 23 菠菜 蔬菜 0.3 第二季\n", - "\n", - "[87 rows x 6 columns]" - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
landNamecropNumcropNamecropTypeplantAreaseason
0A16小麦粮食80.0单季
1A27玉米粮食55.0单季
2A37玉米粮食35.0单季
3A41黄豆粮食(豆类)72.0单季
4A54绿豆粮食(豆类)68.0单季
.....................
82F328小青菜蔬菜0.3第二季
83F330生菜蔬菜0.3第二季
84F419芸豆蔬菜(豆类)0.6第一季
85F434芹菜蔬菜0.3第二季
86F423菠菜蔬菜0.3第二季
\n", - "

87 rows × 6 columns

\n", - "
" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 + "# df_crop_planting" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.013672Z", - "start_time": "2024-09-07T07:39:53.998096Z" - } - }, "cell_type": "code", + "execution_count": 5, + "id": "1503f8b642c842db", + "metadata": {}, + "outputs": [], + "source": [ + "df_land = pd.read_excel('./data/1.xlsx', sheet_name=0)\n", + "# 去除landType和landName的空格\n", + "df_land['landType'] = df_land['landType'].apply(lambda x: x.strip())\n", + "df_land['landName'] = df_land['landName'].apply(lambda x: x.strip())\n", + "# df_land" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3cdf51a9a9d4d30f", + "metadata": {}, + "outputs": [], "source": [ "\n", "unit_profit_lsc = []\n", @@ -237,323 +78,138 @@ " s = str(line[7]).split('-')\n", " unit_profit_lsc.append((float(s[0]) + float(s[1])) / 2 * line[5] - line[6])\n", "df_crop_details['unitProfit'] = unit_profit_lsc\n", - "df_crop_details" - ], - "id": "3cdf51a9a9d4d30f", - "outputs": [ - { - "data": { - "text/plain": [ - " no cropNum cropName cropLandType season unitYield cost price \\\n", - "0 1 1 黄豆 平旱地 单季 400 400 2.50-4.00 \n", - "1 2 2 黑豆 平旱地 单季 500 400 6.50-8.50 \n", - "2 3 3 红豆 平旱地 单季 400 350 7.50-9.00 \n", - "3 4 4 绿豆 平旱地 单季 350 350 6.00-8.00 \n", - "4 5 5 爬豆 平旱地 单季 415 350 6.00-7.50 \n", - ".. ... ... ... ... ... ... ... ... \n", - "120 103 30 生菜 智慧大棚 第二季 4500 2200 5.40-7.20 \n", - "121 104 31 辣椒 智慧大棚 第二季 1800 1300 7.20-10.20 \n", - "122 105 32 空心菜 智慧大棚 第二季 11000 5500 3.60-7.20 \n", - "123 106 33 黄心菜 智慧大棚 第二季 5400 2750 4.80-6.00 \n", - "124 107 34 芹菜 智慧大棚 第二季 6000 1200 3.80-5.80 \n", - "\n", - " unitProfit \n", - "0 900.00 \n", - "1 3350.00 \n", - "2 2950.00 \n", - "3 2100.00 \n", - "4 2451.25 \n", - ".. ... \n", - "120 26150.00 \n", - "121 14360.00 \n", - "122 53900.00 \n", - "123 26410.00 \n", - "124 27600.00 \n", - "\n", - "[125 rows x 9 columns]" - ], - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nocropNumcropNamecropLandTypeseasonunitYieldcostpriceunitProfit
011黄豆平旱地单季4004002.50-4.00900.00
122黑豆平旱地单季5004006.50-8.503350.00
233红豆平旱地单季4003507.50-9.002950.00
344绿豆平旱地单季3503506.00-8.002100.00
455爬豆平旱地单季4153506.00-7.502451.25
..............................
12010330生菜智慧大棚第二季450022005.40-7.2026150.00
12110431辣椒智慧大棚第二季180013007.20-10.2014360.00
12210532空心菜智慧大棚第二季1100055003.60-7.2053900.00
12310633黄心菜智慧大棚第二季540027504.80-6.0026410.00
12410734芹菜智慧大棚第二季600012003.80-5.8027600.00
\n", - "

125 rows × 9 columns

\n", - "
" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 5 + "# df_crop_details" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.029719Z", - "start_time": "2024-09-07T07:39:54.013672Z" - } - }, "cell_type": "code", + "execution_count": 7, + "id": "569016a9b90f841b", + "metadata": {}, + "outputs": [], + "source": [ + "df_crop_type_land = pd.read_excel('./data/1.xlsx', sheet_name=1)\n", + "# 老规矩,去掉cropName和cropType的空格\n", + "df_crop_type_land['cropType'] = df_crop_type_land['cropType'].apply(lambda x: x.strip())\n", + "df_crop_type_land['cropName'] = df_crop_type_land['cropName'].apply(lambda x: x.strip())\n", + "# df_crop_type_land" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "a7661d84217b578c", + "metadata": {}, + "outputs": [], "source": [ "# 搞一下季节和年份的集合\n", "SeasonType = [\"单季\", \"第一季\", \"第二季\"]\n", "SeasonDict = {\"单季\": 1, \"第一季\": 1, \"第二季\": 2}\n", "SeasonNum = [1, 2]\n", "years = [2024, 2025, 2026, 2027, 2028, 2029, 2030]" - ], - "id": "a7661d84217b578c", - "outputs": [], - "execution_count": 6 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.045394Z", - "start_time": "2024-09-07T07:39:54.029719Z" - } - }, "cell_type": "code", + "execution_count": 9, + "id": "4a4e06a1f2d4d8ab", + "metadata": {}, + "outputs": [], "source": [ "# 枚举地块类型\n", "LandType = {\"A\": \"平旱地\", \"B\": \"梯田\", \"C\": \"山坡地\", \"D\": \"水浇地\", \"E\": \"普通大棚\", \"F\": \"智慧大棚\"}\n", "# LandType" - ], - "id": "4a4e06a1f2d4d8ab", - "outputs": [], - "execution_count": 7 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.061240Z", - "start_time": "2024-09-07T07:39:54.045394Z" - } - }, "cell_type": "code", + "execution_count": 10, + "id": "cc938565a63a8129", + "metadata": {}, + "outputs": [], "source": [ "# 枚举地块\n", "LandName = df_crop_planting['landName'].unique()\n", "# LandName" - ], - "id": "cc938565a63a8129", - "outputs": [], - "execution_count": 8 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.076622Z", - "start_time": "2024-09-07T07:39:54.062582Z" - } - }, "cell_type": "code", + "execution_count": 11, + "id": "dae53a6215cea525", + "metadata": {}, + "outputs": [], + "source": [ + "# 枚举地块面积,取df_land的landName为key,landArea为value\n", + "LandArea = {x: df_land[df_land['landName'] == x]['landArea'].values[0] for x in LandName}\n", + "# LandArea" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7a0e6cc209d93b56", + "metadata": {}, + "outputs": [], "source": [ "# 读入作物名称\n", "CropName = df_crop_details['cropName'].unique()\n", "# CropName" - ], - "id": "7a0e6cc209d93b56", - "outputs": [], - "execution_count": 9 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.092071Z", - "start_time": "2024-09-07T07:39:54.081006Z" - } - }, "cell_type": "code", - "source": [ - "any([x[-1] == ' ' for x in CropName])\n", - "# 居然有空格\n", - "# 现在去掉了" - ], - "id": "bf6d61d66f06bdeb", + "execution_count": 13, + "id": "8a280f918bb3139a", + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "False" + "{'粮食(豆类)': array(['黄豆', '黑豆', '红豆', '绿豆', '爬豆'], dtype=object),\n", + " '粮食': array(['小麦', '玉米', '谷子', '高粱', '黍子', '荞麦', '南瓜', '红薯', '莜麦', '大麦', '水稻'],\n", + " dtype=object),\n", + " '蔬菜(豆类)': array(['豇豆', '刀豆', '芸豆'], dtype=object),\n", + " '蔬菜': array(['土豆', '西红柿', '茄子', '菠菜', '青椒', '菜花', '包菜', '油麦菜', '小青菜', '黄瓜',\n", + " '生菜', '辣椒', '空心菜', '黄心菜', '芹菜', '大白菜', '白萝卜', '红萝卜'], dtype=object),\n", + " '食用菌': array(['榆黄菇', '香菇', '白灵菇', '羊肚菌'], dtype=object),\n", + " '粮食(除了水稻)': array(['小麦', '玉米', '谷子', '高粱', '黍子', '荞麦', '南瓜', '红薯', '莜麦', '大麦'],\n", + " dtype=object),\n", + " '豆类': array(['黄豆', '黑豆', '红豆', '绿豆', '爬豆', '豇豆', '刀豆', '芸豆'], dtype=object)}" ] }, - "execution_count": 10, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 10 + "source": [ + "# 作物分类\n", + "CropType = {x: df_crop_type_land[df_crop_type_land['cropType'] == x]['cropName'].values for x in\n", + " df_crop_type_land['cropType'].values}\n", + "CropType['粮食(除了水稻)'] = CropType['粮食'][:-1] # 这样不太好,但能用\n", + "CropType['豆类'] = np.array(list(CropType['粮食(豆类)']) + list(CropType['蔬菜(豆类)']), dtype=object)\n", + "CropType" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.491091Z", - "start_time": "2024-09-07T07:39:54.093999Z" - } - }, "cell_type": "code", + "execution_count": 14, + "id": "bf6d61d66f06bdeb", + "metadata": {}, + "outputs": [], + "source": [ + "# any([x[-1] == ' ' for x in CropName])\n", + "# 居然有空格\n", + "# 现在去掉了" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "22f9730e3d9c1016", + "metadata": {}, + "outputs": [], "source": [ "# 亩产量\n", "unit_yield_lsc = {\n", @@ -575,19 +231,14 @@ "}\n", "\n", "# unit_yield" - ], - "id": "22f9730e3d9c1016", - "outputs": [], - "execution_count": 11 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:54.993663Z", - "start_time": "2024-09-07T07:39:54.493875Z" - } - }, "cell_type": "code", + "execution_count": 16, + "id": "99dbe4ca6c54db0b", + "metadata": {}, + "outputs": [], "source": [ "# 亩利润\n", "unit_profit_lsc = {\n", @@ -610,19 +261,14 @@ "}\n", "\n", "# unit_profit" - ], - "id": "99dbe4ca6c54db0b", - "outputs": [], - "execution_count": 12 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.009266Z", - "start_time": "2024-09-07T07:39:54.993663Z" - } - }, "cell_type": "code", + "execution_count": 17, + "id": "13f2ccc7aa215d4c", + "metadata": {}, + "outputs": [], "source": [ "# 每种作物的总需求\n", "crop_demand = {\n", @@ -638,64 +284,47 @@ " crop_demand[line[2]] += line[4] * unit_yield_lsc[LandType[line[0][0]]][line[5]][line[2]]\n", "\n", "# crop_demand" - ], - "id": "13f2ccc7aa215d4c", - "outputs": [], - "execution_count": 13 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.056963Z", - "start_time": "2024-09-07T07:39:55.009266Z" - } - }, "cell_type": "code", + "execution_count": 18, + "id": "5d09872708d40da4", + "metadata": {}, + "outputs": [], "source": [ "# 准备开搞\n", - "from pulp import LpMaximize, LpProblem, LpVariable, lpSum, value, LpInteger, PULP_CBC_CMD, LpContinuous, LpBinary\n" - ], - "id": "5d09872708d40da4", - "outputs": [], - "execution_count": 14 + "from pulp import LpMaximize, LpProblem, LpVariable, lpSum, value, LpInteger, PULP_CBC_CMD, LpContinuous, LpBinary\n", + "import pulp" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.072925Z", - "start_time": "2024-09-07T07:39:55.058097Z" - } - }, "cell_type": "code", - "source": "model = LpProblem(\"Crop_Planting_Optimization_with_Specific_Rules\", LpMaximize)", + "execution_count": 19, "id": "b6eff87c7a762769", + "metadata": {}, "outputs": [], - "execution_count": 15 + "source": [ + "model = LpProblem(\"Crop_Planting_Optimization_with_Specific_Rules\", LpMaximize)" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.088872Z", - "start_time": "2024-09-07T07:39:55.075153Z" - } - }, "cell_type": "code", + "execution_count": 20, + "id": "7bfdb9425c3e9683", + "metadata": {}, + "outputs": [], "source": [ "# %timeit X = LpVariable.dicts(\"X\", (CropName, LandName, years, seasons), lowBound=0, cat=LpContinuous)\n", "# %timeit XX = LpVariable.dicts(\"X\", [(c, l, y, s) for c in CropName for l in LandName for y in years for s in seasons],lowBound=0, cat=LpContinuous)" - ], - "id": "7bfdb9425c3e9683", - "outputs": [], - "execution_count": 16 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.393238Z", - "start_time": "2024-09-07T07:39:55.091269Z" - } - }, "cell_type": "code", + "execution_count": 21, + "id": "4cb129e20385a7ee", + "metadata": {}, + "outputs": [], "source": [ "# 地块l在y年的s季的种植c的量\n", "# X = LpVariable.dicts(\"crop_plant_area\", (CropName, LandName, years, SeasonType), lowBound=0, cat=LpContinuous)\n", @@ -708,19 +337,14 @@ " cat=LpContinuous\n", " )\n", "# X" - ], - "id": "4cb129e20385a7ee", - "outputs": [], - "execution_count": 17 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:55.696316Z", - "start_time": "2024-09-07T07:39:55.393238Z" - } - }, "cell_type": "code", + "execution_count": 22, + "id": "9dab983ca7b3b607", + "metadata": {}, + "outputs": [], "source": [ "# 地块l在y年的s季是否种植了c\n", "# Y = LpVariable.dicts(\"crop_plant_bool\", (CropName, LandName, years, SeasonType), cat=LpBinary)\n", @@ -728,19 +352,14 @@ " cat=LpBinary)\n", "\n", "# Y" - ], - "id": "9dab983ca7b3b607", - "outputs": [], - "execution_count": 18 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:57.605199Z", - "start_time": "2024-09-07T07:39:55.697108Z" - } - }, "cell_type": "code", + "execution_count": 23, + "id": "603175d36624172f", + "metadata": {}, + "outputs": [], "source": [ "# 确保与X进行01约束\n", "for c in CropName:\n", @@ -751,68 +370,331 @@ " model += X[c, l, y, s] <= 10000000 * Y[c, l, y, s], f\"PlantingConstraint1_{c}_{l}_{y}_{s}\"\n", " # 如果未种植作物,则种植面积为0\n", " model += X[c, l, y, s] >= 0.000001 * Y[c, l, y, s], f\"PlantingConstraint2_{c}_{l}_{y}_{s}\"" - ], - "id": "603175d36624172f", - "outputs": [], - "execution_count": 19 + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:40:30.545252Z", - "start_time": "2024-09-07T07:40:30.317563Z" - } - }, "cell_type": "code", + "execution_count": 24, + "id": "4505b0f2fe6bf93d", + "metadata": {}, + "outputs": [], "source": [ "# 目标函数:总利润 = sum(x[i]*profit[c,l,s])\n", - "model += lpSum(\n", - " X[c,l,y,s] * unit_profit_lsc[LandType[l[0]]][s][c]\n", + "model += lpSum( # 地块类型 季节 作物类型\n", + " X[c, l, y, s] * unit_profit_lsc[LandType[l[0]]][s][c]\n", " for c in CropName\n", " for l in LandName\n", " for y in years\n", " for s in SeasonType\n", - ")\n" - ], - "id": "4505b0f2fe6bf93d", - "outputs": [], - "execution_count": 21 + "), \"total_profit\"\n" + ] }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-07T07:39:58.955478Z", - "start_time": "2024-09-07T07:39:58.955478Z" - } - }, "cell_type": "code", - "source": [ - "# 每个季节每种作物的种植量必须小于需求量\n", - "for c in CropName:\n", - " " - ], + "execution_count": 25, "id": "1f185c0856fbcf27", + "metadata": {}, "outputs": [], - "execution_count": null + "source": [ + "# 约束,启动!\n", + "# 条件1:每年的所有季节中每种作物的种植量必须小于需求量\n", + "for c in CropName:\n", + " for y in years:\n", + " model += lpSum(X[c, l, y, s] * unit_yield_lsc[LandType[l[0]]][s][c] for l in LandName for s in SeasonType) <= \\\n", + " crop_demand[c], f\"CropDemandConstraint_{c}_{y}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "7e13de7700d38f19", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件2: 每年每季每块地的种植面积不能超过该地块的总面积\n", + "for l in LandName:\n", + " for y in years:\n", + " for s in SeasonType:\n", + " model += lpSum(X[c, l, y, s] for c in CropName) <= LandArea[l], f\"LandAreaConstraint_{l}_{y}_{s}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "1f6ac4323825f28b", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件3: 平旱地、梯田和山坡地每年适宜单季种植[粮食类作物(水稻除外)]。因为除了[粮食类作物(水稻除外)]以外的作物似乎已经被上面的产量和利润的0给约束了,所以大概不需要做限制了吧\n", + "for l in LandName:\n", + " if l[0] not in [\"A\", \"B\", \"C\"]: # [\"平旱地\", \"梯田\", \"山坡地\"]\n", + " continue\n", + " for s in SeasonType:\n", + " if s != \"单季\":\n", + " model += lpSum(Y[c, l, y, s] for c in CropName for y in years) == 0, f\"SingleSeasonConstraint_{l}_{s}\"\n", + " # model += lpSum(X[c, l, y, s] for c in CropName for y in years) == 0" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "c0e9b6b37092f0e7", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件4: 水浇地每年可以单季种植水稻或两季种植蔬菜作物。\n", + "for l in LandName:\n", + " if l[0] != \"D\": # [\"水浇地\"]\n", + " continue\n", + " for y in years:\n", + " model += (\n", + " (lpSum(Y[\"水稻\", l, y, \"单季\"]) != 0) and\n", + " (lpSum(\n", + " Y[c, l, y, s] if c != \"水稻\" else 0\n", + " for c in CropName\n", + " for s in [\"第一季\", \"第二季\"]\n", + " ) == 0)\n", + " ) or (\n", + " (lpSum(Y[\"水稻\", l, y, \"单季\"]) == 0) and\n", + " (lpSum(\n", + " Y[c, l, y, s] if c != \"水稻\" else 0\n", + " for c in CropName\n", + " for s in [\"第一季\", \"第二季\"]\n", + " ) != 0)\n", + " ), f\"irrigatedConstraint_{l}_{y}\"\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "8f8da502641f32fa", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件5: 若在某块水浇地种植两季蔬菜,第一季可种植多种蔬菜(大白菜、白萝卜和红萝卜除外);第二季只能种植大白菜、白萝卜和红萝卜中的一种(便于管理)。\n", + "# 感觉没必要,因为前面有field和profit为0的惩罚\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "df2d7e8918382a0", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件6: 根据季节性要求,大白菜、白萝卜和红萝卜只能在水浇地的第二季种植。\n", + "# 感觉也没必要,同理\n" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "1d402d3df13f6732", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件7: 普通大棚每年种植两季作物,第一季可种植多种蔬菜(大白菜、白萝卜和红萝卜除外),第二季只能种植食用菌。\n", + "# 同理\n" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "930ab378623172ec", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件8: 食用菌类只能在普通大棚第二季的时候种植\n", + "# 同理\n" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "bda8b4c538a097bc", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件9: 智慧大棚每年都可种植两季蔬菜(大白菜、白萝卜和红萝卜除外)\n", + "# 同理" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "e8fb2dea1326a05b", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件10: 别种得太碎了,啥意思? 每种作物不超过3块地吧。\n", + "for c in CropName:\n", + " for y in years:\n", + " for s in SeasonType:\n", + " model += lpSum(Y[c, l, y, s] for l in LandName) <= 3, f\"MaxCropTypeConstraint_{c}_{y}_{s}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "49f1490823c6af3c", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件11: 最小种植面积:0.2吧\n", + "for l in LandName:\n", + " for y in years:\n", + " for s in SeasonType:\n", + " for c in CropName:\n", + " model += X[c, l, y, s] >= 0.2 * (1 if Y[c, l, y, s] else 0), f\"MinCropAreaConstraint_{c}_{l}_{y}_{s}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "bdf1048b83723f91", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件12 : 最重要的,不能重复种植同一块地同一年同一季的同一作物\n", + "# 每种作物在同一地块(含大棚)都不能连续重茬种植\n", + "\n", + "for l in LandName:\n", + " for c in CropName:\n", + " for y in years: # 单季不能连年种植 同一年不能连续种植 跨年也不能连续种植\n", + " if y < years[-1]:\n", + " model += Y[c, l, y, \"单季\"] + Y[c, l, y + 1, \"单季\"] <= 1, f\"SingleSeasonConstraint1_{c}_{l}_{y}\"\n", + " model += Y[c, l, y, \"第一季\"] + Y[c, l, y + 1, \"第二季\"] <= 1, f\"DoubleSeasonConstraint1_{c}_{l}_{y}\"\n", + " model += Y[c, l, y, \"第一季\"] + Y[c, l, y, \"第二季\"] <= 1, f\"DoubleSeasonConstraint2_{c}_{l}_{y}\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "50da0aff9c68ae24", + "metadata": {}, + "outputs": [], + "source": [ + "# 条件13: 最重要的,从 2023 年开始要求每个地块(含大棚) 的所有土地三年内至少种植一次豆类作物\n", + "# CropType['豆类']\n", + "for l in LandName:\n", + " for y in years[:-2]:\n", + " model += lpSum(Y[c,l,y_r,s] for c in CropType['豆类'] for y_r in range(y,y+2) for s in SeasonType)>=1, f\"BeanConstraint_{l}_{y}\"\n", + " # model += lpSum(Y[c, l, y_r, \"单季\"] for c in CropType['豆类'] for y_r in\n", + " # range(y - 2, y + 1)) >= 1, f\"BeanConstraint1_{l}_{y}\"\n", + " # model += lpSum(Y[c, l, y_r, s] for c in CropType['豆类'] for y_r in range(y - 2, y + 1) for s in\n", + " # [\"第一季\", \"第二季\"]) >= 1, f\"BeanConstraint2_{l}_{y}\"" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "d4792a1210afca3b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# model.solve()\n", + "\n", + "# 创建求解器实例\n", + "solver = pulp.PULP_CBC_CMD(\n", + " timeLimit=120,\n", + " threads=4,\n", + ")\n", + "solver.solve(model)\n", + "\n", + "\n", + "# print(Y)\n", + "# for c in CropName:\n", + "# for l in LandName:\n", + "# for y in years:\n", + "# for s in SeasonType:\n", + "# print(f\"Y[({c}, {l}, {y}, {s})] = {pulp.value(Y[(c, l, y, s)])}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "cb3f4e95111e3292", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "结果已保存到文件:planting_plan_2024-2030.xlsx\n" + ] + } + ], + "source": [ + "\n", + "# 输出文件名,包含起始年份和结束年份\n", + "output_filename = f\"planting_plan_{years[0]}-{years[-1]}.xlsx\"\n", + "\n", + "# 使用 pd.ExcelWriter 创建 Excel 文件\n", + "with pd.ExcelWriter(output_filename) as writer:\n", + " # 遍历每一年和每个季节\n", + " for y in years:\n", + " for s in SeasonType:\n", + " # 创建一个空的 DataFrame,横轴为作物名称,纵轴为地块名称\n", + " result_table = pd.DataFrame(columns=CropName, index=LandName)\n", + "\n", + " # 填充表格数据\n", + " for l in LandName:\n", + " for c in CropName:\n", + " # 获取变量 X[c, l, y, s] 的值\n", + " crop_value = value(X[c, l, y, s])\n", + " if crop_value is not None and crop_value > 0:\n", + " result_table.at[l, c] = crop_value # 填入结果\n", + "\n", + " # 用 0 填充空值\n", + " result_table.fillna(0, inplace=True)\n", + "\n", + " # 定义每个 sheet 的名称为 年份_季节\n", + " sheet_name = f\"{y}_Season_{s}\"\n", + "\n", + " # 将每个 result_table 写入到 Excel 的不同 sheet 中\n", + " result_table.to_excel(writer, sheet_name=sheet_name)\n", + "\n", + "print(f\"结果已保存到文件:{output_filename}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93b4b3b64fd941aa", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" + "pygments_lexer": "ipython3", + "version": "3.9.17" } }, "nbformat": 4,