CH82 – optimization

Input: Defines the model and constraints

from dcprogs import read_idealized_bursts
from dcprogs.likelihood import QMatrix

name   = "CH82.scn"
tau    = 1e-4
tcrit  = 4e-3
graph  = [["V", "V", "V",   0,   0],
          ["V", "V",   0, "V",   0],
          ["V",   0, "V", "V", "V"],
          [  0, "V", "V", "V",   0],
          [  0,   0, "V",   0, "V"]]
nopen  = 2
qmatrix = QMatrix([[ -3050,        50,  3000,      0,    0 ],
                  [ 2./3., -1502./3.,     0,    500,    0 ],
                  [    15,         0, -2065,     50, 2000 ],
                  [     0,     15000,  4000, -19000,    0 ],
                  [     0,         0,    10,      0,  -10 ] ], 2)

bursts = read_idealized_bursts(name, tau=tau, tcrit=tcrit)

Creates the constraints, the likelihood function, as well as a function to create random Q-matrix.

from scipy.optimize import minimize
from numpy import NaN, zeros, arange
import numpy as np
from dcprogs.likelihood.random import qmatrix as random_qmatrix
from dcprogs.likelihood import QMatrix, Log10Likelihood
from dcprogs.likelihood.optimization import reduce_likelihood

likelihood = Log10Likelihood(bursts, nopen, tau, tcrit)
reduced = reduce_likelihood(likelihood, graph)
x = reduced.to_reduced_coords( random_qmatrix(5).matrix )

constraints = []
def create_inequality_constraints(i, value=0e0, sign=1e0):
    f = lambda x: sign * (x[i]  - value)
    def df(x):
        a = zeros(x.shape)
        a[i] = sign
        return a
    return f, df

for i in range(len(x)):
    f, df = create_inequality_constraints(i)
    constraints.append({'type': 'ineq', 'fun': f, 'jac': df})
    f, df = create_inequality_constraints(i, 1e4, -1)
    constraints.append({'type': 'ineq', 'fun': f, 'jac': df})


def random_starting_point():
    from numpy import infty, NaN
    from dcprogs.likelihood.random import rate_matrix as random_rate_matrix


    for i in range(100):
        matrix = random_rate_matrix(N=len(qmatrix.matrix), zeroprob=0)
        x = reduced.to_reduced_coords( matrix )
        try:
            result = reduced(x)
            print(result, reduced.to_full_coords(x))
        except:
            pass
        else:
            if result != NaN and result != infty and result != -infty: break
    else: raise RuntimeError("Could not create random matrix")
    return x

def does_not_throw(x):
    try: return -reduced(x)
    except: return NaN

Performs the minimization

import math
methods = ['COBYLA', 'SLSQP']
x = random_starting_point()
print ('x=', x)
maxx = (x.copy(), reduced(x))
for i in range(len(methods)):
    result = minimize(does_not_throw,
                      x,
                      method=methods[i],
                      constraints=constraints,
                      options={'maxiter': 1000, 'disp':True})

    print(result)
    if not math.isnan(result.fun):
        if result.fun < maxx[1]: maxx = (x.copy(), result.fun)
        if result.success and i > 4: break
    x +=  random_starting_point() * 1e-2
    if np.all(np.isnan(x)): x = random_starting_point()
print(maxx[0])
print(maxx[1])
-795.0079187129502 [[ -7.31733927e-01   5.73608232e-01   1.58125695e-01   0.00000000e+00
    0.00000000e+00]
 [  5.13099956e+03  -5.13147159e+03   0.00000000e+00   4.72028553e-01
    0.00000000e+00]
 [  5.34657910e-01   0.00000000e+00  -4.57912950e+03   2.82462703e+02
    4.29613214e+03]
 [  0.00000000e+00   8.45220269e-01   2.92597166e-02  -8.74479986e-01
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   1.57421312e-01   0.00000000e+00
   -1.57421312e-01]]
x= [  5.73608232e-01   1.58125695e-01   5.13099956e+03   4.72028553e-01
   5.34657910e-01   2.82462703e+02   4.29613214e+03   8.45220269e-01
   2.92597166e-02   1.57421312e-01]
     fun: -2150.8720254173086
   maxcv: 5.1878344877524985e-16
 message: 'Maximum number of function evaluations has been exceeded.'
    nfev: 1000
  status: 2
 success: False
       x: array([  3.01358997e+00,   1.89327366e+02,   5.12972462e+03,
         2.44890905e+01,   8.00417955e+02,   2.37558925e+02,
         4.24260764e+03,  -5.18783449e-16,   3.93011670e+01,
         1.32532752e+01])
-2231.1152175140232 [[ -1.11438201e+00   8.32376148e-01   2.82005864e-01   0.00000000e+00
    0.00000000e+00]
 [  4.43631622e-01  -1.20756270e+00   0.00000000e+00   7.63931076e-01
    0.00000000e+00]
 [  9.51457047e-01   0.00000000e+00  -1.29672622e+03   1.29508725e+03
    6.87511017e-01]
 [  0.00000000e+00   7.89527185e+03   9.51068931e-01  -7.89622292e+03
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   7.13307027e+03   0.00000000e+00
   -7.13307027e+03]]
Iteration limit exceeded    (Exit mode 9)
            Current function value: nan
            Iterations: 1001
            Function evaluations: 21639
            Gradient evaluations: 1001
     fun: nan
     jac: array([ nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,   0.])
 message: 'Iteration limit exceeded'
    nfev: 21639
     nit: 1001
    njev: 1001
  status: 9
 success: False
       x: array([ nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan])
-11800.651476936484 [[ -8.76004244e+03   2.96504216e-01   8.75974593e+03   0.00000000e+00
    0.00000000e+00]
 [  7.01352194e+03  -7.01410216e+03   0.00000000e+00   5.80220290e-01
    0.00000000e+00]
 [  6.83310821e-01   0.00000000e+00  -1.59395396e+00   6.06206268e-01
    3.04436871e-01]
 [  0.00000000e+00   2.14009497e-01   8.70868111e-01  -1.08487761e+00
    0.00000000e+00]
 [  0.00000000e+00   0.00000000e+00   3.72315643e+03   0.00000000e+00
   -3.72315643e+03]]
[  5.73608232e-01   1.58125695e-01   5.13099956e+03   4.72028553e-01
   5.34657910e-01   2.82462703e+02   4.29613214e+03   8.45220269e-01
   2.92597166e-02   1.57421312e-01]
-2150.87202542