Skip to content

Commit 33a32fe

Browse files
committed
ispae
1 parent 341d91d commit 33a32fe

File tree

6 files changed

+591
-50
lines changed

6 files changed

+591
-50
lines changed

README.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,26 @@ linear and nonlinear equations, and visualizing solution sets for interval syste
55

66
For details, see the complete documentation on [API](https://intvalpy.readthedocs.io/ru/latest/index.html).
77

8+
9+
Links
10+
-----
11+
12+
* [Article](<https://www.researchgate.net/publication/371587916_IntvalPy_-_a_Python_Interval_Computation_Library>)
13+
14+
* [Patent](<https://elibrary.ru/item.asp?id=69597041>)
15+
16+
* [Homepage](<https://github.com/AndrosovAS/intvalpy>)
17+
18+
* [Online documentation](<https://intvalpy.readthedocs.io/ru/latest/#>)
19+
20+
* [PyPI package](<https://pypi.org/project/intvalpy/>)
21+
22+
* A detailed [monograph](<http://www.nsc.ru/interval/Library/InteBooks/SharyBook.pdf>) on interval theory
23+
24+
825
## Installation
926

10-
Make sure you have all the system-wide dependencies, then install the module itself:
27+
Ensure you have all the system-wide dependencies installed, then install the module using pip:
1128
```
1229
pip install intvalpy
1330
```
@@ -87,11 +104,9 @@ iplt.scatter(x, y, color='gray', alpha=0.7, s=10, axindex=axindex)
87104
```
88105
![SolSet](https://raw.githubusercontent.com/AndrosovAS/intvalpy/master/examples/SolSet.png)
89106

90-
It is also possible to make a three-dimensional (two-dimensional) slice of an N-dimensional figure and see what the set of solutions looks like
91-
with fixed N-3 (N-2) parameters. A specific implementation of the algorithm can be found in the examples.
92-
As a result, a gif image of the united set of solutions of the system proposed by S.P. Sharym is shown below, during the evolution of the 4th unknown.
93107

94-
![Shary4Uni](https://raw.githubusercontent.com/AndrosovAS/intvalpy/master/examples/Shary4Uni.gif)
108+
It is also possible to create a three-dimensional (or two-dimensional) slice of an N-dimensional figure to visualize the solution set
109+
with fixed N-3 (or N-2) parameters. A specific implementation of this algorithm can be found in the examples.
95110

96111
### Recognizing functionals:
97112

@@ -187,15 +202,4 @@ x = ip.Interval([-5]*N, [5]*N)
187202
ip.nonlinear.globopt(levy, x, tol=1e-14)
188203
```
189204

190-
Links
191-
-----
192205

193-
* [Article](<https://www.researchgate.net/publication/371587916_IntvalPy_-_a_Python_Interval_Computation_Library>)
194-
195-
* [Homepage](<https://github.com/AndrosovAS/intvalpy>)
196-
197-
* [Online documentation](<https://intvalpy.readthedocs.io/ru/latest/#>)
198-
199-
* [PyPI package](<https://pypi.org/project/intvalpy/>)
200-
201-
* A detailed [monograph](<http://www.nsc.ru/interval/Library/InteBooks/SharyBook.pdf>) on interval theory

intvalpy/kernel/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#############################################################################################################
1717
from .utils import infinity, nan
1818
from .utils import dist, diag, compmat, isnan
19-
from .utils import wid, mid, rad, inf, sup, mag
19+
from .utils import wid, mid, rad, inf, sup, mag, khi
2020
from .utils import subset, superset, proper_subset, proper_superset, contain, supercontain
2121
#############################################################################################################
2222
from .visualization import IPlot

intvalpy/kernel/ralgb5.py

Lines changed: 138 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,193 @@
11
import numpy as np
22

33
def ralgb5(calcfg, x0, tolx=1e-12, tolg=1e-12, tolf=1e-12, maxiter=2000, alpha=2.3, nsims=30, h0=1, nh=3, q1=0.9, q2=1.1):
4-
5-
m = len(x0)
6-
hs = h0
7-
B = np.eye(m)
8-
vf = np.zeros(nsims) + float('inf')
9-
w = 1./alpha - 1
10-
11-
x = np.copy(x0)
12-
xr = np.copy(x0)
13-
14-
nit = 0
15-
ncalls = 1
16-
fr, g0 = calcfg(xr)
17-
4+
"""
5+
Subgradient method ralgb5 for minimizing convex functions with ravine-like structure.
6+
7+
This function implements the ralgb5 algorithm, which is a subgradient method with adaptive stepsize control
8+
and space dilation. It is particularly effective for minimizing non-smooth convex functions or smooth convex
9+
functions with ravine-like level surfaces.
10+
11+
Parameters:
12+
-----------
13+
calcfg : function
14+
A function that computes the value of the objective function and its subgradient at a given point x.
15+
The function should return a tuple (f, g), where f is the function value and g is the subgradient.
16+
17+
x0 : numpy.ndarray
18+
The initial starting point for the optimization algorithm. It should be a 1D array of length n, where n
19+
is the number of variables.
20+
21+
tolx : float, optional
22+
Tolerance for stopping based on the change in the argument (default is 1e-12). The algorithm stops if
23+
the norm of the change in x between iterations is less than tolx.
24+
25+
tolg : float, optional
26+
Tolerance for stopping based on the norm of the subgradient (default is 1e-12). The algorithm stops if
27+
the norm of the subgradient is less than tolg.
28+
29+
tolf : float, optional
30+
Tolerance for stopping based on the change in the function value (default is 1e-12). The algorithm stops
31+
if the relative change in the function value over the last nsims iterations is less than tolf.
32+
33+
maxiter : int, optional
34+
Maximum number of iterations allowed (default is 2000). The algorithm stops if this number of iterations
35+
is reached.
36+
37+
alpha : float, optional
38+
Space dilation coefficient (default is 2.3). This parameter controls the rate at which the space is
39+
stretched in the direction of the subgradient difference.
40+
41+
nsims : int, optional
42+
Number of iterations to consider for the stopping criterion based on the change in the function value
43+
(default is 30).
44+
45+
h0 : float, optional
46+
Initial step size (default is 1). This is the starting step size for the line search along the
47+
subgradient direction.
48+
49+
nh : int, optional
50+
Number of steps after which the step size is increased (default is 3). The step size is increased by a
51+
factor of q2 every nh steps.
52+
53+
q1 : float, optional
54+
Coefficient for decreasing the step size (default is 0.9). If the line search completes in one step, the
55+
step size is multiplied by q1.
56+
57+
q2 : float, optional
58+
Coefficient for increasing the step size (default is 1.1). The step size is multiplied by q2 every nh
59+
steps.
60+
61+
Returns:
62+
--------
63+
xr : numpy.ndarray
64+
The best approximation to the minimum point found by the algorithm.
65+
66+
fr : float
67+
The value of the objective function at the point xr.
68+
69+
nit : int
70+
The number of iterations performed.
71+
72+
ncalls : int
73+
The number of calls to the calcfg function.
74+
75+
ccode : int
76+
A code indicating the reason for stopping:
77+
- 1: Stopped based on the change in the function value (tolf).
78+
- 2: Stopped based on the norm of the subgradient (tolg).
79+
- 3: Stopped based on the change in the argument (tolx).
80+
- 4: Maximum number of iterations reached (maxiter).
81+
- 5: Emergency stop due to too many steps in the line search.
82+
83+
Notes:
84+
------
85+
The algorithm is based on the r-algorithm proposed by N.Z. Shor, with modifications for adaptive stepsize
86+
control and space dilation. It is particularly effective for minimizing non-smooth convex functions or
87+
smooth convex functions with ravine-like level surfaces.
88+
89+
References:
90+
-----------
91+
[1] Stetsyuk, P.I. (2017). Subgradient methods ralgb5 and ralgb4 for minimization of ravine-like convex functions.
92+
[2] Shor, N.Z. (1979). Minimization Methods for Non-Differentiable Functions. Kiev: Naukova Dumka.
93+
"""
94+
95+
# Initialize variables
96+
m = len(x0) # Number of variables
97+
hs = h0 # Current step size
98+
B = np.eye(m) # Transformation matrix (initially identity)
99+
vf = np.zeros(nsims) + float('inf') # Array to store function values for stopping criterion
100+
w = 1./alpha - 1 # Coefficient for space dilation
101+
102+
x = np.copy(x0) # Current point
103+
xr = np.copy(x0) # Best point found so far
104+
105+
nit = 0 # Iteration counter
106+
ncalls = 1 # Counter for function evaluations
107+
fr, g0 = calcfg(xr) # Initial function value and subgradient
108+
109+
# Check if the initial subgradient is already small enough
18110
if np.linalg.norm(g0) < tolg:
19-
ccode = 2
111+
ccode = 2 # Stopping code: subgradient norm is below tolerance
20112
return xr, fr, nit, ncalls, ccode
21113

114+
# Main optimization loop
22115
while nit <= maxiter:
23-
vf[nsims-1] = fr
116+
vf[nsims-1] = fr # Store the current function value
24117

118+
# Compute the direction of movement in the transformed space
25119
g1 = B.T @ g0
26120
dx = B @ (g1 / np.linalg.norm(g1))
27121
normdx = np.linalg.norm(dx)
28122

29-
d = 1
30-
cal = 0
31-
deltax = 0
123+
d = 1 # Initialize the inner loop condition
124+
cal = 0 # Counter for steps in the line search
125+
deltax = 0 # Accumulated change in x during the line search
32126

127+
# Line search along the subgradient direction
33128
while d > 0 and cal <= 500:
34-
x = x - hs*dx
35-
deltax = deltax + hs * normdx
129+
x = x - hs*dx # Update the current point
130+
deltax = deltax + hs * normdx # Accumulate the change in x
36131

37-
ncalls += 1
38-
f, g1 = calcfg(x)
132+
ncalls += 1 # Increment the function evaluation counter
133+
f, g1 = calcfg(x) # Evaluate the function and subgradient at the new point
39134

135+
# Update the best point found so far
40136
if f < fr:
41137
fr = f
42138
xr = x
43139

140+
# Check if the subgradient norm is below tolerance
44141
if np.linalg.norm(g1) < tolg:
45-
ccode = 2
142+
ccode = 2 # Stopping code: subgradient norm is below tolerance
46143
return xr, fr, nit, ncalls, ccode
47144

145+
# Increase the step size every nh steps
48146
if np.mod(cal, nh) == 0:
49147
hs = hs * q2
148+
149+
# Check the inner loop condition
50150
d = dx @ g1
51151

52-
cal += 1
152+
cal += 1 # Increment the line search step counter
53153

154+
# Emergency stop if too many steps are taken in the line search
54155
if cal > 500:
55-
ccode = 5
156+
ccode = 5 # Stopping code: emergency stop
56157
return xr, fr, nit, ncalls, ccode
57158

159+
# Decrease the step size if the line search completes in one step
58160
if cal == 1:
59161
hs = hs * q1
60162

163+
# Check if the change in x is below tolerance
61164
if deltax < tolx:
62-
ccode = 3
165+
ccode = 3 # Stopping code: change in x is below tolerance
63166
return xr, fr, nit, ncalls, ccode
64167

168+
# Update the transformation matrix B and the subgradient
65169
dg = B.T @ (g1 - g0)
66170
xi = dg / np.linalg.norm(dg)
67-
68171
B = B + w * np.outer((B @ xi), xi)
69172
g0 = g1
70173

174+
# Update the function value history for the stopping criterion
71175
vf = np.roll(vf, 1)
72176
vf[0] = abs(fr - vf[0])
73177

178+
# Compute the relative change in the function value
74179
if abs(fr) > 1:
75180
deltaf = np.sum(vf)/abs(fr)
76181
else:
77182
deltaf = np.sum(vf)
78183

184+
# Check if the relative change in the function value is below tolerance
79185
if deltaf < tolf:
80-
ccode = 1
186+
ccode = 1 # Stopping code: change in function value is below tolerance
81187
return xr, fr, nit, ncalls, ccode
82188

83-
nit += 1
189+
nit += 1 # Increment the iteration counter
84190

85-
ccode=4
191+
# If the maximum number of iterations is reached
192+
ccode = 4 # Stopping code: maximum number of iterations reached
86193
return xr, fr, nit, ncalls, ccode

intvalpy/kernel/real_intervals.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import numpy as np
1+
import numpy as np
22

33
import math
44
from mpmath import mp, mpf
@@ -932,6 +932,53 @@ def SingleInterval(left, right, sortQ=True, midRadQ=False):
932932

933933

934934
def Interval(*args, sortQ=True, midRadQ=False):
935+
'''
936+
Construct an interval or array of intervals from input arguments.
937+
938+
This function creates either SingleInterval or ArrayInterval objects
939+
depending on the input format. It supports multiple input representations
940+
and automatically handles bound ordering.
941+
942+
Parameters:
943+
-----------
944+
*args : variable
945+
Input arguments defining the interval(s). Can be:
946+
- Two numbers (lower, upper bound)
947+
- A single number (degenerate interval)
948+
- A sequence of two numbers [lower, upper]
949+
- An existing interval object
950+
- Array-like inputs for vectorized operations
951+
- Nested sequence for the standard interval vector representation
952+
953+
sortQ : bool, optional
954+
If True (default), automatically sorts bounds to ensure a ≤ b.
955+
If False, preserves original order (may create improper intervals).
956+
957+
midRadQ : bool, optional
958+
If True, interprets inputs as midpoint-radius representation.
959+
If False (default), interprets as lower-upper bounds.
960+
961+
Returns:
962+
--------
963+
Interval object
964+
Returns either:
965+
- SingleInterval for scalar inputs
966+
- ArrayInterval for array-like inputs
967+
968+
Raises:
969+
-------
970+
AssertionError
971+
If more than two main arguments are provided
972+
973+
Examples:
974+
---------
975+
>>> Interval(2, 5) # Single interval [2, 5]
976+
>>> Interval([3, 7]) # Single interval from sequence
977+
>>> Interval(4) # Degenerate interval [4, 4]
978+
>>> Interval([1,2], [3,4]) # Array of intervals [1, 3] and [2, 4]
979+
>>> Interval([[1,3], [2,4]]) # Array of intervals [1, 3] and [3, 4]
980+
>>> Interval(x, y, midRadQ=True) # Midpoint-radius interpretation
981+
'''
935982

936983
n = len(args)
937984
assert n <= 2, "There cannot be more than two main arguments."
@@ -944,6 +991,9 @@ def Interval(*args, sortQ=True, midRadQ=False):
944991
else:
945992
if isinstance(args[0], INTERVAL_CLASSES):
946993
return args[0]
994+
elif len(args[0]) == 2:
995+
if isinstance(args[0][0], single_type) and isinstance(args[0][1], single_type):
996+
return SingleInterval(args[0][0], args[0][1], sortQ=sortQ, midRadQ=midRadQ)
947997
elif isinstance(args[0], single_type):
948998
return SingleInterval(args[0], args[0], sortQ=sortQ, midRadQ=midRadQ)
949999
data = np.array(args[0])

0 commit comments

Comments
 (0)