基础版

This commit is contained in:
2025-09-23 00:53:10 +08:00
parent 304f522dc5
commit d2870ee3e5
3 changed files with 219 additions and 19 deletions

154
.gitignore vendored
View File

@@ -1,27 +1,143 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Dependency directories (remove the comment below to include it)
# vendor/
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Go workspace file
go.work
go.work.sum
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# env file
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# IDE
.idea/
.vscode/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
logs/
*.log
# Project specific
config/local_*.yaml

View File

@@ -0,0 +1,36 @@
import optimize_feed
# 示例调用
if __name__ == "__main__":
# 原料数据(加工后,单位:%或MJ/kg价格元/吨)
ingredients = {
'构树叶': {'蛋白': 15, '能量': 9, '纤维': 10, '赖氨酸': 0.5, '蛋氨酸': 0.1, '': 1.5, '': 0.2, '价格': 600},
'玉米胚芽': {'蛋白': 11, '能量': 13, '纤维': 7, '赖氨酸': 0.4, '蛋氨酸': 0.2, '': 0.1, '': 0.3,
'价格': 1700},
'麦麸': {'蛋白': 15, '能量': 10, '纤维': 12, '赖氨酸': 0.4, '蛋氨酸': 0.2, '': 0.1, '': 1.0, '价格': 1300},
'米糠': {'蛋白': 13, '能量': 11, '纤维': 10, '赖氨酸': 0.4, '蛋氨酸': 0.2, '': 0.1, '': 1.5, '价格': 1100},
'牧草': {'蛋白': 17, '能量': 8.5, '纤维': 20, '赖氨酸': 0.6, '蛋氨酸': 0.2, '': 1.2, '': 0.3, '价格': 800},
'玉米': {'蛋白': 9, '能量': 13.5, '纤维': 2.5, '赖氨酸': 0.3, '蛋氨酸': 0.17, '': 0.02, '': 0.3,
'价格': 2367},
'豆粕': {'蛋白': 46, '能量': 10.5, '纤维': 4, '赖氨酸': 2.8, '蛋氨酸': 0.6, '': 0.3, '': 0.7, '价格': 3300},
'植物油': {'蛋白': 0, '能量': 36, '纤维': 0, '赖氨酸': 0, '蛋氨酸': 0, '': 0, '': 0, '价格': 7500},
'赖氨酸': {'蛋白': 78, '能量': 0, '纤维': 0, '赖氨酸': 78, '蛋氨酸': 0, '': 0, '': 0, '价格': 15000},
'蛋氨酸': {'蛋白': 99, '能量': 0, '纤维': 0, '赖氨酸': 0, '蛋氨酸': 99, '': 0, '': 0, '价格': 25000},
'预混料': {'蛋白': 0, '能量': 0, '纤维': 0, '赖氨酸': 0, '蛋氨酸': 0, '': 10, '': 5, '价格': 3000}
}
requirements = {
'蛋白_下限': 17,
'能量_下限': 13,
'纤维_上限': 5,
'赖氨酸_下限': 0.75,
'蛋氨酸_下限': 0.25,
'钙_下限': 0.5,
'磷_下限': 0.4
}
# 运行优化
result = optimize_feed.optimize_feed(requirements, ingredients, ['比例', '成本'], 'min')
print("优化结果:")
for key, value in result.items():
print(f"{key}: {value}")

48
optimize_feed.py Normal file
View File

@@ -0,0 +1,48 @@
import pulp
def optimize_feed(requirements, ingredients, result_fields, optimization_type='min'):
"""
优化饲料配方,计算最低/最高目标值的原料比例
:param requirements: 猪营养需求字典,如 {'蛋白_下限': 16, '能量_下限': 12, '纤维_上限': 8}
:param ingredients: 原料数据字典,如 {'构树叶': {'蛋白': 18, '能量': 10, '纤维': 5, '价格': 500}}
:param result_fields: 结果字段列表,如 ['比例', '成本']
:param optimization_type: 'min'(最小化,如成本)或 'max'(最大化,如消化率)
:return: 字典,含结果字段和值,如 {'构树叶': {'比例': 0.2, '成本': 100}, '总成本': 1475}
"""
# 创建模型
sense = pulp.LpMinimize if optimization_type == 'min' else pulp.LpMaximize
model = pulp.LpProblem("Feed_Optimization", sense)
# 决策变量原料比例0-1
x = pulp.LpVariable.dicts("比例", ingredients, lowBound=0, upBound=1)
# 目标函数:优化指定字段(如价格)
target_field = next(f for f in ingredients[list(ingredients.keys())[0]] if '价格' in f or '成本' in f) # 默认优化价格
model += pulp.lpSum([x[i] * ingredients[i][target_field] for i in ingredients]), "目标"
# 约束1总比例=100%
model += pulp.lpSum([x[i] for i in ingredients]) == 1, "总比例"
# 约束2营养需求下限/上限)
for req, value in requirements.items():
if '下限' in req:
nutrient = req.replace('_下限', '')
model += pulp.lpSum([x[i] * ingredients[i][nutrient] for i in ingredients]) >= value, req
elif '上限' in req:
nutrient = req.replace('_上限', '')
model += pulp.lpSum([x[i] * ingredients[i][nutrient] for i in ingredients]) <= value, req
# 求解
model.solve()
# 构建结果
if pulp.LpStatus[model.status] != 'Optimal':
return {"错误": "无解!检查原料数据或需求(比如纤维全超上限?)"}
result = {}
total_target = pulp.value(model.objective)
result['' + target_field] = round(total_target, 2)
for i in ingredients:
result[i] = {field: round(pulp.value(x[i]) * 100, 2) if field == '比例' else round(
pulp.value(x[i]) * ingredients[i][target_field], 2) for field in result_fields}
return result