Skip to content

Commit c6d4c6b

Browse files
committed
add khi wrapper
1 parent 6f6e851 commit c6d4c6b

File tree

4 files changed

+64
-25
lines changed

4 files changed

+64
-25
lines changed

intvalpy/kernel/real_intervals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ def __array_ufunc__(self, *args):
893893

894894

895895
class precision:
896-
extendedPrecisionQ = True
896+
extendedPrecisionQ = False
897897
mp.dps = 36
898898

899899
def dps(_dps):

intvalpy/kernel/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,21 @@ def _mag(x):
176176
return _mag(x)
177177

178178

179+
def khi(x):
180+
def _khi(x):
181+
if isinstance(x, ARITHMETICS):
182+
return x.khi
183+
else:
184+
return 1
185+
186+
if hasattr(x, '__iter__'):
187+
if isinstance(x, INTERVAL_CLASSES):
188+
x = x.data
189+
return np.vectorize(_khi)(x)
190+
else:
191+
return _khi(x)
192+
193+
179194
subset = lambda a, b: np.array(((a.a >= b.a) & (a.b <= b.b)), dtype=np.bool).all()
180195
superset = lambda a, b: subset(b, a)
181196

intvalpy/models/LIGAM.py renamed to intvalpy/models/ISPAE.py

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,23 @@
77
from ..kernel.preprocessing import asinterval
88

99

10-
class LIGAM(object):
10+
class ISPAE(object):
1111

12-
def __init__(self, alpha=0, beta=1):
12+
def __init__(self, alpha=0, beta=1, basis='monom'):
1313
"""
1414
Linear Interval Generalized Additive Model
1515
"""
1616
self.alpha = alpha
1717
self.beta = beta
18+
19+
self.__bases = {
20+
'monom': np.polynomial.polynomial.Polynomial.basis,
21+
'chebyshev': np.polynomial.chebyshev.Chebyshev.basis,
22+
'hermite': np.polynomial.hermite.Hermite.basis,
23+
'laguerre': np.polynomial.laguerre.Laguerre.basis,
24+
'legendre': np.polynomial.legendre.Legendre.basis,
25+
}
26+
self.basis = self.__bases[basis]
1827

1928

2029
def _wrap_norm(self, residual, norm):
@@ -30,26 +39,42 @@ def _wrap_norm(self, residual, norm):
3039
return obj, mcs
3140

3241

33-
def value_of_one_col(self, beta, x):
42+
def value_of_one_col(self, beta, x, deg=None):
3443
"""
44+
if basis is 'monom'
3545
y = beta[0]*x + ... + beta[N-1]*x**(N-2) + beta[N]*x**(N-1)
3646
"""
37-
def _value_of_one_element(inf, sup):
38-
roots = np.roots( np.polyder(beta, m=1) ) # roots of the first deriv
39-
roots = roots[np.isreal(roots)].real # only real roots
40-
roots = roots[(inf <= roots) & (roots <= sup)] # only in interval (bounded)
41-
roots = [inf, sup] + list(roots)
42-
vals = np.array([np.polyval(beta, root) for root in roots])
43-
return Interval(min(vals), max(vals), sortQ=False)
44-
45-
infs, sups = inf(x), sup(x)
46-
# need reverse for np.polyder, np.polyval
47-
# the fictitious zero coefficient is needed for the free term
48-
beta = np.array([0] + list(beta))[::-1]
49-
if hasattr(x, '__iter__'):
50-
res = asinterval([_value_of_one_element(inf, sup) for inf, sup in zip(infs, sups)])
47+
#+-----+-----+-----+-----+-----+
48+
# initialization block
49+
infs, sups = np.array([inf(x)]).flatten(), np.array([sup(x)]).flatten()
50+
beta = np.array([beta]).flatten()
51+
if deg is None:
52+
basis = np.array([self.basis(k) for k in range(1, len(beta)+1)])
5153
else:
52-
res = _value_of_one_element(infs, sups)
54+
deg = np.array([deg]).flatten()
55+
text = 'The length of the array for the degree of the basis polynomial must match the length of the array of beta coefficients.'
56+
assert len(deg) == len(beta), text
57+
basis = np.array([self.basis(d) for d in deg])
58+
59+
#+-----+-----+-----+-----+-----+
60+
poly = beta @ basis
61+
roots = poly.deriv(1).roots().real
62+
63+
vals = np.zeros( (len(infs), 2+len(roots)) , dtype=float)
64+
vals[:, 0] = poly(infs)
65+
vals[:, 1] = poly(sups)
66+
vals[:, 2:] = poly(roots)
67+
68+
dots = np.zeros( (len(infs), 2+len(roots)) , dtype=float)
69+
dots[:, 0] = infs
70+
dots[:, 1] = sups
71+
dots[:, 2:] = roots
72+
masks = (infs[:, np.newaxis] <= dots) & (dots <= sups[:, np.newaxis])
73+
74+
res = asinterval([
75+
Interval(min(val[mask]), max(val[mask]), sortQ=False)
76+
for val, mask in zip(vals, masks)
77+
])
5378
return res
5479

5580

@@ -105,8 +130,8 @@ def _expand_dataframe(self, dataframe):
105130
X_expand = pd.DataFrame()
106131
nit = 0
107132
for k, col in enumerate(self.columns):
108-
for l in range(1, self.order[k]+1):
109-
X_expand[nit] = dataframe[col]**l
133+
for deg in range(1, self.order[k]+1):
134+
X_expand[nit] = self.value_of_one_col(1, dataframe[col], deg=deg) # self.basis(d)(dataframe[col])
110135
nit = nit + 1
111136
return X_expand
112137

@@ -120,7 +145,7 @@ def fit(
120145
weight=None,
121146
objective='Tol',
122147
norm='inf',
123-
constraint=None,
148+
constraint=None,
124149
**kwargs
125150
):
126151
#+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
@@ -131,7 +156,7 @@ def fit(
131156
assert len(order)==m, 'Inconsistent order array sizes and the number of parameters.'
132157
else:
133158
order = np.full(m, order)
134-
self.order = order
159+
self.order = np.array(order)
135160

136161
X_expand = self._expand_dataframe(X_train)
137162
infX, supX = inf(X_expand), sup(X_expand)
@@ -162,7 +187,6 @@ def fit(
162187
#+-----+-----+-----+-----+-----+-----+
163188
if weight is None:
164189
weight = np.ones(n)
165-
# äåëàåì ñãëàæèâàíèå
166190
weight[0] = self.beta * weight[0]*(1 - self.alpha)
167191
for k in range(1, n):
168192
weight[k] = self.beta * (weight[k]*(1 - self.alpha) + self.alpha*weight[k-1])

intvalpy/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from .WILS import WILS
2-
from .LIGAM import LIGAM
2+
from .ISPAE import ISPAE

0 commit comments

Comments
 (0)