OptlangHelper 0.0.1__tar.gz → 0.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/OptlangHelper.egg-info/PKG-INFO +1 -1
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/OptlangHelper.egg-info/SOURCES.txt +3 -1
- OptlangHelper-0.0.2/OptlangHelper.egg-info/top_level.txt +1 -0
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/PKG-INFO +1 -1
- OptlangHelper-0.0.2/optlanghelper/__init__.py +15 -0
- OptlangHelper-0.0.2/optlanghelper/optlanghelper.py +134 -0
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/setup.py +2 -3
- OptlangHelper-0.0.1/OptlangHelper.egg-info/top_level.txt +0 -1
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/OptlangHelper.egg-info/dependency_links.txt +0 -0
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/OptlangHelper.egg-info/requires.txt +0 -0
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/README.rst +0 -0
- {OptlangHelper-0.0.1 → OptlangHelper-0.0.2}/setup.cfg +0 -0
|
@@ -4,4 +4,6 @@ OptlangHelper.egg-info/PKG-INFO
|
|
|
4
4
|
OptlangHelper.egg-info/SOURCES.txt
|
|
5
5
|
OptlangHelper.egg-info/dependency_links.txt
|
|
6
6
|
OptlangHelper.egg-info/requires.txt
|
|
7
|
-
OptlangHelper.egg-info/top_level.txt
|
|
7
|
+
OptlangHelper.egg-info/top_level.txt
|
|
8
|
+
optlanghelper/__init__.py
|
|
9
|
+
optlanghelper/optlanghelper.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
optlanghelper
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from __future__ import absolute_import
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
__author__ = "Andrew Freiburger"
|
|
8
|
+
__email__ = "afreiburger@anl.gov"
|
|
9
|
+
__version__ = "0.0.1"
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
print("OptlangHelper", __version__)
|
|
14
|
+
|
|
15
|
+
from optlanghelper import GLPKHelper, CPLEXHelper, GurobiHelper, Bounds, tupVariable, tupConstraint, tupObjective
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Thu Aug 18 10:26:32 2022
|
|
4
|
+
@author: Andrew Freiburger
|
|
5
|
+
"""
|
|
6
|
+
from collections import namedtuple
|
|
7
|
+
from optlang import Model
|
|
8
|
+
from typing import Iterable, Union
|
|
9
|
+
from pprint import pprint
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
Bounds = namedtuple("Bounds", ("lb", "ub"), defaults=(0,1000))
|
|
15
|
+
tupVariable = namedtuple("tupVariable", ("name", "bounds", "type"), defaults=("varName", Bounds(), "continuous"))
|
|
16
|
+
tupConstraint = namedtuple("tupConstraint", ("name", "bounds", "expr"), defaults=("consName", Bounds(0,0), None))
|
|
17
|
+
tupObjective = namedtuple("tupObjective", ("name", "expr", "direction"), defaults=("objectiveName", None, "max"))
|
|
18
|
+
|
|
19
|
+
def isIterable(term):
|
|
20
|
+
try:
|
|
21
|
+
iter(term)
|
|
22
|
+
if type(term) is not str: return True
|
|
23
|
+
return False
|
|
24
|
+
except: return False
|
|
25
|
+
|
|
26
|
+
def isnumber(obj):
|
|
27
|
+
try: float(obj) ; return True
|
|
28
|
+
except: return False
|
|
29
|
+
|
|
30
|
+
def define_term(value):
|
|
31
|
+
if isnumber(value):
|
|
32
|
+
return {"type":"Number", "value": value}
|
|
33
|
+
if isinstance(value, str):
|
|
34
|
+
return {"type":"Symbol", "name": value}
|
|
35
|
+
print(f"ERROR: The {value} of type {type(value)} is not known.")
|
|
36
|
+
|
|
37
|
+
def get_expression_template(expr):
|
|
38
|
+
# print(expr)
|
|
39
|
+
if isinstance(expr, list):
|
|
40
|
+
return {"type": "Add", "args": []}
|
|
41
|
+
return {"type": expr["operation"], "args": []}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GLPKHelper:
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def add_variables(var_name:str, var_bounds:(list, tuple), var_type:str="continuous"):
|
|
48
|
+
assert var_bounds[0] <= var_bounds[1], f"The {var_name} variable lower bound {var_bounds[0]} is greater than the upper bound {var_bounds[1]}. The lower bound must be less than the upper bound."
|
|
49
|
+
return {"name": var_name.replace(" ", "_"), "lb": var_bounds[0], "ub": var_bounds[1], "type": var_type}
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def add_constraint(cons_name:str, cons_bounds:(list, tuple), cons_expr:dict):
|
|
53
|
+
assert cons_bounds[0] <= cons_bounds[1], f"The {cons_name} constraint lower bound {cons_bounds[0]} is greater than the upper bound {cons_bounds[1]}. The lower bound must be less than the upper bound."
|
|
54
|
+
return {"name": cons_name.replace(" ", "_"),
|
|
55
|
+
"expression": OptlangHelper._define_expression(cons_expr),
|
|
56
|
+
"lb": cons_bounds[0], "ub": cons_bounds[1], "indicator_variable": None, "active_when": 1}
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def add_objective(obj_name:str, objective_expr:Union[dict, list], direction:str):
|
|
60
|
+
if isinstance(objective_expr, list):
|
|
61
|
+
obj_expr = {"type": "Add", "args": [
|
|
62
|
+
OptlangHelper._define_expression(expr) for expr in objective_expr]}
|
|
63
|
+
elif isinstance(objective_expr, dict):
|
|
64
|
+
obj_expr = {"type": objective_expr["operation"],
|
|
65
|
+
"args": [define_term(term) for term in objective_expr["elements"]]}
|
|
66
|
+
return {"name": obj_name.replace(" ", "_"), "expression": obj_expr, "direction": direction}
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def define_model(model_name, variables, constraints, objective, optlang=False):
|
|
70
|
+
model = {'name':model_name, 'variables':[], 'constraints':[]}
|
|
71
|
+
# pprint(objective)
|
|
72
|
+
for var in variables:
|
|
73
|
+
if len(var) == 2: var.append("continuous")
|
|
74
|
+
model["variables"].append(OptlangHelper.add_variables(var[0], var[1], var[2]))
|
|
75
|
+
for cons in constraints:
|
|
76
|
+
model["constraints"].append(OptlangHelper.add_constraint(cons[0], cons[1], cons[2]))
|
|
77
|
+
# if not isinstance(obj, str): # catches a strange error of the objective name as the objective itself
|
|
78
|
+
model["objective"] = OptlangHelper.add_objective(objective[0], objective[1], objective[2])
|
|
79
|
+
if optlang: return Model.from_json(model)
|
|
80
|
+
return model
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def _define_expression(expr:dict):
|
|
84
|
+
expression = get_expression_template(expr)
|
|
85
|
+
level1_coef = 0
|
|
86
|
+
for ele in expr["elements"]:
|
|
87
|
+
if not isnumber(ele) and not isinstance(ele, str):
|
|
88
|
+
# print(expr, ele, end="\r")
|
|
89
|
+
arguments = []
|
|
90
|
+
level2_coef = 0
|
|
91
|
+
for ele2 in ele["elements"]:
|
|
92
|
+
if not isnumber(ele2) and not isinstance(ele2, str):
|
|
93
|
+
# print("recursive ele\t\t", type(ele2), ele2)
|
|
94
|
+
arguments.append(OptlangHelper._define_expression(ele2))
|
|
95
|
+
elif isinstance(ele2, str): arguments.append(define_term(ele2))
|
|
96
|
+
else: level2_coef += float(ele2)
|
|
97
|
+
expression["args"].append(get_expression_template(ele))
|
|
98
|
+
if level2_coef != 0: arguments.append(define_term(level2_coef))
|
|
99
|
+
expression["args"][-1]["args"] = arguments
|
|
100
|
+
elif isinstance(ele, str): expression["args"].append(define_term(ele))
|
|
101
|
+
else: level1_coef += float(ele)
|
|
102
|
+
if level1_coef != 0: expression["args"].append(define_term(level1_coef))
|
|
103
|
+
# pprint(expression)
|
|
104
|
+
return expression
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def dot_product(zipped_to_sum, heuns_coefs=None):
|
|
108
|
+
# ensure that the lengths are compatible for heun's dot-products
|
|
109
|
+
if heuns_coefs is not None:
|
|
110
|
+
coefs = heuns_coefs if isinstance(heuns_coefs, (list, set)) else heuns_coefs.tolist()
|
|
111
|
+
zipped_length = len(zipped_to_sum); coefs_length = len(coefs)
|
|
112
|
+
if zipped_length != coefs_length:
|
|
113
|
+
raise IndexError(f"ERROR: The length of zipped elements {zipped_length}"
|
|
114
|
+
f" is unequal to that of coefficients {coefs_length}")
|
|
115
|
+
|
|
116
|
+
elements = []
|
|
117
|
+
for index, (term1, term2) in enumerate(zipped_to_sum):
|
|
118
|
+
if heuns_coefs is not None:
|
|
119
|
+
elements.extend([{"operation": "Mul", "elements": [heuns_coefs[index], term1]},
|
|
120
|
+
{"operation": "Mul", "elements": [heuns_coefs[index], term2]}])
|
|
121
|
+
else:
|
|
122
|
+
elements.append({"operation": "Mul", "elements": [term1, term2]})
|
|
123
|
+
return elements
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class CPLEXHelper:
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class GurobiHelper:
|
|
134
|
+
pass
|
|
@@ -7,14 +7,14 @@ with open("README.rst") as f:
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name="OptlangHelper",
|
|
10
|
-
version="0.0.
|
|
10
|
+
version="0.0.2",
|
|
11
11
|
description="Python package for building Linear Programming models that are compatible with Optlang",
|
|
12
12
|
long_description_content_type="text/x-rst",
|
|
13
13
|
long_description=readme,
|
|
14
14
|
author="Andrew Freiburger",
|
|
15
15
|
author_email="afreiburger@anl.gov",
|
|
16
16
|
url="https://github.com/Freiburgermsu/OptlangHelper",
|
|
17
|
-
packages=find_packages(
|
|
17
|
+
packages=find_packages(),
|
|
18
18
|
classifiers=[
|
|
19
19
|
"Development Status :: 3 - Alpha",
|
|
20
20
|
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
@@ -26,7 +26,6 @@ setup(
|
|
|
26
26
|
"Programming Language :: Python :: 3.11",
|
|
27
27
|
"Natural Language :: English",
|
|
28
28
|
],
|
|
29
|
-
include_package_data =True,
|
|
30
29
|
install_requires=[
|
|
31
30
|
"optlang",
|
|
32
31
|
# "glpk",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|