Unknown numpy.optimize.fmin error - python

I am trying to write a program that calculates the optimum amount to bet based on log utility and simultaneous dependent events.
In order to do this I am trying to use the numpy.optimize.fmin function. The function anon that I am passing to it works and produces (hopefully) correct output but when numpy tries to optimise the function I get the following error
s[i].append(f[i][0]*w[i][0] + f[i][1]*w[i][1])
IndexError: invalid index to scalar variable.
Since I have no idea about fmin, I have no idea what is causing this error.
My code is below, hopefully not tl;dr but I wouldn't blame you.
APPENDIX
def main():
p = [[0.1,0.1,0.2, 0.2,0.1,0, 0.1,0.1,0.1]]
w = [[5,4]]
MaxLU(p,w,True)
def MaxLU(p, w, Push = False, maxIter = 10):
#Maximises LU, using Scipy in built function
if Push == True:
anon = lambda f: -PushLogUtility(p, w, f)
else:
anon = lambda f: -LogUtility(p, w, f)
#We use multiple random starts
f = []
LU = []
for i in range(0,maxIter):
start = np.random.rand(len(p))
start = start / 5 * np.sum(start)
f.append(optimize.fmin(anon, start)) #Error occurs in here!
if Push == True:
LU.append(PushLogUtility(p, w, f[-1]))
else:
LU.append(LogUtility(p, w, f[-1]))
#Now find the index of the max LU and return that same index of f
return f[LU.index(np.max(LU))]
def PushLogUtility(p,w,f):
#Outputs log utility incoroporating pushes and dependent totals, money data
#p : 9xk length vector of joint probabilities for each of the k games, p = [[p_(W_T W_M), p_(W_T P_M), p_(W_T L_M), p_(P_T W_M) ... ]]
#w : 2xk matrix of odds where w = [[total odds, money odds] ... ]
#f : 2xk matrix of bankroll percentages to bet, f = [[f_T, f_M] ... ]
utility = 0
k = len(p)
s = k*[[]]
for i in range(0,k):
s[i].append(f[i][0]*w[i][0] + f[i][1]*w[i][1])
s[i].append(f[i][0]*w[i][0])
s[i].append(f[i][0]*w[i][0] - f[i][1])
s[i].append(f[i][1]*w[i][1])
s[i].append(0)
s[i].append(-f[i][1])
s[i].append(-f[i][0] - f[i][1])
s[i].append(-f[i][0] - f[i][1])
s[i].append(-f[i][0] - f[i][1])
for i in range(0,9 ** k):
l = de2ni(i) #Converts number to base 9
if i == 0:
l += int(math.ceil(k - 1 - math.log(i + 1,9))) * [0]
else:
l += int(math.ceil(k - 1 - math.log(i,9))) * [0]
productTerm = np.prod([p[i][l[i]] for i in range(0,k)])
sumTerm = np.sum([s[i][l[i]] for i in range(0,k)])
utility = utility + productTerm * np.log(1 + sumTerm)
return utility

Here where you do:
s[i].append(f[i][0]*w[i][0] + f[i][1]*w[i][1])
if you look at the types, you'll find s[i] is a [], f[i] is 0.104528 and w[i] is [5,4]. You then try to index f[i] a second time - which is not possible and causes the error.

Related

Problem with exec() function in KKT conditions by using SymPy

