I am trying to solve a linear programming problem using IBM's CPLEX Python API. It involves two sets of equality constraints. The code below works fine when we use either one of the two sets of constraints, but fails to find a solution when both sets of constraints are used.
The constraints are:
First constraint: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
Second constraint: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
Objective function: minimize a + c
One solution which meets both sets of constrains is a=1, b=0, c=1.
There is an error in the way I am introducing the two sets of constrains in Cplex Python. My code is below. To check that the code works with either set of constraints by itself comment out on of the sets of constraints.
import cplex
from cplex.exceptions import CplexError
import sys
def populatebynonzero(prob):
my_obj = [1.0, 0.0, 1.0]
my_ub = [1.0] * len(my_obj)
my_lb = [0.0] * len(my_obj)
my_colnames = ["a", "b", "c"]
prob.objective.set_sense(prob.objective.sense.minimize)
prob.variables.add(obj = my_obj, ub = my_ub, lb = my_lb ,names = my_colnames)
# first set of equality constraints: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1]
cols = [0,1,2]
vals = [20.0,20.0,30.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1]
cols = [0,1,2]
vals = [1.0,1.0,1.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
def lpex1():
try:
my_prob = cplex.Cplex()
handle = populatebynonzero(my_prob)
my_prob.solve()
except CplexError, exc:
print exc
return
numrows = my_prob.linear_constraints.get_num()
numcols = my_prob.variables.get_num()
print
# solution.get_status() returns an integer code
print "Solution status = " , my_prob.solution.get_status(), ":",
# the following line prints the corresponding string
print my_prob.solution.status[my_prob.solution.get_status()]
print "Solution value = ", my_prob.solution.get_objective_value()
slack = my_prob.solution.get_linear_slacks()
pi = my_prob.solution.get_dual_values()
x = my_prob.solution.get_values()
dj = my_prob.solution.get_reduced_costs()
for i in range(numrows):
print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])
for j in range(numcols):
print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])
my_prob.write("lpex1.lp")
print x, "SOLUTIONS"
lpex1()
It works if the two sets of constraints are combined into one matrix in the following way, though it would be good to find a solution which does not have to do combining
import cplex
from cplex.exceptions import CplexError
import sys
def populatebynonzero(prob):
my_obj = [1.0, 0.0, 1.0]
my_ub = [1.0] * len(my_obj)
my_lb = [0.0] * len(my_obj)
my_colnames = ["a", "b", "c"]
prob.objective.set_sense(prob.objective.sense.minimize)
prob.variables.add(obj = my_obj, ub = my_ub, lb = my_lb ,names = my_colnames)
#combined constraints
my_rhs = [20.0, 30.0, 1.0, 1.0]
my_rownames = ["c1", "c2", "e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1,2,2,3]
cols = [0,1,2,0,1,2]
vals = [20.0,20.0,30.0,1,1,1]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
"""
# first set of equality constraints: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1]
cols = [0,1,2]
vals = [20.0,20.0,30.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1]
cols = [0,1,2]
vals = [1.0,1.0,1.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
"""
def lpex1():
try:
my_prob = cplex.Cplex()
handle = populatebynonzero(my_prob)
my_prob.solve()
except CplexError, exc:
print exc
return
numrows = my_prob.linear_constraints.get_num()
numcols = my_prob.variables.get_num()
print
# solution.get_status() returns an integer code
print "Solution status = " , my_prob.solution.get_status(), ":",
# the following line prints the corresponding string
print my_prob.solution.status[my_prob.solution.get_status()]
print "Solution value = ", my_prob.solution.get_objective_value()
slack = my_prob.solution.get_linear_slacks()
pi = my_prob.solution.get_dual_values()
x = my_prob.solution.get_values()
dj = my_prob.solution.get_reduced_costs()
for i in range(numrows):
print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])
for j in range(numcols):
print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])
my_prob.write("lpex1.lp")
print x, "SOLUTIONS"
lpex1()
When you are attempting to create the second set of constraints, you are using the wrong indices for the rows:
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1] # <- HERE
cols = [0,1,2]
vals = [1.0,1.0,1.0]
That is, you're using the row indices 0 and 1, which were created for the first set of constraints. Instead, you should do something like the following:
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
cols = [0,1,2]
vals = [1.0,1.0,1.0]
rowindices = list(prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames))
assert len(rowindices) == 2
rows = [rowindices[0], rowindices[0], rowindices[1]]
prob.linear_constraints.set_coefficients(zip(rowindices, cols, vals))
Above, we get the new row indices from the call to prob.linear_constriants.add. With this change, the script works fine.
In addition, it's a good idea to write out the problem in LP format to make sure that it looks correct, like so:
prob.write("model.lp")
Related
I have some code that is mapping data to a matrix... Most of this is all setup so that my problem can be easily reproduced but the only part I need to speed up is what's after the comment # the part I want to speed up
import numpy as np
# config
matrix_height = 100
matrix_width = 200
# fake data
x_data = np.array(range(10000))
y_data = [{i:i for i in range(100)} for t in range(len(x_data))]
# fake mapping
x_to_index = {x: np.random.randint(matrix_width) for x in x_data }
y_to_index = {}
for y_dict in y_data:
for y_key, y_val in y_dict.items():
y_start = np.random.randint(matrix_height-2)
y_to_index[y_key] = (y_start, y_start+2 )
# data that must be stored
total_matrix = np.zeros([matrix_height, matrix_width]).astype(int)
n_matrix = np.zeros([matrix_height, matrix_width]).astype(int)
latest_value = np.zeros([matrix_height, matrix_width]).astype(int)
# the part I want to speed up
for x, y_dict in zip(x_data, y_data):
x_index = x_to_index[x]
for y_key, y_data in y_dict.items():
y_slice = slice(*y_to_index[y_key])
total_matrix[ y_slice, x_index ] += y_data
latest_value[ y_slice, x_index ] = y_data
n_matrix[ y_slice, x_index ] += 1
Again, I'm only concerned with the part below the comment # the part I want to speed up.
I'm not sure how to speed this up but it seems like it should be possible to use a mapping function that can do this all in parallel...
I'm looking for a marked improvement in that last section. Any ideas?
Tailored to number of cores.
For total_matrix, addition is commutative.
For latest_value, apply the split cols in reverse order.
import numpy as np
import time
import multiprocessing as mp
def func(cols, zz, tm, nm, lv, setOrder):
for c in cols:
for t in zz:
tm[slice(*t[0]), c] += t[1]
lv[slice(*t[0]), c] = t[1]
nm[slice(*t[0]), c] += 1
return [tm, nm, lv, setOrder]
if __name__ == '__main__':
mp.freeze_support()
matrix_height = 100
matrix_width = 200
total_range = 10000
x_data = np.array(range(total_range))
y_data = [{i:i for i in range(matrix_height)} for t in range(len(x_data))]
x_to_index = {x: np.random.randint(matrix_width) for x in x_data}
# potential general purpose cols list
#cols = np.random.randint(0, total_range, (1, total_range))[0]
cols = [np.int(x_to_index[k]) for k in x_to_index]
y_to_index = {}
for y_dict in y_data:
for y_key, y_val in y_dict.items():
y_start = np.random.randint(matrix_height-2)
y_to_index[y_key] = (y_start, y_start+2)
# potential general purpose rows list
#rows = [(np.random.randint(matrix_height), np.random.randint(matrix_height)) for x in range(matrix_height)]
rows = [y_to_index[k] for k in y_to_index]
# potential general purpose y data
#y_dat = np.random.randint(0, matrix_height, (1, matrix_height))[0]
y_dat = [i for i in range(matrix_height)]
o_total_matrix = np.zeros([matrix_height, matrix_width]).astype(int)
o_n_matrix = np.zeros([matrix_height, matrix_width]).astype(int)
o_latest_value = np.zeros([matrix_height, matrix_width]).astype(int)
startTime = time.time()
for x, y_dict in zip(x_data, y_data):
x_index = x_to_index[x]
for y_key, y_data in y_dict.items():
y_slice = slice(*y_to_index[y_key])
o_total_matrix[ y_slice, x_index ] += y_data
o_latest_value[ y_slice, x_index ] = y_data
o_n_matrix[ y_slice, x_index ] += 1
print('original time was {0:5.2f} sec'.format(time.time() - startTime))
procs = mp.cpu_count()
i_tm = [np.zeros([matrix_height, matrix_width]).astype(int)] * procs
i_nm = [np.zeros([matrix_height, matrix_width]).astype(int)] * procs
i_lv = [np.zeros([matrix_height, matrix_width]).astype(int)] * procs
zz = list(zip(rows, y_dat))
procs_split = np.array_split(cols, procs)
itup = []
for x in range(procs):
itup.append(((list(procs_split[x])), zz, i_tm[x], i_nm[x], i_lv[x], x))
startTime = time.time()
with mp.Pool(processes=procs) as pool:
ret = pool.starmap(func, itup)
i_total_matrix = ret[0][0]
i_n_matrix = ret[0][1]
for x in range(1, procs):
i_total_matrix = np.add(i_total_matrix, ret[x][0])
i_n_matrix = np.add(i_n_matrix, ret[x][1])
colOrder = [0] * procs
for x in range(procs):
colOrder[x] = (procs-1) - ret[x][3]
i_latest_value = ret[colOrder[0]][2]
for x in range(1, procs):
np.putmask(i_latest_value, i_latest_value == 0, ret[x][2])
print('improved time was {0:5.2f} sec'.format(time.time() - startTime))
comparison = i_total_matrix == o_total_matrix
if not comparison.all():
print('ERROR TOTAL MATRIX')
comparison = i_n_matrix == o_n_matrix
if not comparison.all():
print('ERROR N MATRIX')
comparison = i_latest_value == o_latest_value
if not comparison.all():
print('ERROR LATEST VALUE')
After a trial run, the results showed approx. twice as fast:
original time was 7.12 sec
improved time was 2.29 sec
I am trying to solve a linear programming problem using IBM's Cplex, while calling it from Python.
The problem is to minimize a+c,
subject to the constraint that Ax'=m',
where x=[a,b,c]
A = [[20,0,0],[0,20,30]]
m = [20,30]
with a,b,c between 0 and 1.
One correct solution to the problem is a=1, b=0, and c=1. But Cplex gives solutions, a=1, b=1, and c=0. There is an error in formulating the problem but I cannot figure out where. Code below
import cplex
from cplex.exceptions import CplexError
import sys
my_obj = [1.0, 0.0, 1.0]
my_ub = [1.0] * len(my_obj)
my_lb = [0.0] * len(my_obj)
my_colnames = ["a", "b", "c"]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "E" * len(my_rownames)
def populatebynonzero(prob):
prob.objective.set_sense(prob.objective.sense.minimize)
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.variables.add(obj = my_obj, ub = my_ub, lb = my_lb ,names = my_colnames)
rows = [0,1]
cols = [0,1]
vals = [20.0,30.0]
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
def lpex1():
try:
my_prob = cplex.Cplex()
handle = populatebynonzero(my_prob)
my_prob.solve()
except CplexError, exc:
print exc
return
numrows = my_prob.linear_constraints.get_num()
numcols = my_prob.variables.get_num()
print
# solution.get_status() returns an integer code
print "Solution status = " , my_prob.solution.get_status(), ":",
# the following line prints the corresponding string
print my_prob.solution.status[my_prob.solution.get_status()]
print "Solution value = ", my_prob.solution.get_objective_value()
slack = my_prob.solution.get_linear_slacks()
pi = my_prob.solution.get_dual_values()
x = my_prob.solution.get_values()
dj = my_prob.solution.get_reduced_costs()
for i in range(numrows):
print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])
for j in range(numcols):
print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])
my_prob.write("lpex1.lp")
print x, "SOLUTIONS"
lpex1()
There was an error in definition of rows and columns of the constraint, corrections below, works now
rows = [0,1,1]
cols = [0,1,2]
vals = [20.0,20.0,30.0]
I am relatively new to python and have been asked to write a code where I enter a specific sequence of DNA and get various values for that sequence in return. I made a dictionary and am having trouble making the code recall the dictionary for values. The code is as follows:
import math
def dnaTM(seqobj):
if isinstance(seqobj,SeqRecord):
seq = seqobj.seq.tostring().upper()
elif isinstance(seqobj,Seq):
seq = seqobj.tostring().upper()
elif isinstance(seqobj,str):
seq = seqobj.upper()
C_primer = .000001
C_Monovalent = 1
percentage_annealed = 50
percentage_annealed = percentage_annealed/100.0
R = 1.987
deltaH = dict()
deltaS = dict()
deltaH = { 'AA/TT': -7.9, 'AT/TA': -7.2, 'TA/AT': -7.2, 'CA/GT': -8.5,
'GT/CA': -8.4, 'CT/GA': -7.8, 'GA/CT': -8.2, 'CG/GC': -10.6,
'GC/CG': -9.8, 'GG/CC': -8.0, 'GC_init': 0.1, 'AT_init': 2.3}
deltaS = { 'AA/TT': -22.2, 'AT/TA': -20.4, 'TA/AT': -21.3, 'CA/GT': -22.7,
'GT/CA': -22.4, 'CT/GA': -21.0, 'GA/CT': -22.2, 'CG/GC': -27.2,
'GC/CG': -24.4, 'GG/CC': -19.9, 'GC_init': -2.8, 'AT_init': 4.1,
'sym': -1.4}
seqLength = len(seq)
dH = 0.2 + deltaH[str(seq[0])] + deltaH[str(seq[len(seq)-1])]
dS = -5.7 + deltaS[seq[0]] + deltaS[seq[len(seq)-1]]
for i in range(0, seqLength - 1):
dH += deltaH[str(seq[i:i+2])]
dS += deltaS[seq[i:i+2]]
dS = dS + 0.368 * seqLength * math.log(1)
Tm =(dH * 1000) / (dS + R * (math.log(C_primer*(1- percentage_annealed)/percenta\
ge_annealed)-21.4164))
return Tm
I change this code to work in persian. My code returns:
Key: Text is too short to analyze Text:
and doesn't return key and decrypt text. Is it anything wrong with uppercase or ascii in persian text? What can I do?
# -*- coding: utf-8 -*-
from string import uppercase
from operator import itemgetter
def vigenere_decrypt(target_freqs, input):
nchars = len(uppercase)
ordA = ord(u"ا")
sorted_targets = sorted(target_freqs)
def frequency(input):
result = [[c, 0.0] for c in uppercase]
for c in input:
result[c - ordA][1] += 1
return result
def correlation(input):
result = 0.0
freq = frequency(input)
freq.sort(key=itemgetter(1))
for i, f in enumerate(freq):
result += f[1] * sorted_targets[i]
return result
cleaned = [ord(c) for c in input.upper() if c.isupper()]
best_len = 0
best_corr = -100.0
# Assume that if there are less than 20 characters
# per column, the key's too long to guess
for i in xrange(2, len(cleaned) // 20):
pieces = [[] for _ in xrange(i)]
for j, c in enumerate(cleaned):
pieces[j % i].append(c)
# The correlation seems to increase for smaller
# pieces/longer keys, so weigh against them a little
corr = -0.5 * i + sum(correlation(p) for p in pieces)
if corr > best_corr:
best_len = i
best_corr = corr
if best_len == 0:
return ("Text is too short to analyze", "")
pieces = [[] for _ in xrange(best_len)]
for i, c in enumerate(cleaned):
pieces[i % best_len].append(c)
freqs = [frequency(p) for p in pieces]
key = ""
for fr in freqs:
fr.sort(key=itemgetter(1), reverse=True)
m = 0
max_corr = 0.0
for j in xrange(nchars):
corr = 0.0
c = ordA + j
for frc in fr:
d = (ord(frc[0]) - c + nchars) % nchars
corr += frc[1] * target_freqs[d]
if corr > max_corr:
m = j
max_corr = corr
key += chr(m + ordA)
r = (chr((c - ord(key[i % best_len]) + nchars) % nchars + ordA)
for i, c in enumerate(cleaned))
return (key, "".join(r))
def main():
encoded = " پهيتش غعهدد ذصلدي هزفضر کنهرظ ضذکاح يصتمد "
english_frequences = [
14, 4.2, 0.7, 5.2, 0.1, 1.2, 0.4,
1, 1.4, 7.5, 0.1, 8.5, 2.1, 0.1,
3.3, 2.6, 0.7, 0.3, 0.6, 0.2, 1.5,
0.2, 1.6, 1.2, 3, 1.7, 2.7, 5.7, 7.1, 6, 5.7, 9.1]
(key, decoded) = vigenere_decrypt(english_frequences, encoded)
print "Key:", key
print "\nText:", decoded
main()
I've set up numpy.seterr as follows:
np.seterr(invalid='raise', over ='raise', under='raise')
And I'm getting the following error:
c = beta[j,i] + oneminusbeta[j,i]
FloatingPointError: overflow encountered in double_scalars
I've checked what beta[j,i] and oneminusbeta[j,i] are at the point of crash, and these are their values:
beta: -131.340389182
oneminusbeta: 0.0
Please note, this line of addition (beta[j,i] + oneminusbeta[j,i]) has run for thousands of lines in a loop (that performs image classification) before crashing here at this point.
How can I deal with this? Is it necessary to change the type of the numpy arrays?
This is how I've initialized them:
beta = np.empty([m,n])
oneminusbeta = np.empty([m,n])
Is it possible to cast the individual values before adding them up? Rather than changing the entire array declarations? Or is this even a serious issue? Would it be safe to simply turn off the numpy.seterr configuration and let the calculations go ahead without raising the error?
Edit
Someone suggested below, and I suspected as well, that the values being added shouldn't cause an overflow. Then how can I find out where the overflow is really happening?
This is my code:
epthreshold = 709
enthreshold = -708
f.write("weights["+str(i)+", " + str(j)+"] = math.exp(beta: " +str(beta[j,i])+ " + oneminusbeta: " + str(oneminusbeta[j,i])+")\n" )
c = beta[j,i] + oneminusbeta[j,i]
weights[i,j] = math.exp(np.clip(c, enthreshold, epthreshold))
And when I check my log file, this is the line I get:
weights[5550, 13] = math.exp(beta: -131.340389182 + oneminusbeta: 0.0)
Edit 2
Here's the rest of my code, where variables n,m and H have already been initialized to integer values:
import numba
import numpy as np
import statsmodels.api as sm
weights = np.empty([n,m])
for curr_n in range(n):
for curr_m in range(m):
weights[curr_n,curr_m] = 1.0/(n)
beta = np.empty([m,n])
oneminusbeta = np.empty([m,n])
for curr_class in range(m):
for curr_sample in range(n):
beta[curr_class,curr_sample] = 1./m
epthreshold = 709 # positive exponential threshold
enthreshold = -708
for h in range(H):
print "Boosting round %d ... " % h
z = np.empty([n,m])
for j in range(m): # computing working responses and weights, Step 2(a)(i)
for i in range(no_samples):
i_class = y[i] #get the correct class for the current sample
if h == 0:
z[i,j] = (int(j==i_class) - beta[j,i])/((beta[j,i])*(1. - beta[j,i]))
weights[i,j] = beta[j,i]*(1. - beta[j,i])
else:
if j == i_class:
z[i,j] = math.exp(np.clip(-beta[j,i],enthreshold, epthreshold))
else:
z[i,j] = -math.exp(np.clip(oneminusbeta[j,i], enthreshold, epthreshold))
f.write("weights["+str(i)+", " + str(j)+"] = math.exp(beta: " +str(beta[j,i])+ " + oneminusbeta: " + str(oneminusbeta[j,i])+")\n" )
c = beta[j,i] + oneminusbeta[j,i]
weights[i,j] = math.exp(np.clip(c, enthreshold, epthreshold))
g_h = np.zeros([1,1])
j = 0
# Calculating regression coefficients per class
# building the parameters per j class
for y1_w in zip(z.T, weights.T):
y1, w = y1_w
temp_g = sm.WLS(y1, X, w).fit() # Step 2(a)(ii)
if np.allclose(g_h,0):
g_h = temp_g.params
else:
g_h = np.c_[g_h, temp_g.params]
j = j + 1
if np.allclose(g,0):
g = g_h
else:
g = g + g_h # Step(2)(a)(iii)
# now set g(x), function coefficients according to new formula, step (2)(b)
sum_g = g.sum(axis=1)
for j in range(m):
diff = (g[:,j] - ((1./m) * sum_g))
g[:,j] = ((m-1.)/m) * diff
g_per_round[h,:,j] = g[:,j]
#Now computing beta, Step 2(c)...."
Q = 0.
e = 0.
for j in range(m):
# Calculating beta and oneminusbeta for class j
aj = 0.0
for i in range(no_samples):
i_class = y[i]
X1 = X[i].reshape(1, no_features)
g1 = g[:,j].reshape(no_features, 1)
gc = g[:,i_class].reshape(no_features, 1)
dot = 1. + float(np.dot(X1, g1)) - float(np.dot(X1,gc))
aj = dot
sum_e = 0.
a_q = []
a_q.append(0.)
for j2 in range(m): # calculating sum of e's except for all j except where j=i_class
if j2 != i_class: # g based on j2, not necessarily g1?
g2 = g[:,j2].reshape(no_features, 1)
dot1 = 1. + float(np.dot(X1, g2)) - float(np.dot(X1,gc))
e2 = math.exp(np.clip(dot1,enthreshold, epthreshold))
sum_e = sum_e + e2
a_q.append(dot1)
if (int(j==i_class) == 1):
a_q_arr = np.array(a_q)
alpha = np.array(a_q_arr[1:])
Q = mylogsumexp(f,a_q_arr, 1, 0)
sumalpha = mylogsumexp(f,alpha, 1, 0)
beta[j,i] = -Q
oneminusbeta[j,i] = sumalpha - Q
else:
alpha = a_q
alpha = np.array(alpha[1:])
a_q_arr = np.array(a_q)
Q = mylogsumexp(f,a_q_arr, 0, aj)
sumalpha = log(math.exp(np.clip(Q, enthreshold, epthreshold)) - math.exp(np.clip(aj, enthreshold, epthreshold)))
beta[j,i] = aj - Q
oneminusbeta[j,i] = sumalpha - Q
and the function mylogsumexp is:
def mylogsumexp(f, a, is_class, maxaj, axis=None, b=None):
np.seterr(over="raise", under="raise", invalid="raise")
threshold = -sys.float_info.max
maxthreshold = sys.float_info.max
epthreshold = 709 # positive exponential threshold
enthreshold = -708
a = asarray(a)
if axis is None:
a = a.ravel()
else:
a = rollaxis(a, axis)
if is_class == 1:
a_max = a.max(axis=0)
else:
a_max = maxaj
#bnone = " none "
if b is not None:
a_max = maxaj
b = asarray(b)
if axis is None:
b = b.ravel()
else:
b = rollaxis(b, axis)
a = np.clip(a - a_max, enthreshold, epthreshold)
midout = np.sum(np.exp(a), axis=0)
midout = 1.0 + np.clip(midout - math.exp(a_max), threshold, maxthreshold)
out = np.log(midout)
else:
a = np.clip(a - a_max, enthreshold, epthreshold)
out = np.log(np.sum(np.exp(a)))
out += a_max
if out == float("inf"):
out = maxthreshold
if out == float("-inf"):
out = threshold
return out