optimtool 2.8.3__tar.gz → 2.9.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.
- {optimtool-2.8.3 → optimtool-2.9.1}/PKG-INFO +14 -4
- {optimtool-2.8.3 → optimtool-2.9.1}/README.md +13 -3
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/__init__.py +1 -1
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_drive.py +11 -18
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_search.py +17 -34
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_utils.py +3 -5
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_version.py +1 -1
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/constrain/equal.py +6 -4
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/constrain/mixequal.py +14 -9
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/constrain/unequal.py +10 -6
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/example/Lasso.py +10 -7
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/hybrid/approt.py +2 -1
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/hybrid/fista.py +7 -4
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/hybrid/nesterov.py +4 -2
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/gradient_descent.py +9 -6
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/newton.py +11 -8
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/newton_quasi.py +12 -9
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/nonlinear_least_square.py +6 -4
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/trust_region.py +1 -1
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/PKG-INFO +14 -4
- {optimtool-2.8.3 → optimtool-2.9.1}/setup.py +1 -1
- {optimtool-2.8.3 → optimtool-2.9.1}/LICENSE +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_convert.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_kernel.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_proxim.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/_typing.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/base.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/constrain/__init__.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/example/WanYuan.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/example/__init__.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/hybrid/__init__.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool/unconstrain/__init__.py +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/SOURCES.txt +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/dependency_links.txt +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/not-zip-safe +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/requires.txt +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/optimtool.egg-info/top_level.txt +0 -0
- {optimtool-2.8.3 → optimtool-2.9.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: optimtool
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.1
|
|
4
4
|
Summary: The fundamental package for scientific research in optimization.
|
|
5
5
|
Home-page: https://github.com/linjing-lab/optimtool
|
|
6
6
|
Download-URL: https://github.com/linjing-lab/optimtool/tags
|
|
@@ -52,12 +52,22 @@ License-File: LICENSE
|
|
|
52
52
|
|
|
53
53
|
## 项目介绍
|
|
54
54
|
|
|
55
|
-
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合Python
|
|
55
|
+
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合sp.lambdify实现了高效地数值矩阵的运算,最终设计的用在最优化科学研究的Python工具包。
|
|
56
56
|
|
|
57
57
|
如果你在研究中使用 **optimtool**,欢迎引用它在你的参考资料中(按照下面的格式)。
|
|
58
58
|
|
|
59
|
-
```
|
|
60
|
-
|
|
59
|
+
```bibtex
|
|
60
|
+
@software{Lin2021optimtool,
|
|
61
|
+
author = {Lin, Jing},
|
|
62
|
+
title = {optimtool: The fundamental package for scientific research in optimization.},
|
|
63
|
+
year = {2021},
|
|
64
|
+
version = {2.9.1},
|
|
65
|
+
publisher = {PyPI},
|
|
66
|
+
organization = {linjing-lab},
|
|
67
|
+
url = {https://pypi.org/project/optimtool/},
|
|
68
|
+
license = {MIT},
|
|
69
|
+
note = {Source code available at \url{https://github.com/linjing-lab/optimtool}},
|
|
70
|
+
}
|
|
61
71
|
```
|
|
62
72
|
|
|
63
73
|
下载最新版:
|
|
@@ -23,12 +23,22 @@
|
|
|
23
23
|
|
|
24
24
|
## 项目介绍
|
|
25
25
|
|
|
26
|
-
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合Python
|
|
26
|
+
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合sp.lambdify实现了高效地数值矩阵的运算,最终设计的用在最优化科学研究的Python工具包。
|
|
27
27
|
|
|
28
28
|
如果你在研究中使用 **optimtool**,欢迎引用它在你的参考资料中(按照下面的格式)。
|
|
29
29
|
|
|
30
|
-
```
|
|
31
|
-
|
|
30
|
+
```bibtex
|
|
31
|
+
@software{Lin2021optimtool,
|
|
32
|
+
author = {Lin, Jing},
|
|
33
|
+
title = {optimtool: The fundamental package for scientific research in optimization.},
|
|
34
|
+
year = {2021},
|
|
35
|
+
version = {2.9.1},
|
|
36
|
+
publisher = {PyPI},
|
|
37
|
+
organization = {linjing-lab},
|
|
38
|
+
url = {https://pypi.org/project/optimtool/},
|
|
39
|
+
license = {MIT},
|
|
40
|
+
note = {Source code available at \url{https://github.com/linjing-lab/optimtool}},
|
|
41
|
+
}
|
|
32
42
|
```
|
|
33
43
|
|
|
34
44
|
下载最新版:
|
|
@@ -32,4 +32,4 @@ from .base import MATPLOTLIB_VERSION
|
|
|
32
32
|
from ._version import __version__
|
|
33
33
|
|
|
34
34
|
if sys.version_info < (3, 7, 0):
|
|
35
|
-
raise OSError(f'optimtool-2.
|
|
35
|
+
raise OSError(f'optimtool-2.9.1 requires Python >=3.7, but yours is {sys.version}')
|
|
@@ -26,16 +26,14 @@ def Q_k(eta: float,
|
|
|
26
26
|
assert k >= 0
|
|
27
27
|
return 1 if k == 0 else eta * Q_k(eta, k-1) + 1
|
|
28
28
|
|
|
29
|
-
def C_k(
|
|
30
|
-
args: SympyMutableDenseMatrix,
|
|
29
|
+
def C_k(funcs_num,
|
|
31
30
|
point: List[IterPointType],
|
|
32
31
|
eta: float,
|
|
33
32
|
k: int) -> DataType:
|
|
34
33
|
assert k >= 0
|
|
35
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
36
34
|
temp0 = funcs_num(*point[0])
|
|
37
35
|
tempk = funcs_num(*point[k])
|
|
38
|
-
return temp0 if k == 0 else (1 / (Q_k(eta, k))) * (eta * Q_k(eta, k-1) * C_k(
|
|
36
|
+
return temp0 if k == 0 else (1 / (Q_k(eta, k))) * (eta * Q_k(eta, k-1) * C_k(funcs_num, point, eta, k-1) + tempk)
|
|
39
37
|
# return np.array(funcs.subs(dict(zip(args, point[0])))).astype(DataType) if k == 0 else (1 / (Q_k(eta, k))) * (eta * Q_k(eta, k-1) * C_k(funcs, args, point, eta, k-1) + np.array(funcs.subs(dict(zip(args, point[k])))).astype(DataType))
|
|
40
38
|
|
|
41
39
|
def get_f_delta_gradient(resv: NDArray,
|
|
@@ -169,40 +167,35 @@ def cons_unequal_L(cons_unequal: SympyMutableDenseMatrix,
|
|
|
169
167
|
sub = sub - (muk[i] / sigma)**2
|
|
170
168
|
return sp.Matrix([sub])
|
|
171
169
|
|
|
172
|
-
def v_k(
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
def v_k(cons_equal_num,
|
|
171
|
+
cons_unequal_num,
|
|
172
|
+
len_cons: int,
|
|
175
173
|
muk: NDArray,
|
|
176
174
|
sigma: float,
|
|
177
175
|
x_0: IterPointType) -> DataType:
|
|
178
176
|
sub = 0.
|
|
179
177
|
# reps = dict(zip(args, x_0))
|
|
180
|
-
len_unequal = cons_unequal.shape[0]
|
|
181
|
-
cons_unequal_num = sp.lambdify(args, cons_unequal, modules='numpy')
|
|
182
178
|
consv_unequal = cons_unequal_num(*x_0)
|
|
183
179
|
# consv_unequal = np.array(cons_unequal.subs(reps)).astype(DataType)
|
|
184
|
-
if
|
|
185
|
-
cons_equal_num = sp.lambdify(args, cons_equal, modules='numpy')
|
|
180
|
+
if cons_equal_num is not None:
|
|
186
181
|
consv_equal = cons_equal_num(*x_0)
|
|
187
182
|
# consv_equal = np.array(cons_equal.subs(reps)).astype(DataType)
|
|
188
183
|
sub += (consv_equal.T).dot(consv_equal)
|
|
189
|
-
for i in range(
|
|
184
|
+
for i in range(len_cons):
|
|
190
185
|
sub += (max(consv_unequal[i], - muk[i] / sigma))**2
|
|
191
186
|
else:
|
|
192
|
-
for i in range(
|
|
187
|
+
for i in range(len_cons):
|
|
193
188
|
sub += (max(consv_unequal[i], - muk[i] / sigma))**2
|
|
194
189
|
return np.sqrt(sub)
|
|
195
190
|
|
|
196
|
-
def renew_mu_k(
|
|
197
|
-
|
|
191
|
+
def renew_mu_k(cons_unequal_num,
|
|
192
|
+
len_cons: int,
|
|
198
193
|
muk: NDArray,
|
|
199
194
|
sigma: float,
|
|
200
195
|
x_0: IterPointType) -> NDArray:
|
|
201
196
|
# reps = dict(zip(args, x_0))
|
|
202
|
-
len_unequal = cons_unequal.shape[0]
|
|
203
|
-
cons_unequal_num = sp.lambdify(args, cons_unequal, modules='numpy')
|
|
204
197
|
consv_unequal = cons_unequal_num(*x_0)
|
|
205
|
-
for i in range(
|
|
198
|
+
for i in range(len_cons):
|
|
206
199
|
muk[i] = max(muk[i] + sigma * consv_unequal[i], 0)
|
|
207
200
|
return muk
|
|
208
201
|
|
|
@@ -23,17 +23,15 @@ from ._typing import List, NDArray, SympyMutableDenseMatrix, DataType, IterPoint
|
|
|
23
23
|
|
|
24
24
|
__all__ = ["armijo", "goldstein", "wolfe", "Grippo", "ZhangHanger"]
|
|
25
25
|
|
|
26
|
-
def armijo(
|
|
27
|
-
|
|
28
|
-
args: SympyMutableDenseMatrix,
|
|
26
|
+
def armijo(funcs_num,
|
|
27
|
+
res_num,
|
|
29
28
|
x_0: IterPointType,
|
|
30
29
|
d: NDArray,
|
|
31
30
|
gamma: float=0.5,
|
|
32
31
|
c: float=0.1) -> float:
|
|
33
32
|
'''
|
|
34
|
-
:param
|
|
35
|
-
:param
|
|
36
|
-
:param args: SympyMutableDenseMatrix, symbolic set with order in a list to construct `dict(zip(args, x_0))`.
|
|
33
|
+
:param funcs_num, objective function with `convert` process used for search alpha.
|
|
34
|
+
:param res_num:, gradient function computed by .jacobian function.
|
|
37
35
|
:param x_0: IterPointType, numerical values in a 'list` or 'tuple` according to the order of `args`.
|
|
38
36
|
:param d: NDArray, current gradient descent direction with format at `numpy.ndarray`.
|
|
39
37
|
:param gamma: float, factor used to adjust alpha with interval at (0, 1). default: float=0.5.
|
|
@@ -46,9 +44,7 @@ def armijo(funcs: SympyMutableDenseMatrix,
|
|
|
46
44
|
assert c > 0
|
|
47
45
|
assert c < 1
|
|
48
46
|
alpha = 1
|
|
49
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
50
47
|
f0 = funcs_num(*x_0)
|
|
51
|
-
res_num = sp.lambdify(args, res, modules='numpy')
|
|
52
48
|
res0 = res_num(*x_0)
|
|
53
49
|
# reps = dict(zip(args, x_0))
|
|
54
50
|
# f0 = np.array(funcs.subs(reps)).astype(DataType)
|
|
@@ -63,9 +59,8 @@ def armijo(funcs: SympyMutableDenseMatrix,
|
|
|
63
59
|
alpha *= gamma
|
|
64
60
|
return alpha
|
|
65
61
|
|
|
66
|
-
def goldstein(
|
|
67
|
-
|
|
68
|
-
args: SympyMutableDenseMatrix,
|
|
62
|
+
def goldstein(funcs_num,
|
|
63
|
+
res_num,
|
|
69
64
|
x_0: IterPointType,
|
|
70
65
|
d: NDArray,
|
|
71
66
|
c: float=0.2,
|
|
@@ -74,8 +69,8 @@ def goldstein(funcs: SympyMutableDenseMatrix,
|
|
|
74
69
|
t: float=1.2,
|
|
75
70
|
eps: float=1e-3) -> float:
|
|
76
71
|
'''
|
|
77
|
-
:param
|
|
78
|
-
:param
|
|
72
|
+
:param funcs_num: SympyMutableDenseMatrix, objective function with `convert` process used for search alpha.
|
|
73
|
+
:param res_num: SympyMutableDenseMatrix, gradient function computed by .jacobian function.
|
|
79
74
|
:param args: SympyMutableDenseMatrix, symbolic set with order in a list to construct `dict(zip(args, x_0))`.
|
|
80
75
|
:param x_0: IterPointType, numerical values in a 'list` or 'tuple` according to the order of `args`.
|
|
81
76
|
:param d: NDArray, current gradient descent direction with format at `numpy.ndarray`.
|
|
@@ -94,9 +89,7 @@ def goldstein(funcs: SympyMutableDenseMatrix,
|
|
|
94
89
|
assert t > 0
|
|
95
90
|
assert eps > 0
|
|
96
91
|
alpha = 1
|
|
97
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
98
92
|
f0 = funcs_num(*x_0)
|
|
99
|
-
res_num = sp.lambdify(args, res, modules='numpy')
|
|
100
93
|
res0 = res_num(*x_0)
|
|
101
94
|
# reps = dict(zip(args, x_0))
|
|
102
95
|
# f0 = np.array(funcs.subs(reps)).astype(DataType)
|
|
@@ -122,9 +115,8 @@ def goldstein(funcs: SympyMutableDenseMatrix,
|
|
|
122
115
|
break
|
|
123
116
|
return alpha
|
|
124
117
|
|
|
125
|
-
def wolfe(
|
|
126
|
-
|
|
127
|
-
args: SympyMutableDenseMatrix,
|
|
118
|
+
def wolfe(funcs_num,
|
|
119
|
+
res_num,
|
|
128
120
|
x_0: IterPointType,
|
|
129
121
|
d: NDArray,
|
|
130
122
|
c1: float=0.3,
|
|
@@ -133,9 +125,8 @@ def wolfe(funcs: SympyMutableDenseMatrix,
|
|
|
133
125
|
alphae: float=2.,
|
|
134
126
|
eps: float=1e-3) -> float:
|
|
135
127
|
'''
|
|
136
|
-
:param
|
|
137
|
-
:param
|
|
138
|
-
:param args: SympyMutableDenseMatrix, symbolic set with order in a list to construct `dict(zip(args, x_0))`.
|
|
128
|
+
:param funcs_num, objective function with `convert` process used for search alpha.
|
|
129
|
+
:param res_num, gradient function computed by .jacobian function.
|
|
139
130
|
:param x_0: IterPointType, numerical values in a 'list` or 'tuple` according to the order of `args`.
|
|
140
131
|
:param d: NDArray, current gradient descent direction with format at `numpy.ndarray`.
|
|
141
132
|
:param c1: float, first constant used to constrain alpha adjusted frequency with interval at (0, 1). default: float=0.3.
|
|
@@ -155,9 +146,7 @@ def wolfe(funcs: SympyMutableDenseMatrix,
|
|
|
155
146
|
assert alphas < alphae
|
|
156
147
|
assert eps > 0
|
|
157
148
|
alpha = 1
|
|
158
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
159
149
|
f0 = funcs_num(*x_0)
|
|
160
|
-
res_num = sp.lambdify(args, res, modules='numpy')
|
|
161
150
|
res0 = res_num(*x_0)
|
|
162
151
|
# reps = dict(zip(args, x_0))
|
|
163
152
|
# f0 = np.array(funcs.subs(reps)).astype(DataType)
|
|
@@ -182,8 +171,7 @@ def wolfe(funcs: SympyMutableDenseMatrix,
|
|
|
182
171
|
return alpha
|
|
183
172
|
|
|
184
173
|
# coordinate with `barzilar_borwein`.
|
|
185
|
-
def Grippo(
|
|
186
|
-
args: SympyMutableDenseMatrix,
|
|
174
|
+
def Grippo(funcs_num,
|
|
187
175
|
x_0: IterPointType,
|
|
188
176
|
d: NDArray,
|
|
189
177
|
k: int,
|
|
@@ -193,8 +181,7 @@ def Grippo(funcs: SympyMutableDenseMatrix,
|
|
|
193
181
|
alpha: float,
|
|
194
182
|
M: int) -> float:
|
|
195
183
|
'''
|
|
196
|
-
:param
|
|
197
|
-
:param args: SympyMutableDenseMatrix, symbolic set with order in a list to construct `dict(zip(args, x_0))`.
|
|
184
|
+
:param funcs_num, objective function with `convert` process used for search alpha.
|
|
198
185
|
:param x_0: IterPointType, numerical values in a 'list` or 'tuple` according to the order of `args`.
|
|
199
186
|
:param d: NDArray, current gradient descent direction with format at `numpy.ndarray`.
|
|
200
187
|
:param k: int, current number of iterative process in `barzilar_borwein` method.
|
|
@@ -211,7 +198,6 @@ def Grippo(funcs: SympyMutableDenseMatrix,
|
|
|
211
198
|
assert c1 < 1
|
|
212
199
|
assert beta > 0
|
|
213
200
|
assert beta < 1
|
|
214
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
215
201
|
while 1:
|
|
216
202
|
x = x_0 + (alpha*d)[0]
|
|
217
203
|
f1 = funcs_num(*x)
|
|
@@ -227,8 +213,7 @@ def Grippo(funcs: SympyMutableDenseMatrix,
|
|
|
227
213
|
alpha *= beta
|
|
228
214
|
return alpha
|
|
229
215
|
|
|
230
|
-
def ZhangHanger(
|
|
231
|
-
args: SympyMutableDenseMatrix,
|
|
216
|
+
def ZhangHanger(funcs_num,
|
|
232
217
|
x_0: IterPointType,
|
|
233
218
|
d: NDArray,
|
|
234
219
|
k: int,
|
|
@@ -238,8 +223,7 @@ def ZhangHanger(funcs: SympyMutableDenseMatrix,
|
|
|
238
223
|
alpha: float,
|
|
239
224
|
eta: float) -> float:
|
|
240
225
|
'''
|
|
241
|
-
:param
|
|
242
|
-
:param args: SympyMutableDenseMatrix, symbolic set with order in a list to construct `dict(zip(args, x_0))`.
|
|
226
|
+
:param funcs_num, objective function with `convert` process used for search alpha.
|
|
243
227
|
:param x_0: IterPointType, numerical values in a 'list` or 'tuple` according to the order of `args`.
|
|
244
228
|
:param d: NDArray, current gradient descent direction with format at `numpy.ndarray`.
|
|
245
229
|
:param k: int, current number of iterative process in `barzilar_borwein` method.
|
|
@@ -259,12 +243,11 @@ def ZhangHanger(funcs: SympyMutableDenseMatrix,
|
|
|
259
243
|
assert beta > 0
|
|
260
244
|
assert beta < 1
|
|
261
245
|
from ._drive import C_k
|
|
262
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
263
246
|
while 1:
|
|
264
247
|
x = x_0 + (alpha*d)[0]
|
|
265
248
|
f1 = funcs_num(*x)
|
|
266
249
|
# f1 = np.array(funcs.subs(dict(zip(args, x)))).astype(DataType)
|
|
267
|
-
Ck = C_k(
|
|
250
|
+
Ck = C_k(funcs_num, point, eta, k)
|
|
268
251
|
if f1 <= Ck + c1 * alpha * (-d).dot(d.T):
|
|
269
252
|
break
|
|
270
253
|
else:
|
|
@@ -19,21 +19,19 @@
|
|
|
19
19
|
# SOFTWARE.
|
|
20
20
|
|
|
21
21
|
from .base import np, sp, plt
|
|
22
|
-
from ._typing import DataType, Optional,
|
|
22
|
+
from ._typing import DataType, Optional, List, IterPointType
|
|
23
23
|
|
|
24
24
|
__all__ = ["get_value", "plot_iteration"]
|
|
25
25
|
|
|
26
|
-
def get_value(
|
|
26
|
+
def get_value(funcs_num, x_0: IterPointType, mu: Optional[float]=None, proxim: Optional[str]=None) -> DataType:
|
|
27
27
|
'''
|
|
28
|
-
:param
|
|
29
|
-
:param args: SympyMutableDenseMatrix, symbolic set after `convert` with order.
|
|
28
|
+
:param funcs_num, objective function after `convert`.
|
|
30
29
|
:param x_0: IterPointType, numpy.ndarray or List[PointType] or Tuple[PointType].
|
|
31
30
|
:param mu: float | None, parameters collaborate with the problems applied in `Lasso`. default=None.
|
|
32
31
|
:param proxim: str | None, parameter indicate the type of proximity operators. default=None.
|
|
33
32
|
|
|
34
33
|
:return: functional value with DataType.
|
|
35
34
|
'''
|
|
36
|
-
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
37
35
|
funcsv = funcs_num(*x_0)
|
|
38
36
|
# funcsv = np.array(funcs.subs(dict(zip(args, x_0)))).astype(DataType)
|
|
39
37
|
if mu is not None:
|
|
@@ -60,12 +60,13 @@ def penalty_quadratice(funcs: FuncArray,
|
|
|
60
60
|
assert p > 1
|
|
61
61
|
from .._kernel import kernel
|
|
62
62
|
funcs, args, x_0, cons = f2m(funcs), a2m(args), p2t(x_0), f2m(cons)
|
|
63
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
63
64
|
search, point, f = kernel(method), [], []
|
|
64
65
|
sig = sp.symbols("sig")
|
|
65
66
|
pen = funcs + (sig / 2) * cons.T * cons
|
|
66
67
|
while 1:
|
|
67
68
|
point.append(np.array(x_0))
|
|
68
|
-
f.append(get_value(
|
|
69
|
+
f.append(get_value(funcs_num, x_0))
|
|
69
70
|
if verbose:
|
|
70
71
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
71
72
|
pe = pen.subs(sig, sigma)
|
|
@@ -74,7 +75,7 @@ def penalty_quadratice(funcs: FuncArray,
|
|
|
74
75
|
sigma *= p
|
|
75
76
|
if np.linalg.norm(x_0 - point[k - 1]) < epsilon:
|
|
76
77
|
point.append(np.array(x_0))
|
|
77
|
-
f.append(get_value(
|
|
78
|
+
f.append(get_value(funcs_num, x_0))
|
|
78
79
|
if verbose:
|
|
79
80
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
80
81
|
break
|
|
@@ -118,10 +119,11 @@ def lagrange_augmentede(funcs: FuncArray,
|
|
|
118
119
|
from .._kernel import kernel
|
|
119
120
|
search, f = kernel(method), []
|
|
120
121
|
funcs, args, x_0, cons = f2m(funcs), a2m(args), p2t(x_0), f2m(cons)
|
|
122
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
121
123
|
lamk = np.array([lamk for _ in range(cons.shape[0])]).reshape(cons.shape[0], 1)
|
|
122
124
|
cons_num = sp.lambdify(args, cons, modules='numpy')
|
|
123
125
|
while 1:
|
|
124
|
-
f.append(get_value(
|
|
126
|
+
f.append(get_value(funcs_num, x_0))
|
|
125
127
|
if verbose:
|
|
126
128
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
127
129
|
L = sp.Matrix([funcs + (sigma / 2) * cons.T * cons + cons.T * lamk])
|
|
@@ -133,7 +135,7 @@ def lagrange_augmentede(funcs: FuncArray,
|
|
|
133
135
|
k += 1
|
|
134
136
|
sigma *= p
|
|
135
137
|
if np.linalg.norm(consv) <= epsilon:
|
|
136
|
-
f.append(get_value(
|
|
138
|
+
f.append(get_value(funcs_num, x_0))
|
|
137
139
|
if verbose:
|
|
138
140
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
139
141
|
break
|
|
@@ -62,11 +62,12 @@ def penalty_quadraticm(funcs: FuncArray,
|
|
|
62
62
|
assert p > 0
|
|
63
63
|
from .._kernel import kernel
|
|
64
64
|
funcs, args, cons_equal, cons_unequal, x_0 = f2m(funcs), a2m(args), f2m(cons_equal), f2m(cons_unequal), p2t(x_0)
|
|
65
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
65
66
|
search, point, f = kernel(method), [], []
|
|
66
67
|
cons_unequal_num = sp.lambdify(args, cons_unequal, modules='numpy')
|
|
67
68
|
while 1:
|
|
68
69
|
point.append(np.array(x_0))
|
|
69
|
-
f.append(get_value(
|
|
70
|
+
f.append(get_value(funcs_num, x_0))
|
|
70
71
|
if verbose:
|
|
71
72
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
72
73
|
# reps = dict(zip(args, x_0))
|
|
@@ -80,7 +81,7 @@ def penalty_quadraticm(funcs: FuncArray,
|
|
|
80
81
|
sigma *= p
|
|
81
82
|
if np.linalg.norm(x_0 - point[k - 1]) < epsilon:
|
|
82
83
|
point.append(np.array(x_0))
|
|
83
|
-
f.append(get_value(
|
|
84
|
+
f.append(get_value(funcs_num, x_0))
|
|
84
85
|
if verbose:
|
|
85
86
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
86
87
|
break
|
|
@@ -123,15 +124,16 @@ def penalty_L1(funcs: FuncArray,
|
|
|
123
124
|
assert p > 0
|
|
124
125
|
from .._kernel import kernel
|
|
125
126
|
funcs, args, cons_equal, cons_unequal, x_0 = f2m(funcs), a2m(args), f2m(cons_equal), f2m(cons_unequal), p2t(x_0)
|
|
127
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
126
128
|
search, point, f = kernel(method), [], []
|
|
127
129
|
cons_unequal_num = sp.lambdify(args, cons_unequal, modules='numpy')
|
|
128
130
|
cons_equal_num = sp.lambdify(args, cons_equal, modules='numpy')
|
|
129
131
|
while 1:
|
|
130
132
|
point.append(np.array(x_0))
|
|
131
|
-
f.append(get_value(
|
|
133
|
+
f.append(get_value(funcs_num, x_0))
|
|
132
134
|
if verbose:
|
|
133
135
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
134
|
-
reps = dict(zip(args, x_0))
|
|
136
|
+
# reps = dict(zip(args, x_0))
|
|
135
137
|
consv_unequal = cons_unequal_num(*x_0)
|
|
136
138
|
# consv_unequal = np.array(cons_unequal.subs(reps)).astype(DataType)
|
|
137
139
|
consv_unequal = np.where(consv_unequal <= 0, consv_unequal, 1)
|
|
@@ -146,7 +148,7 @@ def penalty_L1(funcs: FuncArray,
|
|
|
146
148
|
sigma *= p
|
|
147
149
|
if np.linalg.norm(x_0 - point[k - 1]) < epsilon:
|
|
148
150
|
point.append(np.array(x_0))
|
|
149
|
-
f.append(get_value(
|
|
151
|
+
f.append(get_value(funcs_num, x_0))
|
|
150
152
|
if verbose:
|
|
151
153
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
152
154
|
break
|
|
@@ -201,12 +203,15 @@ def lagrange_augmentedm(funcs: FuncArray,
|
|
|
201
203
|
from .._kernel import kernel
|
|
202
204
|
from .._drive import cons_unequal_L, v_k, renew_mu_k
|
|
203
205
|
funcs, args, cons_equal, cons_unequal, x_0 = f2m(funcs), a2m(args), f2m(cons_equal), f2m(cons_unequal), p2t(x_0)
|
|
206
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
204
207
|
search, f = kernel(method), []
|
|
205
208
|
lamk = np.array([lamk for _ in range(cons_equal.shape[0])]).reshape(cons_equal.shape[0], 1)
|
|
206
209
|
muk = np.array([muk for _ in range(cons_unequal.shape[0])]).reshape(cons_unequal.shape[0], 1)
|
|
207
210
|
cons_equal_num = sp.lambdify(args, cons_equal, modules='numpy')
|
|
211
|
+
len_cons_unequal = len(cons_unequal)
|
|
212
|
+
cons_unequal_num = sp.lambdify(args, cons_unequal, modules='numpy')
|
|
208
213
|
while 1:
|
|
209
|
-
f.append(get_value(
|
|
214
|
+
f.append(get_value(funcs_num, x_0))
|
|
210
215
|
if verbose:
|
|
211
216
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
212
217
|
etak = 1 / sigma
|
|
@@ -215,19 +220,19 @@ def lagrange_augmentedm(funcs: FuncArray,
|
|
|
215
220
|
L = sp.Matrix([funcs + (sigma / 2) * (cons_equal.T * cons_equal + cons_uneuqal_modifyed) + cons_equal.T * lamk])
|
|
216
221
|
x_0, _ = search(L, args, tuple(x_0), draw=False, epsilon=epsilonk)
|
|
217
222
|
k += 1
|
|
218
|
-
vkx = v_k(
|
|
223
|
+
vkx = v_k(cons_equal_num, cons_unequal_num, len_cons_unequal, muk, sigma, x_0)
|
|
219
224
|
if vkx <= epsilonk:
|
|
220
225
|
res = L.jacobian(args)
|
|
221
226
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
222
227
|
if (vkx <= epsilon) and (np.linalg.norm(res_num(*x_0)) <= etak):
|
|
223
|
-
f.append(get_value(
|
|
228
|
+
f.append(get_value(funcs_num, x_0))
|
|
224
229
|
if verbose:
|
|
225
230
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
226
231
|
break
|
|
227
232
|
else:
|
|
228
233
|
consv_equal = cons_equal_num(*x_0)
|
|
229
234
|
lamk += sigma * consv_equal
|
|
230
|
-
muk = renew_mu_k(
|
|
235
|
+
muk = renew_mu_k(cons_unequal_num, len_cons_unequal, muk, sigma, x_0)
|
|
231
236
|
etak /= sigma
|
|
232
237
|
epsilonk /= sigma**beta
|
|
233
238
|
else:
|
|
@@ -61,11 +61,12 @@ def penalty_quadraticu(funcs: FuncArray,
|
|
|
61
61
|
assert p < 1
|
|
62
62
|
from .._kernel import kernel
|
|
63
63
|
funcs, args, x_0, cons = f2m(funcs), a2m(args), p2t(x_0), f2m(cons)
|
|
64
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
64
65
|
search, point, f = kernel(method), [], []
|
|
65
66
|
cons_num = sp.lambdify(args, cons, modules='numpy')
|
|
66
67
|
while 1:
|
|
67
68
|
point.append(np.array(x_0))
|
|
68
|
-
f.append(get_value(
|
|
69
|
+
f.append(get_value(funcs_num, x_0))
|
|
69
70
|
if verbose:
|
|
70
71
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
71
72
|
# reps = dict(zip(args, x_0))
|
|
@@ -79,7 +80,7 @@ def penalty_quadraticu(funcs: FuncArray,
|
|
|
79
80
|
sigma *= p
|
|
80
81
|
if np.linalg.norm(x_0 - point[k - 1]) < epsilon:
|
|
81
82
|
point.append(np.array(x_0))
|
|
82
|
-
f.append(get_value(
|
|
83
|
+
f.append(get_value(funcs_num, x_0))
|
|
83
84
|
if verbose:
|
|
84
85
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
85
86
|
break
|
|
@@ -131,10 +132,13 @@ def lagrange_augmentedu(funcs: FuncArray,
|
|
|
131
132
|
from .._kernel import kernel
|
|
132
133
|
from .._drive import cons_unequal_L, renew_mu_k, v_k
|
|
133
134
|
funcs, args, x_0, cons = f2m(funcs), a2m(args), p2t(x_0), f2m(cons)
|
|
135
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
134
136
|
search, f = kernel(method), []
|
|
135
137
|
muk = np.array([muk for _ in range(cons.shape[0])]).reshape(cons.shape[0], 1)
|
|
138
|
+
len_cons = len(cons)
|
|
139
|
+
cons_unequal_num = sp.lambdify(args, cons, modules='numpy')
|
|
136
140
|
while 1:
|
|
137
|
-
f.append(get_value(
|
|
141
|
+
f.append(get_value(funcs_num, x_0))
|
|
138
142
|
if verbose:
|
|
139
143
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
140
144
|
etak = 1 / sigma
|
|
@@ -143,17 +147,17 @@ def lagrange_augmentedu(funcs: FuncArray,
|
|
|
143
147
|
L = sp.Matrix([funcs + (sigma / 2) * cons_uneuqal_modifyed])
|
|
144
148
|
x_0, _ = search(L, args, tuple(x_0), draw=False, epsilon=epsilonk)
|
|
145
149
|
k += 1
|
|
146
|
-
vkx = v_k(None,
|
|
150
|
+
vkx = v_k(None, cons_unequal_num, len_cons, muk, sigma, x_0)
|
|
147
151
|
if vkx <= epsilonk:
|
|
148
152
|
res = L.jacobian(args)
|
|
149
153
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
150
154
|
if (vkx <= epsilon) and (np.linalg.norm(res_num(*x_0)) <= eta):
|
|
151
|
-
f.append(get_value(
|
|
155
|
+
f.append(get_value(funcs_num, x_0))
|
|
152
156
|
if verbose:
|
|
153
157
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
154
158
|
break
|
|
155
159
|
else:
|
|
156
|
-
muk = renew_mu_k(
|
|
160
|
+
muk = renew_mu_k(cons_unequal_num, len_cons, muk, sigma, x_0)
|
|
157
161
|
etak /= sigma
|
|
158
162
|
epsilonk /= sigma**beta
|
|
159
163
|
else:
|
|
@@ -60,6 +60,7 @@ def gradient(A: NDArray,
|
|
|
60
60
|
args, x_0 = a2m(args), p2t(x_0)
|
|
61
61
|
assert args.shape[0] == len(x_0)
|
|
62
62
|
funcs = sp.Matrix([0.5*((A*args - b).T)*(A*args - b)])
|
|
63
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
63
64
|
res = funcs.jacobian(args)
|
|
64
65
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
65
66
|
args_num = sp.lambdify(args, args, modules='numpy')
|
|
@@ -69,7 +70,7 @@ def gradient(A: NDArray,
|
|
|
69
70
|
while 1:
|
|
70
71
|
# reps = dict(zip(args, x_0))
|
|
71
72
|
point.append(np.array(x_0))
|
|
72
|
-
f.append(get_value(
|
|
73
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
73
74
|
if verbose:
|
|
74
75
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
75
76
|
resv = res_num(*x_0)
|
|
@@ -79,7 +80,7 @@ def gradient(A: NDArray,
|
|
|
79
80
|
k = k + 1
|
|
80
81
|
if np.linalg.norm(x_0 - point[k - 1]) <= epsilon:
|
|
81
82
|
point.append(np.array(x_0))
|
|
82
|
-
f.append(get_value(
|
|
83
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
83
84
|
if verbose:
|
|
84
85
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
85
86
|
break
|
|
@@ -117,14 +118,15 @@ def subgradient(A: NDArray,
|
|
|
117
118
|
args, x_0 = a2m(args), p2t(x_0)
|
|
118
119
|
assert args.shape[0] == len(x_0)
|
|
119
120
|
funcs = sp.Matrix([0.5*((A*args - b).T)*(A*args - b)])
|
|
121
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
120
122
|
res = funcs.jacobian(args)
|
|
121
123
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
122
124
|
args_num = sp.lambdify(args, args, modules='numpy')
|
|
123
125
|
point, f = [], []
|
|
124
126
|
while 1:
|
|
125
|
-
reps = dict(zip(args, x_0))
|
|
127
|
+
# reps = dict(zip(args, x_0))
|
|
126
128
|
point.append(np.array(x_0))
|
|
127
|
-
f.append(get_value(
|
|
129
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
128
130
|
if verbose:
|
|
129
131
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
130
132
|
resv = res_num(*x_0)
|
|
@@ -135,7 +137,7 @@ def subgradient(A: NDArray,
|
|
|
135
137
|
k = k + 1
|
|
136
138
|
if np.linalg.norm(x_0 - point[k - 1]) <= epsilon:
|
|
137
139
|
point.append(np.array(x_0))
|
|
138
|
-
f.append(get_value(
|
|
140
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
139
141
|
if verbose:
|
|
140
142
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
141
143
|
break
|
|
@@ -172,13 +174,14 @@ def approximate_point(A: NDArray,
|
|
|
172
174
|
lambda_ma = max(values)
|
|
173
175
|
tk = 1 / np.real(lambda_ma) if isinstance(lambda_ma, complex) else 1 / lambda_ma
|
|
174
176
|
funcs = sp.Matrix([0.5*((A*args - b).T)*(A*args - b)])
|
|
177
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
175
178
|
res = funcs.jacobian(args)
|
|
176
179
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
177
180
|
point, f = [], []
|
|
178
181
|
while 1:
|
|
179
182
|
# reps = dict(zip(args, x_0))
|
|
180
183
|
point.append(x_0)
|
|
181
|
-
f.append(get_value(
|
|
184
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
182
185
|
if verbose:
|
|
183
186
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
184
187
|
grad = res_num(*x_0)
|
|
@@ -187,7 +190,7 @@ def approximate_point(A: NDArray,
|
|
|
187
190
|
k = k + 1
|
|
188
191
|
if np.linalg.norm(x_0 - point[k - 1]) < epsilon:
|
|
189
192
|
point.append(x_0)
|
|
190
|
-
f.append(get_value(
|
|
193
|
+
f.append(get_value(funcs_num, x_0, mu, "L1"))
|
|
191
194
|
if verbose:
|
|
192
195
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
193
196
|
break
|
|
@@ -58,11 +58,12 @@ def grad(funcs: FuncArray,
|
|
|
58
58
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
59
59
|
from .._kernel import set_proxim
|
|
60
60
|
proximo, f = set_proxim(proxim), []
|
|
61
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
61
62
|
res = funcs.jacobian(args) # gradient
|
|
62
63
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
63
64
|
while 1:
|
|
64
65
|
# reps = dict(zip(args, x_0))
|
|
65
|
-
f.append(get_value(
|
|
66
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
66
67
|
if verbose:
|
|
67
68
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
68
69
|
dk = -res_num(*x_0)
|
|
@@ -58,11 +58,12 @@ def normal(funcs: FuncArray,
|
|
|
58
58
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
59
59
|
from .._kernel import set_proxim
|
|
60
60
|
proximo, point, f = set_proxim(proxim), [], []
|
|
61
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
61
62
|
res = funcs.jacobian(args) # gradient
|
|
62
63
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
63
64
|
while 1:
|
|
64
65
|
point.append(np.array(x_0))
|
|
65
|
-
f.append(get_value(
|
|
66
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
66
67
|
if verbose:
|
|
67
68
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
68
69
|
dk = -res_num(*x_0)
|
|
@@ -110,12 +111,13 @@ def variant(funcs: FuncArray,
|
|
|
110
111
|
from .._kernel import set_proxim
|
|
111
112
|
from .._drive import gammak
|
|
112
113
|
proximo, point, f = set_proxim(proxim), [], []
|
|
114
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
113
115
|
res = funcs.jacobian(args) # gradient
|
|
114
116
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
115
117
|
vkx = lambda k: x_0 if k == 0 else point[k-1] + (x_0 - point[k-1]) / gk
|
|
116
118
|
while 1:
|
|
117
119
|
point.append(np.array(x_0))
|
|
118
|
-
f.append(get_value(
|
|
120
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
119
121
|
if verbose:
|
|
120
122
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
121
123
|
dk = -res_num(*x_0)
|
|
@@ -164,12 +166,13 @@ def decline(funcs: FuncArray,
|
|
|
164
166
|
from .._kernel import set_proxim
|
|
165
167
|
from .._drive import gammak
|
|
166
168
|
proximo, point, f = set_proxim(proxim), [], []
|
|
169
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
167
170
|
res = funcs.jacobian(args) # gradient
|
|
168
171
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
169
172
|
vkx = lambda k: x_0 if k == 0 else point[k-1] + (x_0 - point[k-1]) / gk
|
|
170
173
|
while 1:
|
|
171
174
|
point.append(np.array(x_0))
|
|
172
|
-
f.append(get_value(
|
|
175
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
173
176
|
if verbose:
|
|
174
177
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
175
178
|
dk = -res_num(*x_0)
|
|
@@ -179,7 +182,7 @@ def decline(funcs: FuncArray,
|
|
|
179
182
|
dky = -res_num(*yk)
|
|
180
183
|
delta = yk + tk * dky[0]
|
|
181
184
|
u = proximo(delta, mu, tk)
|
|
182
|
-
phiu = get_value(
|
|
185
|
+
phiu = get_value(funcs_num, u, mu, proxim)
|
|
183
186
|
x_0 = u if phiu <= f[-1] else x_0
|
|
184
187
|
k += 1
|
|
185
188
|
else:
|
|
@@ -59,10 +59,11 @@ def seckin(funcs: FuncArray,
|
|
|
59
59
|
from .._kernel import set_proxim
|
|
60
60
|
from .._drive import gammak
|
|
61
61
|
proximo, f = set_proxim(proxim), []
|
|
62
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
62
63
|
res, yk = funcs.jacobian(args), x_0 # gradient
|
|
63
64
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
64
65
|
while 1:
|
|
65
|
-
f.append(get_value(
|
|
66
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
66
67
|
if verbose:
|
|
67
68
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
68
69
|
dk = -res_num(*x_0)
|
|
@@ -115,10 +116,11 @@ def accer(funcs: FuncArray,
|
|
|
115
116
|
from .._kernel import set_proxim
|
|
116
117
|
from .._drive import gammak
|
|
117
118
|
proximo, f = set_proxim(proxim), []
|
|
119
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
118
120
|
res, yk = funcs.jacobian(args), x_0 # gradient
|
|
119
121
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
120
122
|
while 1:
|
|
121
|
-
f.append(get_value(
|
|
123
|
+
f.append(get_value(funcs_num, x_0, mu, proxim))
|
|
122
124
|
if verbose:
|
|
123
125
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
124
126
|
dk = -res_num(*x_0)
|
|
@@ -48,13 +48,14 @@ def solve(funcs: FuncArray,
|
|
|
48
48
|
'''
|
|
49
49
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
50
50
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
51
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
51
52
|
res = funcs.jacobian(args) # gradient
|
|
52
53
|
m = sp.symbols("m")
|
|
53
54
|
arg, f = sp.Matrix([m]), []
|
|
54
55
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
55
56
|
while 1:
|
|
56
57
|
# reps = dict(zip(args, x_0))
|
|
57
|
-
f.append(get_value(
|
|
58
|
+
f.append(get_value(funcs_num, x_0))
|
|
58
59
|
if verbose:
|
|
59
60
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
60
61
|
dk = -res_num(*x_0)
|
|
@@ -96,17 +97,18 @@ def steepest(funcs: FuncArray,
|
|
|
96
97
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
97
98
|
from .._kernel import linear_search
|
|
98
99
|
search, f = linear_search(method), []
|
|
100
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
99
101
|
res = funcs.jacobian(args) # gradient
|
|
100
102
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
101
103
|
while 1:
|
|
102
104
|
# reps = dict(zip(args, x_0))
|
|
103
|
-
f.append(get_value(
|
|
105
|
+
f.append(get_value(funcs_num, x_0))
|
|
104
106
|
if verbose:
|
|
105
107
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
106
108
|
dk = -res_num(*x_0)
|
|
107
109
|
# dk = -np.array(res.subs(reps)).astype(DataType)
|
|
108
110
|
if np.linalg.norm(dk) >= epsilon:
|
|
109
|
-
alpha = search(
|
|
111
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
110
112
|
x_0 += alpha * dk[0]
|
|
111
113
|
k += 1
|
|
112
114
|
else:
|
|
@@ -157,25 +159,26 @@ def barzilar_borwein(funcs: FuncArray,
|
|
|
157
159
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
158
160
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
159
161
|
from .._kernel import nonmonotonic_search
|
|
162
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
160
163
|
search, constant = nonmonotonic_search(method, M, eta)
|
|
161
164
|
res, point, f = funcs.jacobian(args), [], []
|
|
162
165
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
163
166
|
while 1: # while k < max_iters when constraint optimization
|
|
164
167
|
point.append(x_0)
|
|
165
168
|
# reps = dict(zip(args, x_0))
|
|
166
|
-
f.append(get_value(
|
|
169
|
+
f.append(get_value(funcs_num, x_0))
|
|
167
170
|
if verbose:
|
|
168
171
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
169
172
|
dk = -res_num(*x_0)
|
|
170
173
|
# dk = -np.array(res.subs(reps)).astype(DataType)
|
|
171
174
|
if np.linalg.norm(dk) >= epsilon:
|
|
172
|
-
alpha = search(
|
|
175
|
+
alpha = search(funcs_num, x_0, dk, k, point, c1, beta, alpha, constant)
|
|
173
176
|
delta = alpha * dk[0]
|
|
174
177
|
x_0 = x_0 + delta
|
|
175
178
|
yk = res_num(*x_0) + dk
|
|
176
179
|
alpha_up = delta.dot(delta.T)
|
|
177
180
|
alpha_down = (delta.dot(yk.T))[0]
|
|
178
|
-
if alpha_down
|
|
181
|
+
if alpha_down > 0:
|
|
179
182
|
alpha = alpha_up / alpha_down
|
|
180
183
|
k += 1
|
|
181
184
|
else:
|
|
@@ -48,13 +48,14 @@ def classic(funcs: FuncArray,
|
|
|
48
48
|
'''
|
|
49
49
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
50
50
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
51
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
51
52
|
res = funcs.jacobian(args) # gradient
|
|
52
53
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
53
|
-
hes, f =
|
|
54
|
+
hes, f = sp.hessian(funcs, args), []
|
|
54
55
|
hes_num = sp.lambdify(args, hes, modules='numpy')
|
|
55
56
|
while 1:
|
|
56
57
|
# reps = dict(zip(args, x_0))
|
|
57
|
-
f.append(get_value(
|
|
58
|
+
f.append(get_value(funcs_num, x_0))
|
|
58
59
|
if verbose:
|
|
59
60
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
60
61
|
gradient = res_num(*x_0)
|
|
@@ -95,14 +96,15 @@ def modified(funcs: FuncArray,
|
|
|
95
96
|
from .._kernel import linear_search
|
|
96
97
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
97
98
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
99
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
98
100
|
search, f = linear_search(method), []
|
|
99
101
|
res = funcs.jacobian(args) # graident
|
|
100
102
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
101
|
-
hes =
|
|
103
|
+
hes = sp.hessian(funcs, args) # hessian
|
|
102
104
|
hes_num = sp.lambdify(args, hes, modules='numpy')
|
|
103
105
|
while 1:
|
|
104
106
|
# reps = dict(zip(args, x_0))
|
|
105
|
-
f.append(get_value(
|
|
107
|
+
f.append(get_value(funcs_num, x_0))
|
|
106
108
|
if verbose:
|
|
107
109
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
108
110
|
gradient = res_num(*x_0)
|
|
@@ -112,7 +114,7 @@ def modified(funcs: FuncArray,
|
|
|
112
114
|
hessian = h2h(hessian)
|
|
113
115
|
dk = -np.linalg.inv(hessian).dot(gradient.T).reshape(1, -1)
|
|
114
116
|
if np.linalg.norm(dk) >= epsilon:
|
|
115
|
-
alpha = search(
|
|
117
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
116
118
|
x_0 += alpha * dk[0]
|
|
117
119
|
k += 1
|
|
118
120
|
else:
|
|
@@ -148,14 +150,15 @@ def CG(funcs: FuncArray,
|
|
|
148
150
|
from .._kernel import linear_search
|
|
149
151
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
150
152
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
153
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
151
154
|
search, f = linear_search(method), []
|
|
152
155
|
res = funcs.jacobian(args) # gradient
|
|
153
156
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
154
|
-
hes, dk0 =
|
|
157
|
+
hes, dk0 = sp.hessian(funcs, args), np.zeros((args.shape[0], 1)) # hessian and initial dk
|
|
155
158
|
hes_num = sp.lambdify(args, hes, modules='numpy')
|
|
156
159
|
while 1: # while k < max_iters when constraint optimization
|
|
157
160
|
# reps = dict(zip(args, x_0))
|
|
158
|
-
f.append(get_value(
|
|
161
|
+
f.append(get_value(funcs_num, x_0))
|
|
159
162
|
if verbose:
|
|
160
163
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
161
164
|
gradient = res_num(*x_0)
|
|
@@ -164,7 +167,7 @@ def CG(funcs: FuncArray,
|
|
|
164
167
|
hessian = hes_num(*x_0)
|
|
165
168
|
dk = conjugate(hessian, -gradient, dk0, eps).reshape(1, -1)
|
|
166
169
|
if np.linalg.norm(dk) >= epsilon:
|
|
167
|
-
alpha = search(
|
|
170
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
168
171
|
x_0 += alpha * dk[0]
|
|
169
172
|
k += 1
|
|
170
173
|
else:
|
|
@@ -51,24 +51,25 @@ def bfgs(funcs: FuncArray,
|
|
|
51
51
|
from .._kernel import linear_search
|
|
52
52
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
53
53
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
54
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
54
55
|
search, f = linear_search(method), []
|
|
55
56
|
res = funcs.jacobian(args)
|
|
56
57
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
57
|
-
hes =
|
|
58
|
+
hes = sp.hessian(funcs, args)
|
|
58
59
|
hes_num = sp.lambdify(args, hes, modules='numpy')
|
|
59
60
|
hessian = hes_num(*x_0)
|
|
60
61
|
# hessian = np.array(hes.subs(dict(zip(args, x_0)))).astype(DataType)
|
|
61
62
|
hessian = h2h(hessian)
|
|
62
63
|
while 1: # while k < max_iters when constraint optimization
|
|
63
64
|
# reps = dict(zip(args, x_0))
|
|
64
|
-
f.append(get_value(
|
|
65
|
+
f.append(get_value(funcs_num, x_0))
|
|
65
66
|
if verbose:
|
|
66
67
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
67
68
|
gradient = res_num(*x_0)
|
|
68
69
|
# gradient = np.array(res.subs(reps)).astype(DataType)
|
|
69
70
|
dk = -np.linalg.inv(hessian).dot(gradient.T).reshape(1, -1)
|
|
70
71
|
if np.linalg.norm(dk) >= epsilon:
|
|
71
|
-
alpha = search(
|
|
72
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
72
73
|
delta = alpha * dk # sk
|
|
73
74
|
x_0 += delta[0]
|
|
74
75
|
yk = res_num(*x_0) - gradient
|
|
@@ -106,10 +107,11 @@ def dfp(funcs: FuncArray,
|
|
|
106
107
|
from .._kernel import linear_search
|
|
107
108
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
108
109
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
110
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
109
111
|
search, f = linear_search(method), []
|
|
110
112
|
res = funcs.jacobian(args)
|
|
111
113
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
112
|
-
hes =
|
|
114
|
+
hes = sp.hessian(funcs, args)
|
|
113
115
|
hes_num = sp.lambdify(args, hes, modules='numpy')
|
|
114
116
|
hessian = hes_num(*x_0)
|
|
115
117
|
# hessian = np.array(hes.subs(dict(zip(args, x_0)))).astype(DataType)
|
|
@@ -117,13 +119,13 @@ def dfp(funcs: FuncArray,
|
|
|
117
119
|
hessiani = np.linalg.inv(hessian)
|
|
118
120
|
while 1:
|
|
119
121
|
# reps = dict(zip(args, x_0))
|
|
120
|
-
f.append(get_value(
|
|
122
|
+
f.append(get_value(funcs_num, x_0))
|
|
121
123
|
if verbose:
|
|
122
124
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
123
125
|
gradient = res_num(*x_0)
|
|
124
126
|
dk = -hessiani.dot(gradient.T).reshape(1, -1)
|
|
125
127
|
if np.linalg.norm(dk) >= epsilon:
|
|
126
|
-
alpha = search(
|
|
128
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
127
129
|
delta = alpha * dk # sk
|
|
128
130
|
x_0 += delta[0]
|
|
129
131
|
yk = res_num(*x_0) - gradient
|
|
@@ -165,17 +167,18 @@ def L_BFGS(funcs: FuncArray,
|
|
|
165
167
|
from .._kernel import linear_search
|
|
166
168
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
167
169
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
170
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
168
171
|
search = linear_search(method)
|
|
169
172
|
res = funcs.jacobian(args)
|
|
170
173
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
171
|
-
hes =
|
|
174
|
+
hes = sp.hessian(funcs, args)
|
|
172
175
|
l = hes.shape[0]
|
|
173
176
|
f, s, y, p = [], [], [], []
|
|
174
177
|
gamma = []
|
|
175
178
|
gamma.append(1)
|
|
176
179
|
while 1:
|
|
177
180
|
# reps = dict(zip(args, x_0))
|
|
178
|
-
f.append(get_value(
|
|
181
|
+
f.append(get_value(funcs_num, x_0))
|
|
179
182
|
if verbose:
|
|
180
183
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
181
184
|
Hkm = gamma[k] * np.identity(l)
|
|
@@ -183,7 +186,7 @@ def L_BFGS(funcs: FuncArray,
|
|
|
183
186
|
# grad = np.array(res.subs(reps)).astype(DataType)
|
|
184
187
|
dk = -double_loop(grad, p, s, y, m, k, Hkm).reshape(1, -1)
|
|
185
188
|
if np.linalg.norm(dk) >= epsilon:
|
|
186
|
-
alphak = search(
|
|
189
|
+
alphak = search(funcs_num, res_num, x_0, dk)
|
|
187
190
|
delta = alphak * dk # sk
|
|
188
191
|
x_0 += delta[0]
|
|
189
192
|
if k > m:
|
|
@@ -53,14 +53,16 @@ def gauss_newton(funcr: FuncArray,
|
|
|
53
53
|
assert funcr.shape[0] > 1 and funcr.shape[1] ==1 and args.shape[0] == len(x_0)
|
|
54
54
|
search, f = linear_search(method), []
|
|
55
55
|
resr, funcs = funcr.jacobian(args), sp.Matrix([(1/2)*funcr.T*funcr])
|
|
56
|
+
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
56
57
|
funcr_num = sp.lambdify(args, funcr, modules='numpy')
|
|
57
58
|
res = funcs.jacobian(args)
|
|
59
|
+
res_num = sp.lambdify(args, res, modules='numpy')
|
|
58
60
|
resr_num = sp.lambdify(args, resr, modules='numpy')
|
|
59
61
|
while 1:
|
|
60
62
|
# reps = dict(zip(args, x_0))
|
|
61
63
|
rk = funcr_num(*x_0)
|
|
62
64
|
# rk = np.array(funcr.subs(reps)).astype(DataType)
|
|
63
|
-
f.append(get_value(
|
|
65
|
+
f.append(get_value(funcs_num, x_0))
|
|
64
66
|
if verbose:
|
|
65
67
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
66
68
|
jk = resr_num(*x_0)
|
|
@@ -68,7 +70,7 @@ def gauss_newton(funcr: FuncArray,
|
|
|
68
70
|
q, r = np.linalg.qr(jk)
|
|
69
71
|
dk = np.linalg.inv(r).dot(-(q.T).dot(rk)).reshape(1,-1) # operate with x_0
|
|
70
72
|
if np.linalg.norm(dk) > epsilon:
|
|
71
|
-
alpha = search(
|
|
73
|
+
alpha = search(funcs_num, res_num, x_0, dk)
|
|
72
74
|
x_0 += alpha * dk[0]
|
|
73
75
|
k += 1
|
|
74
76
|
else:
|
|
@@ -121,7 +123,7 @@ def levenberg_marquardt(funcr: FuncArray,
|
|
|
121
123
|
assert funcr.shape[0] > 1 and funcr.shape[1] ==1 and args.shape[0] == len(x_0)
|
|
122
124
|
res, funcs = funcr.jacobian(args), sp.Matrix([(1/2)*funcr.T*funcr])
|
|
123
125
|
resf = funcs.jacobian(args)
|
|
124
|
-
hess, dk0, f =
|
|
126
|
+
hess, dk0, f = sp.hessian(funcs, args), np.zeros((args.shape[0], 1)), []
|
|
125
127
|
funcr_num = sp.lambdify(args, funcr, modules='numpy')
|
|
126
128
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
127
129
|
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
@@ -131,7 +133,7 @@ def levenberg_marquardt(funcr: FuncArray,
|
|
|
131
133
|
# reps = dict(zip(args, x_0))
|
|
132
134
|
rk = funcr_num(*x_0)
|
|
133
135
|
# rk = np.array(funcr.subs(reps)).astype(DataType)
|
|
134
|
-
f.append(get_value(
|
|
136
|
+
f.append(get_value(funcs_num, x_0))
|
|
135
137
|
if verbose:
|
|
136
138
|
print("{}\t{}\t{}".format(x_0, f[-1], k))
|
|
137
139
|
jk = res_num(*x_0)
|
|
@@ -73,7 +73,7 @@ def steihaug_CG(funcs: FuncArray,
|
|
|
73
73
|
funcs, args, x_0 = f2m(funcs), a2m(args), p2t(x_0)
|
|
74
74
|
assert all(funcs.shape) == 1 and args.shape[0] == len(x_0)
|
|
75
75
|
res = funcs.jacobian(args)
|
|
76
|
-
hes =
|
|
76
|
+
hes = sp.hessian(funcs, args)
|
|
77
77
|
s0, f = [0 for _ in range(args.shape[0])], []
|
|
78
78
|
funcs_num = sp.lambdify(args, funcs, modules='numpy')
|
|
79
79
|
res_num = sp.lambdify(args, res, modules='numpy')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: optimtool
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.1
|
|
4
4
|
Summary: The fundamental package for scientific research in optimization.
|
|
5
5
|
Home-page: https://github.com/linjing-lab/optimtool
|
|
6
6
|
Download-URL: https://github.com/linjing-lab/optimtool/tags
|
|
@@ -52,12 +52,22 @@ License-File: LICENSE
|
|
|
52
52
|
|
|
53
53
|
## 项目介绍
|
|
54
54
|
|
|
55
|
-
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合Python
|
|
55
|
+
  optimtool采用了北京大学出版的《最优化:建模、算法与理论》这本书中的部分理论方法框架,运用了`Numpy`包高效处理数组间运算等的特性,巧妙地应用了`Sympy`内部支持的jacobian等方法,并结合sp.lambdify实现了高效地数值矩阵的运算,最终设计的用在最优化科学研究的Python工具包。
|
|
56
56
|
|
|
57
57
|
如果你在研究中使用 **optimtool**,欢迎引用它在你的参考资料中(按照下面的格式)。
|
|
58
58
|
|
|
59
|
-
```
|
|
60
|
-
|
|
59
|
+
```bibtex
|
|
60
|
+
@software{Lin2021optimtool,
|
|
61
|
+
author = {Lin, Jing},
|
|
62
|
+
title = {optimtool: The fundamental package for scientific research in optimization.},
|
|
63
|
+
year = {2021},
|
|
64
|
+
version = {2.9.1},
|
|
65
|
+
publisher = {PyPI},
|
|
66
|
+
organization = {linjing-lab},
|
|
67
|
+
url = {https://pypi.org/project/optimtool/},
|
|
68
|
+
license = {MIT},
|
|
69
|
+
note = {Source code available at \url{https://github.com/linjing-lab/optimtool}},
|
|
70
|
+
}
|
|
61
71
|
```
|
|
62
72
|
|
|
63
73
|
下载最新版:
|
|
@@ -4,7 +4,7 @@ import sys
|
|
|
4
4
|
from setuptools import setup
|
|
5
5
|
|
|
6
6
|
if sys.version_info < (3, 7, 0):
|
|
7
|
-
raise OSError(f'optimtool-2.
|
|
7
|
+
raise OSError(f'optimtool-2.9.1 requires Python >=3.7, but yours is {sys.version}')
|
|
8
8
|
|
|
9
9
|
if (3, 7, 0) <= sys.version_info < (3, 8, 0):
|
|
10
10
|
# https://github.com/pypa/setuptools/issues/926#issuecomment-294369342
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|