I'm writing a not full-implemented Python function using SymPy library which looks for the critical points of a mathematical function f through the KKT conditions, as it follows:
def KKT(f: str, h=[], g=[], max=True):
# NOTE: The expressions contained in g must be such that g <= 0 and the ones contained in h must be such that h = 0. Both g and h are string lists
import sympy as sp # Importing a SymPy library
n = len(h) # Quantity of equality constraints
m = len(g) # Quantity of inequality constraints
f = sp.parse_expr(f) # Constructing the f function by passing a string as an argument
vars = f.free_symbols # Getting the variables set
pars = list(vars) # Parameters list
if n > 0:
for i in range(n):
exec(f'h{i+1} = sp.Symbol("h_{i+1}")')
exec(f'h{i+1} = sp.parse_expr(h[{i}])') # Create the equality constraint h_i
exec(f'l{i+1} = sp.Symbol("\\lambda_{i+1}")') # Create the parameter lambda_i
exec(f'pars.append(l{i+1})') # Adding lambda_i to parameters list
if m > 0:
for j in range(m):
exec(f'g_{j+1} = sp.Symbol("g_{j+1}")')
exec(f'g{j+1} = sp.parse_expr(g[{j}])') # Create the inequality constraint g_i
exec(f'u{j+1} = sp.Symbol("\\mu_{j+1}", negative=False)') # Create the parameter mu_i
exec(f'pars.append(u{j+1})') # Add mu_i to parameters list
exec(f'p{j+1} = sp.Symbol("p_{j+1}", negative=False)') # Create fill portion p_i
exec(f'pars.append(p{j+1})') # Add p_i to parameters list
# Creating the Lagrangean
L = f
if n > 0:
for i in range(n):
exec(f'L = L - l{i+1} * h{i+1}') 'Adding lambda_j * h_j to the Lagrangean
if m > 0:
for j in range(m):
exec(f'L = L - u{j+1} * g{j+1}') # <- THIS LINE IS NOT WORKING
# Adding mu_i * g_i to the Lagrangean
print(f'j: {j}')
print(f'{L}\n')
# Creating the KKT condition from Lagrangean
R = [] # Constraint's set
for var in vars:
R.append(sp.diff(L, var)) # Add the Lagrangean's partial derivative with respect to var
if n > 0:
for i in range(n):
exec(f'R.append(h{i+1})')
if m > 0:
for j in range(m):
exec(f'R.append(u{j+1} * g{j+1})')
exec(f'R.append(g{j+1} + p{j+1})')
# Solving KKT conditions
sols_lagr = sp.solve(R, pars, dict=True) # Lagrangian solutions
critical_points = [{var: sol.get(var) for var in sol if var in vars} for sol in sols_lagr]
return critical_points
KKT('24*x_1 - x_1**2 + 10*x_2 - 2*x_2**2',
[],
['x_1 - 8', 'x_2 - 7', '-x_1', '-x_2']
)
However, for some reason, the following line code doesn't work:
exec(f'L = L - u{j+1} * g{j+1}')
Because I'm getting this result when I execute this code's block:
j: 0
-x_1**2 + 24*x_1 - 2*x_2**2 + 10*x_2
j: 1
-x_1**2 + 24*x_1 - 2*x_2**2 + 10*x_2
j: 2
-x_1**2 + 24*x_1 - 2*x_2**2 + 10*x_2
j: 3
-x_1**2 + 24*x_1 - 2*x_2**2 + 10*x_2
Which shows the Lagrangean is not adding up the parcels. I'd be grateful if someone could help me.

How to perform a ranking selection in this Genetic Algorithm

