Commit cd7dfa8c authored by Martin Reinecke's avatar Martin Reinecke

explicitly disallow in-place operations on Fields and MultiFields

parent 0be9da82
......@@ -141,9 +141,7 @@ class RGSpace(StructuredDomain):
@staticmethod
def _kernel(x, sigma):
from ..sugar import exp
tmp = x*x
tmp *= -2.*np.pi*np.pi*sigma*sigma
return exp(tmp)
return exp(x*x * (-2.*np.pi*np.pi*sigma*sigma))
def get_fft_smoothing_kernel_function(self, sigma):
if (not self.harmonic):
......
......@@ -31,7 +31,7 @@ def _get_acceptable_model(M):
raise ValueError('Initial Model value must be finite')
dir = from_random("normal", M.position.domain)
dirder = M.jacobian(dir)
dir *= val/(dirder).norm()*1e-5
dir = dir * val * (1e-5/dirder.norm())
# Find a step length that leads to a "reasonable" Model
for i in range(50):
try:
......@@ -40,7 +40,7 @@ def _get_acceptable_model(M):
break
except FloatingPointError:
pass
dir *= 0.5
dir = dir*0.5
else:
raise ValueError("could not find a reasonable initial step")
return M2
......@@ -52,7 +52,7 @@ def _get_acceptable_energy(E):
raise ValueError('Initial Energy must be finite')
dir = from_random("normal", E.position.domain)
dirder = E.gradient.vdot(dir)
dir *= np.abs(val)/np.abs(dirder)*1e-5
dir = dir * (np.abs(val)/np.abs(dirder)*1e-5)
# Find a step length that leads to a "reasonable" energy
for i in range(50):
try:
......@@ -61,7 +61,7 @@ def _get_acceptable_energy(E):
break
except FloatingPointError:
pass
dir *= 0.5
dir = dir*0.5
else:
raise ValueError("could not find a reasonable initial step")
return E2
......@@ -92,7 +92,7 @@ def check_value_gradient_consistency(E, tol=1e-8, ntries=100):
xtol = tol*Emid.gradient_norm
if abs(numgrad-dirder) < xtol:
break
dir *= 0.5
dir = dir*0.5
dirnorm *= 0.5
E2 = Emid
else:
......@@ -117,7 +117,7 @@ def check_value_gradient_metric_consistency(E, tol=1e-8, ntries=100):
if abs((E2.value-val)/dirnorm - dirder) < xtol and \
(abs((E2.gradient-E.gradient)/dirnorm-dgrad) < xtol).all():
break
dir *= 0.5
dir = dir*0.5
dirnorm *= 0.5
E2 = Emid
else:
......
......@@ -670,3 +670,12 @@ for op in ["__add__", "__radd__",
return NotImplemented
return func2
setattr(Field, op, func(op))
for op in ["__iadd__", "__isub__", "__imul__", "__idiv__",
"__itruediv__", "__ifloordiv__", "__ipow__"]:
def func(op):
def func2(self, other):
raise TypeError(
"In-place operations are deliberately not supported")
return func2
setattr(Field, op, func(op))
......@@ -84,8 +84,7 @@ class ConjugateGradient(Minimizer):
logger.error("Error: ConjugateGradient: alpha<0.")
return energy, controller.ERROR
q *= -alpha
r = r + q
r = r - q*alpha
energy = energy.at_with_grad(energy.position - alpha*d, r)
......@@ -103,7 +102,6 @@ class ConjugateGradient(Minimizer):
if status != controller.CONTINUE:
return energy, status
d *= max(0, gamma/previous_gamma)
d += s
d = d * max(0, gamma/previous_gamma) + s
previous_gamma = gamma
......@@ -61,16 +61,16 @@ class L_BFGS(DescentMinimizer):
for i in range(k-1, k-nhist-1, -1):
idx = i % maxhist
alpha[idx] = s[idx].vdot(p)/s[idx].vdot(y[idx])
p -= alpha[idx]*y[idx]
p = p - alpha[idx]*y[idx]
idx = (k-1) % maxhist
fact = s[idx].vdot(y[idx]) / y[idx].vdot(y[idx])
if fact <= 0.:
logger.error("L-BFGS curvature not positive definite!")
p *= fact
p = p*fact
for i in range(k-nhist, k):
idx = i % maxhist
beta = y[idx].vdot(p) / s[idx].vdot(y[idx])
p += (alpha[idx]-beta)*s[idx]
p = p + (alpha[idx]-beta)*s[idx]
self._lastx = x
self._lastgrad = gradient
self._k += 1
......
......@@ -67,7 +67,7 @@ class VL_BFGS(DescentMinimizer):
descent_direction = delta[0] * b[0]
for i in range(1, len(delta)):
descent_direction += delta[i] * b[i]
descent_direction = descent_direction + delta[i]*b[i]
return descent_direction
......
......@@ -220,3 +220,12 @@ for op in ["__add__", "__radd__",
return MultiField(result_val)
return func2
setattr(MultiField, op, func(op))
for op in ["__iadd__", "__isub__", "__imul__", "__idiv__",
"__itruediv__", "__ifloordiv__", "__ipow__"]:
def func(op):
def func2(self, other):
raise TypeError(
"In-place operations are deliberately not supported")
return func2
setattr(MultiField, op, func(op))
......@@ -185,7 +185,6 @@ class DiagonalOperator(EndomorphicOperator):
res = Field.from_random(random_type="normal", domain=self._domain,
dtype=dtype)
if from_inverse:
res /= np.sqrt(self._ldiag)
return res/np.sqrt(self._ldiag)
else:
res *= np.sqrt(self._ldiag)
return res
return res*np.sqrt(self._ldiag)
......@@ -118,10 +118,7 @@ class FFTOperator(LinearOperator):
fct = self._domain[self._space].scalar_dvol
else:
fct = self._target[self._space].scalar_dvol
if fct != 1:
Tval *= fct
return Tval
return Tval if fct == 1 else Tval*fct
@property
def domain(self):
......
......@@ -172,14 +172,15 @@ class SumOperator(LinearOperator):
def apply(self, x, mode):
self._check_mode(mode)
for i, op in enumerate(self._ops):
if i == 0:
res = -op.apply(x, mode) if self._neg[i] else op.apply(x, mode)
res = None
for op, neg in zip(self._ops, self._neg):
if res is None:
res = -op.apply(x, mode) if neg else op.apply(x, mode)
else:
if self._neg[i]:
res -= op.apply(x, mode)
if neg:
res = res - op.apply(x, mode)
else:
res += op.apply(x, mode)
res = res + op.apply(x, mode)
return res
def draw_sample(self, from_inverse=False, dtype=np.float64):
......
......@@ -31,9 +31,9 @@ class StatCalculator(object):
self._M2 = 0.*value
else:
delta = value - self._mean
self._mean += delta*(1./self._count)
self._mean = self.mean + delta*(1./self._count)
delta2 = value - self._mean
self._M2 += delta*delta2
self._M2 = self._M2 + delta*delta2
@property
def mean(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment