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",
- " landName | \n",
- " cropNum | \n",
- " cropName | \n",
- " cropType | \n",
- " plantArea | \n",
- " season | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " | 0 | \n",
- " A1 | \n",
- " 6 | \n",
- " 小麦 | \n",
- " 粮食 | \n",
- " 80.0 | \n",
- " 单季 | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " A2 | \n",
- " 7 | \n",
- " 玉米 | \n",
- " 粮食 | \n",
- " 55.0 | \n",
- " 单季 | \n",
- "
\n",
- " \n",
- " | 2 | \n",
- " A3 | \n",
- " 7 | \n",
- " 玉米 | \n",
- " 粮食 | \n",
- " 35.0 | \n",
- " 单季 | \n",
- "
\n",
- " \n",
- " | 3 | \n",
- " A4 | \n",
- " 1 | \n",
- " 黄豆 | \n",
- " 粮食(豆类) | \n",
- " 72.0 | \n",
- " 单季 | \n",
- "
\n",
- " \n",
- " | 4 | \n",
- " A5 | \n",
- " 4 | \n",
- " 绿豆 | \n",
- " 粮食(豆类) | \n",
- " 68.0 | \n",
- " 单季 | \n",
- "
\n",
- " \n",
- " | ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " | 82 | \n",
- " F3 | \n",
- " 28 | \n",
- " 小青菜 | \n",
- " 蔬菜 | \n",
- " 0.3 | \n",
- " 第二季 | \n",
- "
\n",
- " \n",
- " | 83 | \n",
- " F3 | \n",
- " 30 | \n",
- " 生菜 | \n",
- " 蔬菜 | \n",
- " 0.3 | \n",
- " 第二季 | \n",
- "
\n",
- " \n",
- " | 84 | \n",
- " F4 | \n",
- " 19 | \n",
- " 芸豆 | \n",
- " 蔬菜(豆类) | \n",
- " 0.6 | \n",
- " 第一季 | \n",
- "
\n",
- " \n",
- " | 85 | \n",
- " F4 | \n",
- " 34 | \n",
- " 芹菜 | \n",
- " 蔬菜 | \n",
- " 0.3 | \n",
- " 第二季 | \n",
- "
\n",
- " \n",
- " | 86 | \n",
- " F4 | \n",
- " 23 | \n",
- " 菠菜 | \n",
- " 蔬菜 | \n",
- " 0.3 | \n",
- " 第二季 | \n",
- "
\n",
- " \n",
- "
\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",
- " no | \n",
- " cropNum | \n",
- " cropName | \n",
- " cropLandType | \n",
- " season | \n",
- " unitYield | \n",
- " cost | \n",
- " price | \n",
- " unitProfit | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " | 0 | \n",
- " 1 | \n",
- " 1 | \n",
- " 黄豆 | \n",
- " 平旱地 | \n",
- " 单季 | \n",
- " 400 | \n",
- " 400 | \n",
- " 2.50-4.00 | \n",
- " 900.00 | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " 2 | \n",
- " 2 | \n",
- " 黑豆 | \n",
- " 平旱地 | \n",
- " 单季 | \n",
- " 500 | \n",
- " 400 | \n",
- " 6.50-8.50 | \n",
- " 3350.00 | \n",
- "
\n",
- " \n",
- " | 2 | \n",
- " 3 | \n",
- " 3 | \n",
- " 红豆 | \n",
- " 平旱地 | \n",
- " 单季 | \n",
- " 400 | \n",
- " 350 | \n",
- " 7.50-9.00 | \n",
- " 2950.00 | \n",
- "
\n",
- " \n",
- " | 3 | \n",
- " 4 | \n",
- " 4 | \n",
- " 绿豆 | \n",
- " 平旱地 | \n",
- " 单季 | \n",
- " 350 | \n",
- " 350 | \n",
- " 6.00-8.00 | \n",
- " 2100.00 | \n",
- "
\n",
- " \n",
- " | 4 | \n",
- " 5 | \n",
- " 5 | \n",
- " 爬豆 | \n",
- " 平旱地 | \n",
- " 单季 | \n",
- " 415 | \n",
- " 350 | \n",
- " 6.00-7.50 | \n",
- " 2451.25 | \n",
- "
\n",
- " \n",
- " | ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " | 120 | \n",
- " 103 | \n",
- " 30 | \n",
- " 生菜 | \n",
- " 智慧大棚 | \n",
- " 第二季 | \n",
- " 4500 | \n",
- " 2200 | \n",
- " 5.40-7.20 | \n",
- " 26150.00 | \n",
- "
\n",
- " \n",
- " | 121 | \n",
- " 104 | \n",
- " 31 | \n",
- " 辣椒 | \n",
- " 智慧大棚 | \n",
- " 第二季 | \n",
- " 1800 | \n",
- " 1300 | \n",
- " 7.20-10.20 | \n",
- " 14360.00 | \n",
- "
\n",
- " \n",
- " | 122 | \n",
- " 105 | \n",
- " 32 | \n",
- " 空心菜 | \n",
- " 智慧大棚 | \n",
- " 第二季 | \n",
- " 11000 | \n",
- " 5500 | \n",
- " 3.60-7.20 | \n",
- " 53900.00 | \n",
- "
\n",
- " \n",
- " | 123 | \n",
- " 106 | \n",
- " 33 | \n",
- " 黄心菜 | \n",
- " 智慧大棚 | \n",
- " 第二季 | \n",
- " 5400 | \n",
- " 2750 | \n",
- " 4.80-6.00 | \n",
- " 26410.00 | \n",
- "
\n",
- " \n",
- " | 124 | \n",
- " 107 | \n",
- " 34 | \n",
- " 芹菜 | \n",
- " 智慧大棚 | \n",
- " 第二季 | \n",
- " 6000 | \n",
- " 1200 | \n",
- " 3.80-5.80 | \n",
- " 27600.00 | \n",
- "
\n",
- " \n",
- "
\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,