feat: 初始化Easy Patch插件及依赖文件

- 添加Blender插件核心文件:__init__.py、ui.py、property.py、preference.py
- 添加插件工具模块:g.py、loop.py、generate_loop.py、const.py、op.py
- 添加翻译工具:utils/trans.py
- 添加PuLP线性规划库及其依赖文件,包括CBC求解器二进制文件
- 添加.gitignore和VSCode配置文件
This commit is contained in:
2026-03-03 19:24:57 +08:00
commit ab91b120e6
44 changed files with 17551 additions and 0 deletions

165
utils/pulp/apis/__init__.py Normal file
View File

@@ -0,0 +1,165 @@
from .coin_api import *
from .cplex_api import *
from .gurobi_api import *
from .glpk_api import *
from .choco_api import *
from .mipcl_api import *
from .mosek_api import *
from .scip_api import *
from .xpress_api import *
from .highs_api import *
from .copt_api import *
from .core import *
_all_solvers = [
GLPK_CMD,
PYGLPK,
CPLEX_CMD,
CPLEX_PY,
GUROBI,
GUROBI_CMD,
MOSEK,
XPRESS,
XPRESS_CMD,
XPRESS_PY,
PULP_CBC_CMD,
COIN_CMD,
COINMP_DLL,
CHOCO_CMD,
MIPCL_CMD,
SCIP_CMD,
FSCIP_CMD,
SCIP_PY,
HiGHS,
HiGHS_CMD,
COPT,
COPT_DLL,
COPT_CMD,
]
import json
# Default solver selection
if PULP_CBC_CMD().available():
LpSolverDefault = PULP_CBC_CMD()
elif GLPK_CMD().available():
LpSolverDefault = GLPK_CMD()
elif COIN_CMD().available():
LpSolverDefault = COIN_CMD()
else:
LpSolverDefault = None
def setConfigInformation(**keywords):
"""
set the data in the configuration file
at the moment will only edit things in [locations]
the keyword value pairs come from the keywords dictionary
"""
# TODO: extend if we ever add another section in the config file
# read the old configuration
config = Parser()
config.read(config_filename)
# set the new keys
for key, val in keywords.items():
config.set("locations", key, val)
# write the new configuration
fp = open(config_filename, "w")
config.write(fp)
fp.close()
def configSolvers():
"""
Configure the path the the solvers on the command line
Designed to configure the file locations of the solvers from the
command line after installation
"""
configlist = [
(cplex_dll_path, "cplexpath", "CPLEX: "),
(coinMP_path, "coinmppath", "CoinMP dll (windows only): "),
]
print(
"Please type the full path including filename and extension \n"
+ "for each solver available"
)
configdict = {}
for default, key, msg in configlist:
value = input(msg + "[" + str(default) + "]")
if value:
configdict[key] = value
setConfigInformation(**configdict)
def getSolver(solver, *args, **kwargs):
"""
Instantiates a solver from its name
:param str solver: solver name to create
:param args: additional arguments to the solver
:param kwargs: additional keyword arguments to the solver
:return: solver of type :py:class:`LpSolver`
"""
mapping = {k.name: k for k in _all_solvers}
try:
return mapping[solver](*args, **kwargs)
except KeyError:
raise PulpSolverError(
"The solver {} does not exist in PuLP.\nPossible options are: \n{}".format(
solver, mapping.keys()
)
)
def getSolverFromDict(data):
"""
Instantiates a solver from a dictionary with its data
:param dict data: a dictionary with, at least an "solver" key with the name
of the solver to create
:return: a solver of type :py:class:`LpSolver`
:raises PulpSolverError: if the dictionary does not have the "solver" key
:rtype: LpSolver
"""
solver = data.pop("solver", None)
if solver is None:
raise PulpSolverError("The json file has no solver attribute.")
return getSolver(solver, **data)
def getSolverFromJson(filename):
"""
Instantiates a solver from a json file with its data
:param str filename: name of the json file to read
:return: a solver of type :py:class:`LpSolver`
:rtype: LpSolver
"""
with open(filename) as f:
data = json.load(f)
return getSolverFromDict(data)
def listSolvers(onlyAvailable=False):
"""
List the names of all the existing solvers in PuLP
:param bool onlyAvailable: if True, only show the available solvers
:return: list of solver names
:rtype: list
"""
result = []
for s in _all_solvers:
solver = s()
if (not onlyAvailable) or solver.available():
result.append(solver.name)
del solver
return result
# DEPRECATED aliases:
get_solver = getSolver
get_solver_from_json = getSolverFromJson
get_solver_from_dict = getSolverFromDict
list_solvers = listSolvers