PySCIPOpt 5.3.0__tar.gz → 5.4.1__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.
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/PKG-INFO +15 -4
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/PySCIPOpt.egg-info/PKG-INFO +15 -4
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/PySCIPOpt.egg-info/SOURCES.txt +4 -0
- pyscipopt-5.4.1/PySCIPOpt.egg-info/requires.txt +1 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/README.md +13 -3
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/pyproject.toml +1 -1
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/setup.cfg +0 -3
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/setup.py +2 -2
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/__init__.py +5 -0
- pyscipopt-5.4.1/src/pyscipopt/_version.py +1 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/expr.pxi +59 -9
- pyscipopt-5.4.1/src/pyscipopt/matrix.pxi +139 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/scip.c +123219 -91453
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/scip.pxd +4 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/scip.pxi +750 -17
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_heur.py +1 -1
- pyscipopt-5.4.1/tests/test_matrix_variable.py +322 -0
- pyscipopt-5.4.1/tests/test_node.py +21 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_nogil.py +1 -1
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_nonlinear.py +11 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_solution.py +3 -3
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_strong_branching.py +3 -3
- pyscipopt-5.3.0/src/pyscipopt/_version.py +0 -1
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/LICENSE +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/PySCIPOpt.egg-info/dependency_links.txt +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/PySCIPOpt.egg-info/top_level.txt +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/Multidict.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/benders.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/benderscut.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/branchrule.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/conshdlr.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/cutsel.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/event.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/heuristic.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/lp.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/nodesel.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/presol.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/pricer.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/propagator.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/reader.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/recipes/__init__.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/recipes/infeasibilities.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/recipes/nonlinear.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/recipes/piecewise.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/recipes/primal_dual_evolution.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/relax.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/scip.pyx +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/src/pyscipopt/sepa.pxi +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_alldiff.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_benders.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_bipartite.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_branch_mostinfeas.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_branch_probing_lp.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_cons.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_conshdlr.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_copy.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_customizedbenders.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_cutsel.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_event.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_expr.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_gomory.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_knapsack.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_linexpr.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_logical.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_lp.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_memory.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_model.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_nlrow.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_nodesel.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_pricer.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_quadcons.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_quickprod.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_quicksum.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_reader.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_recipe_infeasibilities.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_recipe_nonlinear.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_recipe_piecewise.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_recipe_primal_dual_evolution.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_relax.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_reopt.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_short.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_sub_sol.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_tree.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_tsp.py +0 -0
- {pyscipopt-5.3.0 → pyscipopt-5.4.1}/tests/test_vars.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PySCIPOpt
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.4.1
|
|
4
4
|
Summary: Python interface and modeling environment for SCIP
|
|
5
5
|
Home-page: https://github.com/SCIP-Interfaces/PySCIPOpt
|
|
6
6
|
Author: Zuse Institute Berlin
|
|
@@ -17,6 +17,7 @@ Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
|
17
17
|
Requires-Python: >=3.8
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy>=1.16.0
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: home-page
|
|
22
23
|
|
|
@@ -66,20 +67,20 @@ following steps are always required when using the interface:
|
|
|
66
67
|
1) It is necessary to import python-scip in your code. This is achieved
|
|
67
68
|
by including the line
|
|
68
69
|
|
|
69
|
-
```
|
|
70
|
+
```python
|
|
70
71
|
from pyscipopt import Model
|
|
71
72
|
```
|
|
72
73
|
|
|
73
74
|
2) Create a solver instance.
|
|
74
75
|
|
|
75
|
-
```
|
|
76
|
+
```python
|
|
76
77
|
model = Model("Example") # model name is optional
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
3) Access the methods in the `scip.pxi` file using the solver/model
|
|
80
81
|
instance `model`, e.g.:
|
|
81
82
|
|
|
82
|
-
```
|
|
83
|
+
```python
|
|
83
84
|
x = model.addVar("x")
|
|
84
85
|
y = model.addVar("y", vtype="INTEGER")
|
|
85
86
|
model.setObjective(x + y)
|
|
@@ -104,6 +105,16 @@ examples.
|
|
|
104
105
|
Please notice that in most cases one needs to use a `dictionary` to
|
|
105
106
|
specify the return values needed by SCIP.
|
|
106
107
|
|
|
108
|
+
Using PySCIPOpt?
|
|
109
|
+
----------------
|
|
110
|
+
|
|
111
|
+
If your project or company is using PySCIPOpt, consider letting us know at scip@zib.de. We are always interested
|
|
112
|
+
in knowing how PySCIPOpt is being used, and, given permission, would also appreciate adding your company's logo
|
|
113
|
+
to our website.
|
|
114
|
+
|
|
115
|
+
If you are creating models with some degree of complexity which don't take too long to solve, also consider
|
|
116
|
+
sharing them with us. We might want to add them to [`tests/helpers/utils.py`](tests/helpers/utils.py) to help make our tests more robust, or add them to our examples.
|
|
117
|
+
|
|
107
118
|
Citing PySCIPOpt
|
|
108
119
|
----------------
|
|
109
120
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: PySCIPOpt
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.4.1
|
|
4
4
|
Summary: Python interface and modeling environment for SCIP
|
|
5
5
|
Home-page: https://github.com/SCIP-Interfaces/PySCIPOpt
|
|
6
6
|
Author: Zuse Institute Berlin
|
|
@@ -17,6 +17,7 @@ Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
|
17
17
|
Requires-Python: >=3.8
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy>=1.16.0
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: home-page
|
|
22
23
|
|
|
@@ -66,20 +67,20 @@ following steps are always required when using the interface:
|
|
|
66
67
|
1) It is necessary to import python-scip in your code. This is achieved
|
|
67
68
|
by including the line
|
|
68
69
|
|
|
69
|
-
```
|
|
70
|
+
```python
|
|
70
71
|
from pyscipopt import Model
|
|
71
72
|
```
|
|
72
73
|
|
|
73
74
|
2) Create a solver instance.
|
|
74
75
|
|
|
75
|
-
```
|
|
76
|
+
```python
|
|
76
77
|
model = Model("Example") # model name is optional
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
3) Access the methods in the `scip.pxi` file using the solver/model
|
|
80
81
|
instance `model`, e.g.:
|
|
81
82
|
|
|
82
|
-
```
|
|
83
|
+
```python
|
|
83
84
|
x = model.addVar("x")
|
|
84
85
|
y = model.addVar("y", vtype="INTEGER")
|
|
85
86
|
model.setObjective(x + y)
|
|
@@ -104,6 +105,16 @@ examples.
|
|
|
104
105
|
Please notice that in most cases one needs to use a `dictionary` to
|
|
105
106
|
specify the return values needed by SCIP.
|
|
106
107
|
|
|
108
|
+
Using PySCIPOpt?
|
|
109
|
+
----------------
|
|
110
|
+
|
|
111
|
+
If your project or company is using PySCIPOpt, consider letting us know at scip@zib.de. We are always interested
|
|
112
|
+
in knowing how PySCIPOpt is being used, and, given permission, would also appreciate adding your company's logo
|
|
113
|
+
to our website.
|
|
114
|
+
|
|
115
|
+
If you are creating models with some degree of complexity which don't take too long to solve, also consider
|
|
116
|
+
sharing them with us. We might want to add them to [`tests/helpers/utils.py`](tests/helpers/utils.py) to help make our tests more robust, or add them to our examples.
|
|
117
|
+
|
|
107
118
|
Citing PySCIPOpt
|
|
108
119
|
----------------
|
|
109
120
|
|
|
@@ -6,6 +6,7 @@ setup.py
|
|
|
6
6
|
PySCIPOpt.egg-info/PKG-INFO
|
|
7
7
|
PySCIPOpt.egg-info/SOURCES.txt
|
|
8
8
|
PySCIPOpt.egg-info/dependency_links.txt
|
|
9
|
+
PySCIPOpt.egg-info/requires.txt
|
|
9
10
|
PySCIPOpt.egg-info/top_level.txt
|
|
10
11
|
src/pyscipopt/Multidict.py
|
|
11
12
|
src/pyscipopt/__init__.py
|
|
@@ -19,6 +20,7 @@ src/pyscipopt/event.pxi
|
|
|
19
20
|
src/pyscipopt/expr.pxi
|
|
20
21
|
src/pyscipopt/heuristic.pxi
|
|
21
22
|
src/pyscipopt/lp.pxi
|
|
23
|
+
src/pyscipopt/matrix.pxi
|
|
22
24
|
src/pyscipopt/nodesel.pxi
|
|
23
25
|
src/pyscipopt/presol.pxi
|
|
24
26
|
src/pyscipopt/pricer.pxi
|
|
@@ -53,9 +55,11 @@ tests/test_knapsack.py
|
|
|
53
55
|
tests/test_linexpr.py
|
|
54
56
|
tests/test_logical.py
|
|
55
57
|
tests/test_lp.py
|
|
58
|
+
tests/test_matrix_variable.py
|
|
56
59
|
tests/test_memory.py
|
|
57
60
|
tests/test_model.py
|
|
58
61
|
tests/test_nlrow.py
|
|
62
|
+
tests/test_node.py
|
|
59
63
|
tests/test_nodesel.py
|
|
60
64
|
tests/test_nogil.py
|
|
61
65
|
tests/test_nonlinear.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numpy>=1.16.0
|
|
@@ -44,20 +44,20 @@ following steps are always required when using the interface:
|
|
|
44
44
|
1) It is necessary to import python-scip in your code. This is achieved
|
|
45
45
|
by including the line
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
```python
|
|
48
48
|
from pyscipopt import Model
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
2) Create a solver instance.
|
|
52
52
|
|
|
53
|
-
```
|
|
53
|
+
```python
|
|
54
54
|
model = Model("Example") # model name is optional
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
3) Access the methods in the `scip.pxi` file using the solver/model
|
|
58
58
|
instance `model`, e.g.:
|
|
59
59
|
|
|
60
|
-
```
|
|
60
|
+
```python
|
|
61
61
|
x = model.addVar("x")
|
|
62
62
|
y = model.addVar("y", vtype="INTEGER")
|
|
63
63
|
model.setObjective(x + y)
|
|
@@ -82,6 +82,16 @@ examples.
|
|
|
82
82
|
Please notice that in most cases one needs to use a `dictionary` to
|
|
83
83
|
specify the return values needed by SCIP.
|
|
84
84
|
|
|
85
|
+
Using PySCIPOpt?
|
|
86
|
+
----------------
|
|
87
|
+
|
|
88
|
+
If your project or company is using PySCIPOpt, consider letting us know at scip@zib.de. We are always interested
|
|
89
|
+
in knowing how PySCIPOpt is being used, and, given permission, would also appreciate adding your company's logo
|
|
90
|
+
to our website.
|
|
91
|
+
|
|
92
|
+
If you are creating models with some degree of complexity which don't take too long to solve, also consider
|
|
93
|
+
sharing them with us. We might want to add them to [`tests/helpers/utils.py`](tests/helpers/utils.py) to help make our tests more robust, or add them to our examples.
|
|
94
|
+
|
|
85
95
|
Citing PySCIPOpt
|
|
86
96
|
----------------
|
|
87
97
|
|
|
@@ -8,7 +8,7 @@ description = "Python interface and modeling environment for SCIP"
|
|
|
8
8
|
authors = [
|
|
9
9
|
{name = "Zuse Institute Berlin", email = "scip@zib.de"},
|
|
10
10
|
]
|
|
11
|
-
dependencies = []
|
|
11
|
+
dependencies = ['numpy >=1.16.0']
|
|
12
12
|
requires-python = ">=3.8"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
license = {text = "MIT"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from setuptools import find_packages, setup, Extension
|
|
2
|
-
import os, platform, sys
|
|
2
|
+
import os, platform, sys
|
|
3
3
|
|
|
4
4
|
# look for environment variable that specifies path to SCIP
|
|
5
5
|
scipoptdir = os.environ.get("SCIPOPTDIR", "").strip('"')
|
|
@@ -109,7 +109,7 @@ with open("README.md") as f:
|
|
|
109
109
|
|
|
110
110
|
setup(
|
|
111
111
|
name="PySCIPOpt",
|
|
112
|
-
version="5.
|
|
112
|
+
version="5.4.1",
|
|
113
113
|
description="Python interface and modeling environment for SCIP",
|
|
114
114
|
long_description=long_description,
|
|
115
115
|
long_description_content_type="text/markdown",
|
|
@@ -10,7 +10,9 @@ if hasattr(os, 'add_dll_directory'):
|
|
|
10
10
|
from pyscipopt.Multidict import multidict
|
|
11
11
|
from pyscipopt.scip import Model
|
|
12
12
|
from pyscipopt.scip import Variable
|
|
13
|
+
from pyscipopt.scip import MatrixVariable
|
|
13
14
|
from pyscipopt.scip import Constraint
|
|
15
|
+
from pyscipopt.scip import MatrixConstraint
|
|
14
16
|
from pyscipopt.scip import Benders
|
|
15
17
|
from pyscipopt.scip import Benderscut
|
|
16
18
|
from pyscipopt.scip import Branchrule
|
|
@@ -26,6 +28,9 @@ from pyscipopt.scip import Sepa
|
|
|
26
28
|
from pyscipopt.scip import LP
|
|
27
29
|
from pyscipopt.scip import readStatistics
|
|
28
30
|
from pyscipopt.scip import Expr
|
|
31
|
+
from pyscipopt.scip import MatrixExpr
|
|
32
|
+
from pyscipopt.scip import MatrixExprCons
|
|
33
|
+
from pyscipopt.scip import ExprCons
|
|
29
34
|
from pyscipopt.scip import quicksum
|
|
30
35
|
from pyscipopt.scip import quickprod
|
|
31
36
|
from pyscipopt.scip import exp
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '5.4.1'
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
# which should, in princple, modify the expr. However, since we do not implement __isub__, __sub__
|
|
43
43
|
# gets called (I guess) and so a copy is returned.
|
|
44
44
|
# Modifying the expression directly would be a bug, given that the expression might be re-used by the user. </pre>
|
|
45
|
-
|
|
45
|
+
include "matrix.pxi"
|
|
46
46
|
|
|
47
47
|
def _is_number(e):
|
|
48
48
|
try:
|
|
@@ -52,14 +52,15 @@ def _is_number(e):
|
|
|
52
52
|
return False
|
|
53
53
|
except TypeError: # for other types (Variable, Expr)
|
|
54
54
|
return False
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
|
|
57
56
|
def _expr_richcmp(self, other, op):
|
|
58
57
|
if op == 1: # <=
|
|
59
58
|
if isinstance(other, Expr) or isinstance(other, GenExpr):
|
|
60
59
|
return (self - other) <= 0.0
|
|
61
60
|
elif _is_number(other):
|
|
62
61
|
return ExprCons(self, rhs=float(other))
|
|
62
|
+
elif isinstance(other, MatrixExpr):
|
|
63
|
+
return _expr_richcmp(other, self, 5)
|
|
63
64
|
else:
|
|
64
65
|
raise NotImplementedError
|
|
65
66
|
elif op == 5: # >=
|
|
@@ -67,6 +68,8 @@ def _expr_richcmp(self, other, op):
|
|
|
67
68
|
return (self - other) >= 0.0
|
|
68
69
|
elif _is_number(other):
|
|
69
70
|
return ExprCons(self, lhs=float(other))
|
|
71
|
+
elif isinstance(other, MatrixExpr):
|
|
72
|
+
return _expr_richcmp(other, self, 1)
|
|
70
73
|
else:
|
|
71
74
|
raise NotImplementedError
|
|
72
75
|
elif op == 2: # ==
|
|
@@ -74,6 +77,8 @@ def _expr_richcmp(self, other, op):
|
|
|
74
77
|
return (self - other) == 0.0
|
|
75
78
|
elif _is_number(other):
|
|
76
79
|
return ExprCons(self, lhs=float(other), rhs=float(other))
|
|
80
|
+
elif isinstance(other, MatrixExpr):
|
|
81
|
+
return _expr_richcmp(other, self, 2)
|
|
77
82
|
else:
|
|
78
83
|
raise NotImplementedError
|
|
79
84
|
else:
|
|
@@ -117,6 +122,7 @@ def buildGenExprObj(expr):
|
|
|
117
122
|
"""helper function to generate an object of type GenExpr"""
|
|
118
123
|
if _is_number(expr):
|
|
119
124
|
return Constant(expr)
|
|
125
|
+
|
|
120
126
|
elif isinstance(expr, Expr):
|
|
121
127
|
# loop over terms and create a sumexpr with the sum of each term
|
|
122
128
|
# each term is either a variable (which gets transformed into varexpr)
|
|
@@ -135,6 +141,13 @@ def buildGenExprObj(expr):
|
|
|
135
141
|
prodexpr *= varexpr
|
|
136
142
|
sumexpr += coef * prodexpr
|
|
137
143
|
return sumexpr
|
|
144
|
+
|
|
145
|
+
elif isinstance(expr, MatrixExpr):
|
|
146
|
+
GenExprs = np.empty(expr.shape, dtype=object)
|
|
147
|
+
for idx in np.ndindex(expr.shape):
|
|
148
|
+
GenExprs[idx] = buildGenExprObj(expr[idx])
|
|
149
|
+
return GenExprs
|
|
150
|
+
|
|
138
151
|
else:
|
|
139
152
|
assert isinstance(expr, GenExpr)
|
|
140
153
|
return expr
|
|
@@ -185,8 +198,11 @@ cdef class Expr:
|
|
|
185
198
|
terms[CONST] = terms.get(CONST, 0.0) + c
|
|
186
199
|
elif isinstance(right, GenExpr):
|
|
187
200
|
return buildGenExprObj(left) + right
|
|
201
|
+
elif isinstance(right, MatrixExpr):
|
|
202
|
+
return right + left
|
|
188
203
|
else:
|
|
189
204
|
raise NotImplementedError
|
|
205
|
+
|
|
190
206
|
return Expr(terms)
|
|
191
207
|
|
|
192
208
|
def __iadd__(self, other):
|
|
@@ -203,6 +219,7 @@ cdef class Expr:
|
|
|
203
219
|
return buildGenExprObj(self) + other
|
|
204
220
|
else:
|
|
205
221
|
raise NotImplementedError
|
|
222
|
+
|
|
206
223
|
return self
|
|
207
224
|
|
|
208
225
|
def __mul__(self, other):
|
|
@@ -319,7 +336,6 @@ cdef class ExprCons:
|
|
|
319
336
|
if op == 1: # <=
|
|
320
337
|
if not self._rhs is None:
|
|
321
338
|
raise TypeError('ExprCons already has upper bound')
|
|
322
|
-
assert self._rhs is None
|
|
323
339
|
assert not self._lhs is None
|
|
324
340
|
|
|
325
341
|
if not _is_number(other):
|
|
@@ -622,19 +638,53 @@ cdef class Constant(GenExpr):
|
|
|
622
638
|
|
|
623
639
|
def exp(expr):
|
|
624
640
|
"""returns expression with exp-function"""
|
|
625
|
-
|
|
641
|
+
if isinstance(expr, MatrixExpr):
|
|
642
|
+
unary_exprs = np.empty(shape=expr.shape, dtype=object)
|
|
643
|
+
for idx in np.ndindex(expr.shape):
|
|
644
|
+
unary_exprs[idx] = UnaryExpr(Operator.exp, buildGenExprObj(expr[idx]))
|
|
645
|
+
return unary_exprs.view(MatrixGenExpr)
|
|
646
|
+
else:
|
|
647
|
+
return UnaryExpr(Operator.exp, buildGenExprObj(expr))
|
|
648
|
+
|
|
626
649
|
def log(expr):
|
|
627
650
|
"""returns expression with log-function"""
|
|
628
|
-
|
|
651
|
+
if isinstance(expr, MatrixExpr):
|
|
652
|
+
unary_exprs = np.empty(shape=expr.shape, dtype=object)
|
|
653
|
+
for idx in np.ndindex(expr.shape):
|
|
654
|
+
unary_exprs[idx] = UnaryExpr(Operator.log, buildGenExprObj(expr[idx]))
|
|
655
|
+
return unary_exprs.view(MatrixGenExpr)
|
|
656
|
+
else:
|
|
657
|
+
return UnaryExpr(Operator.log, buildGenExprObj(expr))
|
|
658
|
+
|
|
629
659
|
def sqrt(expr):
|
|
630
660
|
"""returns expression with sqrt-function"""
|
|
631
|
-
|
|
661
|
+
if isinstance(expr, MatrixExpr):
|
|
662
|
+
unary_exprs = np.empty(shape=expr.shape, dtype=object)
|
|
663
|
+
for idx in np.ndindex(expr.shape):
|
|
664
|
+
unary_exprs[idx] = UnaryExpr(Operator.sqrt, buildGenExprObj(expr[idx]))
|
|
665
|
+
return unary_exprs.view(MatrixGenExpr)
|
|
666
|
+
else:
|
|
667
|
+
return UnaryExpr(Operator.sqrt, buildGenExprObj(expr))
|
|
668
|
+
|
|
632
669
|
def sin(expr):
|
|
633
670
|
"""returns expression with sin-function"""
|
|
634
|
-
|
|
671
|
+
if isinstance(expr, MatrixExpr):
|
|
672
|
+
unary_exprs = np.empty(shape=expr.shape, dtype=object)
|
|
673
|
+
for idx in np.ndindex(expr.shape):
|
|
674
|
+
unary_exprs[idx] = UnaryExpr(Operator.sin, buildGenExprObj(expr[idx]))
|
|
675
|
+
return unary_exprs.view(MatrixGenExpr)
|
|
676
|
+
else:
|
|
677
|
+
return UnaryExpr(Operator.sin, buildGenExprObj(expr))
|
|
678
|
+
|
|
635
679
|
def cos(expr):
|
|
636
680
|
"""returns expression with cos-function"""
|
|
637
|
-
|
|
681
|
+
if isinstance(expr, MatrixExpr):
|
|
682
|
+
unary_exprs = np.empty(shape=expr.shape, dtype=object)
|
|
683
|
+
for idx in np.ndindex(expr.shape):
|
|
684
|
+
unary_exprs[idx] = UnaryExpr(Operator.cos, buildGenExprObj(expr[idx]))
|
|
685
|
+
return unary_exprs.view(MatrixGenExpr)
|
|
686
|
+
else:
|
|
687
|
+
return UnaryExpr(Operator.cos, buildGenExprObj(expr))
|
|
638
688
|
|
|
639
689
|
def expr_to_nodes(expr):
|
|
640
690
|
'''transforms tree to an array of nodes. each node is an operator and the position of the
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# TODO Cythonize things. Improve performance.
|
|
3
|
+
# TODO Add tests
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from typing import Union
|
|
8
|
+
|
|
9
|
+
def _is_number(e):
|
|
10
|
+
try:
|
|
11
|
+
f = float(e)
|
|
12
|
+
return True
|
|
13
|
+
except ValueError: # for malformed strings
|
|
14
|
+
return False
|
|
15
|
+
except TypeError: # for other types (Variable, Expr)
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
class MatrixExpr(np.ndarray):
|
|
19
|
+
def sum(self, **kwargs):
|
|
20
|
+
return super().sum(**kwargs).item()
|
|
21
|
+
|
|
22
|
+
def __le__(self, other: Union[float, int, Variable, np.ndarray, 'MatrixExpr']) -> np.ndarray:
|
|
23
|
+
|
|
24
|
+
expr_cons_matrix = np.empty(self.shape, dtype=object)
|
|
25
|
+
if _is_number(other) or isinstance(other, Variable):
|
|
26
|
+
for idx in np.ndindex(self.shape):
|
|
27
|
+
expr_cons_matrix[idx] = self[idx] <= other
|
|
28
|
+
|
|
29
|
+
elif isinstance(other, np.ndarray):
|
|
30
|
+
for idx in np.ndindex(self.shape):
|
|
31
|
+
expr_cons_matrix[idx] = self[idx] <= other[idx]
|
|
32
|
+
else:
|
|
33
|
+
raise TypeError(f"Unsupported type {type(other)}")
|
|
34
|
+
|
|
35
|
+
return expr_cons_matrix.view(MatrixExprCons)
|
|
36
|
+
|
|
37
|
+
def __ge__(self, other: Union[float, int, Variable, np.ndarray, 'MatrixExpr']) -> np.ndarray:
|
|
38
|
+
|
|
39
|
+
expr_cons_matrix = np.empty(self.shape, dtype=object)
|
|
40
|
+
if _is_number(other) or isinstance(other, Variable):
|
|
41
|
+
for idx in np.ndindex(self.shape):
|
|
42
|
+
expr_cons_matrix[idx] = self[idx] >= other
|
|
43
|
+
|
|
44
|
+
elif isinstance(other, np.ndarray):
|
|
45
|
+
for idx in np.ndindex(self.shape):
|
|
46
|
+
expr_cons_matrix[idx] = self[idx] >= other[idx]
|
|
47
|
+
else:
|
|
48
|
+
raise TypeError(f"Unsupported type {type(other)}")
|
|
49
|
+
|
|
50
|
+
return expr_cons_matrix.view(MatrixExprCons)
|
|
51
|
+
|
|
52
|
+
def __eq__(self, other: Union[float, int, Variable, np.ndarray, 'MatrixExpr']) -> np.ndarray:
|
|
53
|
+
|
|
54
|
+
expr_cons_matrix = np.empty(self.shape, dtype=object)
|
|
55
|
+
if _is_number(other) or isinstance(other, Variable):
|
|
56
|
+
for idx in np.ndindex(self.shape):
|
|
57
|
+
expr_cons_matrix[idx] = self[idx] == other
|
|
58
|
+
|
|
59
|
+
elif isinstance(other, np.ndarray):
|
|
60
|
+
for idx in np.ndindex(self.shape):
|
|
61
|
+
expr_cons_matrix[idx] = self[idx] == other[idx]
|
|
62
|
+
else:
|
|
63
|
+
raise TypeError(f"Unsupported type {type(other)}")
|
|
64
|
+
|
|
65
|
+
return expr_cons_matrix.view(MatrixExprCons)
|
|
66
|
+
|
|
67
|
+
def __add__(self, other):
|
|
68
|
+
return super().__add__(other).view(MatrixExpr)
|
|
69
|
+
|
|
70
|
+
def __iadd__(self, other):
|
|
71
|
+
return super().__iadd__(other).view(MatrixExpr)
|
|
72
|
+
|
|
73
|
+
def __mul__(self, other):
|
|
74
|
+
return super().__mul__(other).view(MatrixExpr)
|
|
75
|
+
|
|
76
|
+
def __truediv__(self, other):
|
|
77
|
+
return super().__truediv__(other).view(MatrixExpr)
|
|
78
|
+
|
|
79
|
+
def __rtruediv__(self, other):
|
|
80
|
+
return super().__rtruediv__(other).view(MatrixExpr)
|
|
81
|
+
|
|
82
|
+
def __pow__(self, other):
|
|
83
|
+
return super().__pow__(other).view(MatrixExpr)
|
|
84
|
+
|
|
85
|
+
def __sub__(self, other):
|
|
86
|
+
return super().__sub__(other).view(MatrixExpr)
|
|
87
|
+
|
|
88
|
+
def __radd__(self, other):
|
|
89
|
+
return super().__radd__(other).view(MatrixExpr)
|
|
90
|
+
|
|
91
|
+
def __rmul__(self, other):
|
|
92
|
+
return super().__rmul__(other).view(MatrixExpr)
|
|
93
|
+
|
|
94
|
+
def __rsub__(self, other):
|
|
95
|
+
return super().__rsub__(other).view(MatrixExpr)
|
|
96
|
+
|
|
97
|
+
class MatrixGenExpr(MatrixExpr):
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
class MatrixExprCons(np.ndarray):
|
|
101
|
+
|
|
102
|
+
def __le__(self, other: Union[float, int, Variable, MatrixExpr]) -> np.ndarray:
|
|
103
|
+
|
|
104
|
+
if not _is_number(other) or not isinstance(other, MatrixExpr):
|
|
105
|
+
raise TypeError('Ranged MatrixExprCons is not well defined!')
|
|
106
|
+
|
|
107
|
+
expr_cons_matrix = np.empty(self.shape, dtype=object)
|
|
108
|
+
if _is_number(other) or isinstance(other, Variable):
|
|
109
|
+
for idx in np.ndindex(self.shape):
|
|
110
|
+
expr_cons_matrix[idx] = self[idx] <= other
|
|
111
|
+
|
|
112
|
+
elif isinstance(other, np.ndarray):
|
|
113
|
+
for idx in np.ndindex(self.shape):
|
|
114
|
+
expr_cons_matrix[idx] = self[idx] <= other[idx]
|
|
115
|
+
else:
|
|
116
|
+
raise TypeError(f"Unsupported type {type(other)}")
|
|
117
|
+
|
|
118
|
+
return expr_cons_matrix.view(MatrixExprCons)
|
|
119
|
+
|
|
120
|
+
def __ge__(self, other: Union[float, int, Variable, MatrixExpr]) -> np.ndarray:
|
|
121
|
+
|
|
122
|
+
if not _is_number(other) or not isinstance(other, MatrixExpr):
|
|
123
|
+
raise TypeError('Ranged MatrixExprCons is not well defined!')
|
|
124
|
+
|
|
125
|
+
expr_cons_matrix = np.empty(self.shape, dtype=object)
|
|
126
|
+
if _is_number(other) or isinstance(other, Variable):
|
|
127
|
+
for idx in np.ndindex(self.shape):
|
|
128
|
+
expr_cons_matrix[idx] = self[idx] >= other
|
|
129
|
+
|
|
130
|
+
elif isinstance(other, np.ndarray):
|
|
131
|
+
for idx in np.ndindex(self.shape):
|
|
132
|
+
expr_cons_matrix[idx] = self[idx] >= other[idx]
|
|
133
|
+
else:
|
|
134
|
+
raise TypeError(f"Unsupported type {type(other)}")
|
|
135
|
+
|
|
136
|
+
return expr_cons_matrix.view(MatrixExprCons)
|
|
137
|
+
|
|
138
|
+
def __eq__(self, other):
|
|
139
|
+
raise TypeError
|