Files
blender-easy-patch/utils/pulp/utilities.py
小煜 ab91b120e6 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配置文件
2026-03-03 19:24:57 +08:00

233 lines
6.0 KiB
Python

# Utility functions
import itertools
import collections
def resource_clock():
import resource
return resource.getrusage(resource.RUSAGE_CHILDREN).ru_utime
def isNumber(x):
"""Returns true if x is an int or a float"""
return isinstance(x, (int, float))
def value(x):
"""Returns the value of the variable/expression x, or x if it is a number"""
if isNumber(x):
return x
else:
return x.value()
def valueOrDefault(x):
"""Returns the value of the variable/expression x, or x if it is a number
Variable without value (None) are affected a possible value (within their
bounds)."""
if isNumber(x):
return x
else:
return x.valueOrDefault()
def __combination(orgset, k):
"""
fall back if probstat is not installed note it is GPL so cannot
be included
"""
if k == 1:
for i in orgset:
yield (i,)
elif k > 1:
for i, x in enumerate(orgset):
# iterates though to near the end
for s in __combination(orgset[i + 1 :], k - 1):
yield (x,) + s
try: # python >= 3.4
from itertools import combinations as combination
except ImportError:
try: # python 2.7
from itertools import combination
except ImportError: # pulp's
combination = __combination
def __permutation(orgset, k):
"""
fall back if probstat is not installed note it is GPL so cannot
be included
"""
if k == 1:
for i in orgset:
yield (i,)
elif k > 1:
for i, x in enumerate(orgset):
# iterates though to near the end
for s in __permutation(orgset[:i] + orgset[i + 1 :], k - 1):
yield (x,) + s
try: # python >= 3.4
from itertools import permutations as permutation
except ImportError:
try: # python 2.7
from itertools import permutation
except ImportError: # pulp's
permutation = __permutation
def allpermutations(orgset, k):
"""
returns all permutations of orgset with up to k items
:param orgset: the list to be iterated
:param k: the maxcardinality of the subsets
:return: an iterator of the subsets
example:
>>> c = allpermutations([1,2,3,4],2)
>>> for s in c:
... print(s)
(1,)
(2,)
(3,)
(4,)
(1, 2)
(1, 3)
(1, 4)
(2, 1)
(2, 3)
(2, 4)
(3, 1)
(3, 2)
(3, 4)
(4, 1)
(4, 2)
(4, 3)
"""
return itertools.chain(*[permutation(orgset, i) for i in range(1, k + 1)])
def allcombinations(orgset, k):
"""
returns all combinations of orgset with up to k items
:param orgset: the list to be iterated
:param k: the maxcardinality of the subsets
:return: an iterator of the subsets
example:
>>> c = allcombinations([1,2,3,4],2)
>>> for s in c:
... print(s)
(1,)
(2,)
(3,)
(4,)
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
"""
return itertools.chain(*[combination(orgset, i) for i in range(1, k + 1)])
def makeDict(headers, array, default=None):
"""
makes a list into a dictionary with the headings given in headings
headers is a list of header lists
array is a list with the data
"""
result, defdict = __makeDict(headers, array, default)
return result
def __makeDict(headers, array, default=None):
# this is a recursive function so end the recursion as follows
result = {}
returndefaultvalue = None
if len(headers) == 1:
result.update(dict(zip(headers[0], array)))
defaultvalue = default
else:
for i, h in enumerate(headers[0]):
result[h], defaultvalue = __makeDict(headers[1:], array[i], default)
if default is not None:
f = lambda: defaultvalue
defresult = collections.defaultdict(f)
defresult.update(result)
result = defresult
returndefaultvalue = collections.defaultdict(f)
return result, returndefaultvalue
def splitDict(data):
"""
Split a dictionary with lists as the data, into smaller dictionaries
:param data: A dictionary with lists as the values
:return: A tuple of dictionaries each containing the data separately,
with the same dictionary keys
"""
# find the maximum number of items in the dictionary
maxitems = max([len(values) for values in data.values()])
output = [dict() for _ in range(maxitems)]
for key, values in data.items():
for i, val in enumerate(values):
output[i][key] = val
return tuple(output)
def read_table(data, coerce_type, transpose=False):
"""
Reads in data from a simple table and forces it to be a particular type
This is a helper function that allows data to be easily constained in a
simple script
::return: a dictionary of with the keys being a tuple of the strings
in the first row and colum of the table
::param data: the multiline string containing the table data
::param coerce_type: the type that the table data is converted to
::param transpose: reverses the data if needed
Example:
>>> table_data = '''
... L1 L2 L3 L4 L5 L6
... C1 6736 42658 70414 45170 184679 111569
... C2 217266 227190 249640 203029 153531 117487
... C3 35936 28768 126316 2498 130317 74034
... C4 73446 52077 108368 75011 49827 62850
... C5 174664 177461 151589 153300 59916 135162
... C6 186302 189099 147026 164938 149836 286307
... '''
>>> table = read_table(table_data, int)
>>> table[("C1","L1")]
6736
>>> table[("C6","L5")]
149836
"""
lines = data.splitlines()
headings = lines[1].split()
result = {}
for row in lines[2:]:
items = row.split()
for i, item in enumerate(items[1:]):
if transpose:
key = (headings[i], items[0])
else:
key = (items[0], headings[i])
result[key] = coerce_type(item)
return result