from scipy.optimize import linprog
import numpy as np
raw_materials = [
    {"name": "46%小颗粒尿素", "nitrogen": 0.46, "phosphorus": 0.0, "potassium": 0.0, "price": 2200},
    {"name": "46%大颗粒尿素", "nitrogen": 0.46, "phosphorus": 0.0, "potassium": 0.0, "price": 2300},
    {"name": "20.5%粉体硫酸铵", "nitrogen": 0.205, "phosphorus": 0.0, "potassium": 0.0, "price": 1200},
    {"name": "20.5%晶体硫酸铵", "nitrogen": 0.205, "phosphorus": 0.0, "potassium": 0.0, "price": 1200},
    {"name": "17.1%碳酸氢铵", "nitrogen": 0.171, "phosphorus": 0.0, "potassium": 0.0, "price": 1300},
    {"name": "55%10-45-0磷酸一铵", "nitrogen": 0.1, "phosphorus": 0.45, "potassium": 0.0, "price": 3200},
    {"name": "55%11-40-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.44, "potassium": 0.0, "price": 2936},
    {"name": "58%11-47-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.47, "potassium": 0.0, "price": 3119},
    {"name": "60%11-49-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.49, "potassium": 0.0, "price": 3257},
    {"name": "64%11-53-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.53, "potassium": 0.0, "price": 3600},
    {"name": "66%11-55-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.55, "potassium": 0.0, "price": 4700},
    {"name": "66%11.5-54.5-0磷酸一铵", "nitrogen": 0.115, "phosphorus": 0.545, "potassium": 0.0, "price": 4312},
    {"name": "68%10-58-0磷酸一铵", "nitrogen": 0.1, "phosphorus": 0.58, "potassium": 0.0, "price": 4404},
    {"name": "68%11-57-0磷酸一铵", "nitrogen": 0.11, "phosphorus": 0.57, "potassium": 0.0, "price": 4404},
    {"name": "72%12-60-0磷酸一铵", "nitrogen": 0.12, "phosphorus": 0.6, "potassium": 0.0, "price": 5596},
    {"name": "62进口氯化钾", "nitrogen": 0.0, "phosphorus": 0.0, "potassium": 0.62, "price": 2410},
    {"name": "52%曼海姆硫酸钾", "nitrogen": 0.0, "phosphorus": 0.0, "potassium": 0.52, "price": 3180},
    {"name": "52%罗布泊硫酸钾", "nitrogen": 0.0, "phosphorus": 0.0, "potassium": 0.52, "price": 2880},
    {"name": "60%氯化钾", "nitrogen": 0.0, "phosphorus": 0.0, "potassium": 0.6, "price": 2350}
]


from pulp import LpProblem, LpVariable, LpMinimize, lpSum, value

def calculate_minimum_cost(raw_materials, target_total_content, target_element_content, fluctuation):
    # 创建线性规划问题
    problem = LpProblem("Minimum Cost", LpMinimize)

    # 创建变量
    amounts = [LpVariable(material["name"], lowBound=0, cat="Continuous") for material in raw_materials]

    # 定义目标函数(最小化成本)
    problem += lpSum(material["price"] * amount for material, amount in zip(raw_materials, amounts))

    # 定义约束条件(目标含量)
    for element in ["nitrogen", "phosphorus", "potassium"]:
        problem += lpSum(material[element] * amount for material, amount in zip(raw_materials, amounts)) >= \
                   (target_element_content[element] - fluctuation)

        problem += lpSum(material[element] * amount for material, amount in zip(raw_materials, amounts)) <= \
                   (target_element_content[element] + fluctuation)

    # 约束条件(总和为目标总含量)
    problem += lpSum(material["nitrogen"] * amount for material, amount in zip(raw_materials, amounts)) + \
               lpSum(material["phosphorus"] * amount for material, amount in zip(raw_materials, amounts)) + \
               lpSum(material["potassium"] * amount for material, amount in zip(raw_materials, amounts)) == \
               target_total_content

    # 求解线性规划问题
    problem.solve()

    # 输出结果
    if problem.status == 1:  # 若求解成功
        optimal_amounts = [value(amount) for amount in amounts]

        # 构建最终使用的原料和用量
        used_materials = []
        for material, amount in zip(raw_materials, optimal_amounts):
            if amount > 0:
                used_materials.append({"name": material["name"], "amount": amount})

        # 计算实际的氮磷钾含量
        actual_nitrogen = sum(material["nitrogen"] * amount for material, amount in zip(raw_materials, optimal_amounts))
        actual_phosphorus = sum(material["phosphorus"] * amount for material, amount in zip(raw_materials, optimal_amounts))
        actual_potassium = sum(material["potassium"] * amount for material, amount in zip(raw_materials, optimal_amounts))

        # 计算最终成本
        total_cost = value(problem.objective)

        # 返回结果
        return used_materials, actual_nitrogen, actual_phosphorus, actual_potassium, total_cost
    else:
        return None, None, None, None, None


# 目标总含量和目标单元素含量
target_total_content = 0.45
target_element_content = {"nitrogen": 0.15, "phosphorus": 0.15, "potassium": 0.15}

# 波动范围
fluctuation = 0.005

# 计算最低成本
used_materials, actual_nitrogen, actual_phosphorus, actual_potassium, total_cost = calculate_minimum_cost(raw_materials, target_total_content, target_element_content, fluctuation)

if used_materials is not None:
    # 输出最终使用的原料和用量
    print("最终使用的原料和用量:")
    for material in used_materials:
        print(material["name"], ": ", material["amount"])

    # 输出最终的氮磷钾含量
    print("最终的氮磷钾含量:")
    print("氮含量: ", actual_nitrogen)
    print("磷含量: ", actual_phosphorus)
    print("钾含量: ", actual_potassium)

    # 输出最终的成本
    print("最终的成本: ", total_cost)
else:
    print("无法找到满足要求的解决方案。")

0 Comments latest

No comments.