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:
232
utils/pulp/utilities.py
Normal file
232
utils/pulp/utilities.py
Normal file
@@ -0,0 +1,232 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user