I'm building a Genetic Algorithm to maximize this function: x^5 - 10x^3 + 30x - y^2 + 21y.
The code must be in binary and the bounds for x and y are [-2.5, 2.5]. To generate the initial population I made a 16 bit string for both x and y where:
The first bit represents the signal [0 or 1]
The the second and third bit represents the integer part [00, 01 or 10]
The rest represents the float part
This is the function that generates the initial population:
def generate_population(n_pop):
population = list()
for _ in range(n_pop):
aux = list()
for _ in range(2):
signal = bin(randint(0, 1))[2:]
int_part = bin(randint(0, 2))[2:].zfill(2)
float_part = bin(randint(0, 5000))[2:].zfill(13)
aux.append((signal+int_part+float_part))
population.append(aux)
return population
I also made a function that returns the binary number into float:
def convert_float(individual):
float_num = list()
for i in range(2):
signal = int(individual[i][0])
int_part = int(individual[i][1:3], 2)
float_part = int(individual[i][3:], 2) * (10 ** -4)
value = round(int_part + float_part, 4)
if value > 2.5:
value = 2.5
if signal == 1:
value = value * (-1)
float_num.append(value)
return float_num
And lastly this function that calculate the fitness of each individual:
def get_fitness(individual):
x = individual[0]
y = individual[1]
return x ** 5 - 10 * x ** 3 + 30 * x - y ** 2 + 21 * y
This is my main function:
def ga(n_pop=10, n_iter=10):
population = generate_population(n_pop)
best_fitness_id, best_fitness = 0, get_fitness(convert_float(population[0]))
for i in range(n_iter):
float_population = [convert_float(x) for x in population]
fitness_population = [get_fitness(x) for x in float_population]
for j in range(n_pop):
if fitness_population[j] > best_fitness:
best_fitness_id, best_fitness = j, fitness_population[j]
print(f'--> NEW BEST FOUND AT GENERATION {i}:')
print(f'{float_population[j]} = {fitness_population[j]}')
selected_parents = rank_selection()
# childrens = list()
# childrens = childrens + population[best_fitness_id] # ELITE
After running the program I have something like this:
The population looks like: [['0000001100110111', '0000110111110101'], ['0010011111101110', '1000100101001001'], ...
The float population: [[0.0823, 0.3573], [1.203, -0.2377], ...
And the fitness values: [9.839066068044746, 16.15145434928624, ...
I need help to build the rank_selection() function, I've been stuck in this selection for 2 days. I know is something 1/N, 2/N etc and I've seen tons of examples in multiple languages but I could not apply any of them to this particular algorithm and it MUST be rank selecion.
I already know how to perform crossover and mutation.

A root of a "saw-like" function

Say, we have f(t) = v * t + A * sin(w * t). I call such functions "saw-like":
I want to solve saw(t) = C, that is, find a root of saw(t) - C (still "saw-like").
I tried writing down a ternary search for function abs(saw(t) - C) to find its minima. If we are lucky (or crafty), it would be the root. Unfortunately, my code does not always work: sometimes we get stuck in those places:
My code (python3):
def calculate(fun):
eps = 0.000000001
eps_l = 0.1
x = terns(fun, 0, 100000000000000)
t = terns(fun, 0, x)
cnt = 0
while fun(x) > eps:
t = x
x = terns(fun, 0, t)
if abs(t - x) < eps_l:
cnt += 1
# A sorry attempt pass some wrong value as a right one.
# Gets us out of an infinite loop at least.
if cnt == 10:
break
return t
def terns(f, l, r):
eps = 0.00000000001
while r - l > eps:
x_1 = l + (r - l) / 3
x_2 = r - (r - l) / 3
if f(x_1) < f(x_2):
r = x_2
else:
l = x_1
return (l + r) / 2
So, how is it done? Is using ternary search the right way?
My other idea was somehow sending the equation over to the net, passing it to Wolfram Alpha and fetching the answers. Yet, I don't how it's done, as I am not quite fluent at python.
How could this be done?

Function that calculates NPV from a list of cash flows

trying to write a function that will calculate present value of list of cash flows. I know that numpy can do this very easily but for an assignment I have to write my own function for this :/.
Here are the three cash flows in a list as well as discount rate.
cfList = [20, 50, 90]
r = 0.05
Here's the function i've written so far. f = 0 because I want to start with the first cash flow (in this case 20). i = 1 because for the first flow its raised to the 1st power and the second flow (50) will be squared and so on.
def npv(cfList, r):
f = 0
i = 1
pv = cfList[f] / ((1 + r) ** i)
while i < len(cfList):
f += 1
i += 1
return pv
print(npv(cfList, r))
However, this output only gives me the PV of the first cashflow, and not the sum of all three from the list. If you can help i appreciate it so much thanks !
You need to sum the individual cashflows within your function and return that. At the moment you are returning the value of pv of the first cashflow as you have a return statement in your for loop.
Also, I think the way you check your while loop against i will mean that you'll miss the last payment value. Usually you don't need to instantiate counter variables yourself (see my examples below):
def npv(cfList, r):
f = 0
i = 1
pv = cfList[f] / ((1 + r) ** i) # <-- this needs to be in the loop
while i < len(cfList): # <-- i will break loop before last payment is calculated.
f += 1
i += 1
return pv # <-- this return here is the issue
print(npv(cfList, r))
NPV being the sum of PV of all future cashflows, that is what you need to calculate. E.g.:
def npv(cfList, r):
sum_pv = 0 # <-- variable used to sum result
for i, pmt in enumerate(cfList, start=1): # <-- use of enumerate allows you to do away with the counter variables.
sum_pv += pmt / ((1 + r) ** i) # <-- add pv of one of the cash flows to the sum variable
return sum_pv # <-- only return the sum after your loop has completed.
Always remember that a return statement in a for-loop will break out of the loop the first time the return is encountered.
An alternate implementation would be to yield individual PVs from a PV generator and sum the results:
def pv_gen(cfList, r):
for i, pmt in enumerate(cfList, start=1):
yield pmt / ((1 + r) ** i)
print(sum(pv_gen(cfList, r)))
Returning the NPV of a list of cash flows would look like:
def npv(cfList, r):
return sum(f / ((1 + r) ** i) for i, f in enumerate(cfList, 1))
In []:
cfList = [20, 50, 90]
r = 0.05
npv(cfList, r)
Out[]:
142.14447683835436
If you're iterating across the list using the while loop, then you should have the action taking line of code within the while loop.
It also looks like your loop will be cutting early as i = 2 = len(cflist) on the second iteration (don't forget that python uses 0 based indexing) and because the return call is within the while loop.
This should work:
def npv(cfList, r):
f = 0
i = 1
pv = 0
while f <= len(cfList):
pv += (cfList[f] / ((1 + r) ** i))
f += 1
i += 1
return pv

Why my while loop failed (python)?

I'm a new learner of python programming. Recently I'm trying to write a "tool" program of "dynamic programming" algorithm. However, the last part of my programe -- a while loop, failed to loop. the code is like
import numpy as np
beta, rho, B, M = 0.5, 0.9, 10, 5
S = range(B + M + 1) # State space = 0,...,B + M
Z = range(B + 1) # Shock space = 0,...,B
def U(c):
"Utility function."
return c**beta
def phi(z):
"Probability mass function, uniform distribution."
return 1.0 / len(Z) if 0 <= z <= B else 0
def Gamma(x):
"The correspondence of feasible actions."
return range(min(x, M) + 1)
def T(v):
"""An implementation of the Bellman operator.
Parameters: v is a sequence representing a function on S.
Returns: Tv, a list."""
Tv = []
for x in S:
# Compute the value of the objective function for each
# a in Gamma(x), and store the result in vals (n*m matrix)
vals = []
for a in Gamma(x):
y = U(x - a) + rho * sum(v[a + z]*phi(z) for z in Z)
# the place v comes into play, v is array for each state
vals.append(y)
# Store the maximum reward for this x in the list Tv
Tv.append(max(vals))
return Tv
# create initial value
def v_init():
v = []
for i in S:
val = []
for j in Gamma(i):
# deterministic
y = U(i-j)
val.append(y)
v.append(max(val))
return v
# Create an instance of value function
v = v_init()
# parameters
max_iter = 10000
tol = 0.0001
num_iter = 0
diff = 1.0
N = len(S)
# value iteration
value = np.empty([max_iter,N])
while (diff>=tol and num_iter<max_iter ):
v = T(v)
value[num_iter] = v
diff = np.abs(value[-1] - value[-2]).max()
num_iter = num_iter + 1
As you can see, the while loop at the bottom is used to iterate over "value function" and find the right answer. However, the while fails to loop, and just return num_iter=1. As for I know, the while loop "repeats a sequence of statements until some condition becomes false", clearly, this condition will not be satisfied until the diff converge to near 0
The major part of code works just fine, as far as I use the following for loop
value = np.empty([num_iter,N])
for x in range(num_iter):
v = T(v)
value[x] = v
diff = np.abs(value[-1] - value[-2]).max()
print(diff)
You define value as np.empty(...). That means that it is composed completely of zeros. The difference, therefore, between the last element and the second-to-last element will be zero. 0 is not >= 0.0001, so that expression will be False. Therefore, your loop breaks.

Categories

Resources