I have set-up a polynomial equation with 4 factors inside, that I want to solve using scipy.optimize.minimize.
However, I might want to solve only a certain set of the 4 factors at any one time. For example,
-> given Y(x1, x2, x3, x4) = Function(x1, x2, x3, x4) = 0.0 (to get the roots)
Sometimes, I want to get all [x1, x2, x3, x4], but sometimes, I want to just solve-for/calibrate [x2, x3] etc, or any iteration of the set [x1, x2, x3, x4].
Is there a way to do this elegantly?
def fit_beta(fwd_ = 0.01, shift_ = 0.0, time_ = 1.0, beta = 1.0, k_ = np.array([]), vols_ = np.array([]), params = np.array([1, 1, 1, 1])):
def calib_(x):
curve_ = []
for strike_ in k_:
vol_ = vol_log(strike_, fwd_, time_, x[0], x[1], x[2], x[3])
curve_.append(vol_)
return np.sum((np.array(curve_) - np.array(vols_))**2)
x0 = np.array([0.01, 0.5, 0.00, 0.10]) # initial guess
bounds = [(0.0001, None), (0.0001, 0.9999), (-0.9999, 0.9999), (0.0001, None)]
res = minimize(calib_, x0, method='L-BFGS-B', bounds=bounds)
x1_, x2_, x3_, x4_ = res.x
return [x1_, x2_, x3_, x4_]
Related
I am trying to make a fill between two datasets of different length using Matplotlib in Python.
Datasets are as follows
x1 = [0.00137221, 0.01372213, 0.02607204, 0.03910806, 0.05351629,
0.07066895, 0.08713551, 0.10634648, 0.12761578, 0.14888508,
0.17221269, 0.19691252, 0.2271012 , 0.25797599, 0.28747856,
0.31766724, 0.34373928, 0.36569468, 0.38559177]
y1 = [1.03307393, 1.04661479, 1.05875486, 1.07182879, 1.08723735,
1.10544747, 1.11945525, 1.13299611, 1.14607004, 1.15540856,
1.15680934, 1.15680934, 1.15354086, 1.14513619, 1.13346303,
1.12085603, 1.10964981, 1.09891051, 1.08677043]
x2 = [0.00960549, 0.03773585, 0.06929674, 0.11595197, 0.15574614,
0.18113208, 0.20994854, 0.2380789 , 0.27101201]
y2 = [1.00645914, 1.02233463, 1.03821012, 1.05315175, 1.05688716,
1.05595331, 1.04894942, 1.04054475, 1.01579767]
I followed the procedure suggested here:
fill between two lines lacking common x values
xfill = np.linspace(0,0.4,10)
y1fill = np.interp(xfill, x1,y1)
y2fill = np.interp(xfill, x2,y2)
plt.plot(x1,y1)
plt.plot(x2,y2)
plt.fill_between(xfill, y1fill,y2fill,color = "lightgray")
When I apply the suggested code, I am getting wrong fill_between:
Using pgfplots in LaTeX I am getting somewhat that I want
You can add an extra start/end point with the terminal values of the outside line:
x_start = min(x1[0], x2[0])
x_end = max(x1[-1], x2[-1])
y_start = y1[0] if x_start == x1[0] else y2[0]
y_end = y1[-1] if x_end == x1[-1] else y2[-1]
xfill = np.linspace(x_start, x_end, 100)
y1fill = np.interp(xfill, np.r_[x_start, x1, x_end], np.r_[y_start, y1, y_end])
y2fill = np.interp(xfill, np.r_[x_start, x2, x_end], np.r_[y_start, y2, y_end])
plt.plot(x1,y1)
plt.plot(x2,y2)
plt.fill_between(xfill, y1fill, y2fill, color="lightgray")
Output:
As a function:
def fill_between_ends(x1, x2, y1, y2, **kwargs):
x_start = min(x1[0], x2[0])
x_end = max(x1[-1], x2[-1])
y_start = y1[0] if x_start == x1[0] else y2[0]
y_end = y1[-1] if x_end == x1[-1] else y2[-1]
xfill = np.linspace(x_start, x_end,100)
y1fill = np.interp(xfill, np.r_[x_start, x1, x_end], np.r_[y_start, y1, y_end])
y2fill = np.interp(xfill, np.r_[x_start, x2, x_end], np.r_[y_start, y2, y_end])
plt.fill_between(xfill, y1fill, y2fill, **kwargs)
plt.plot(x1,y1)
plt.plot(x2,y2)
fill_between_ends(x1, x2, y1, y2, color="lightgray")
I have this coupled mass system code that runs good and prints results. But I have trouble plotting the graphs for positions and velocities since I am unable to extract values from arrays. I would appreciate some help!
import numpy as np
%matplotlib inline
import matplotlib.pyplot as pl
from scipy.integrate import odeint
def vectorfield(w, t, p):
x1, y1, x2, y2 = w
m1, m2, k1, k2, kc = p
# Create f = (x1',y1',x2',y2'):
f = [y1, (-x1*(k1+kc) + x2*kc)/m1, y2, (x1*kc - x2*(k2+kc)) / m2]
return f
# Parameter values
# Masses:
m1 = 1.0
m2 = 1.0
# Spring constants
k1 = 4.0
k2 = 1.0
kc = 0.1
# Initial conditions
# x1 and x2 are the initial displacements; y1 and y2 are the initial velocities
x1 = -2.0
y1 = 5.0
x2 = 2.0
y2 = 10.0
# ODE solver parameters
abserr = 1.0e-8
relerr = 1.0e-6
stoptime = 100.0
numpoints = 250
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
# Pack up the parameters and initial conditions:
p = [m1, m2, k1, k2, kc]
w0 = [x1, y1, x2, y2]
# Call the ODE solver.
wsol = odeint(vectorfield, w0, t, args=(p,), atol=abserr, rtol=relerr)
# Print solution
for t1, w1 in zip(t, wsol):
AZ = [t1, w1[0], w1[1], w1[2], w1[3]]
print(AZ)
I have tried searching the web but wasnt unable to find a fitting solution to plot this. I tried
with open('coupled_masses.dat', 'w') as f:
for t1, w1 in zip(t, wsol):
print(f, t1, w1[0], w1[1], w1[2], w1[3])
import matplotlib.pyplot as plt;
from matplotlib.font_manager import FontProperties;
# get saved values from saved file
t, x1, y1, x2, y2 = np.loadtxt('coupled_masses.dat', unpack=True);
but it doesnt work
Is this what you want? Using list comprehension here and then convert to numpy array.
from scipy.integrate import odeint
def vectorfield(w, t, p):
x1, y1, x2, y2 = w
m1, m2, k1, k2, kc = p
# Create f = (x1',y1',x2',y2'):
f = [y1, (-x1*(k1+kc) + x2*kc)/m1, y2, (x1*kc - x2*(k2+kc)) / m2]
return f
# Parameter values
# Masses:
m1 = 1.0
m2 = 1.0
# Spring constants
k1 = 4.0
k2 = 1.0
kc = 0.1
# Initial conditions
# x1 and x2 are the initial displacements; y1 and y2 are the initial velocities
x1 = -2.0
y1 = 5.0
x2 = 2.0
y2 = 10.0
# ODE solver parameters
abserr = 1.0e-8
relerr = 1.0e-6
stoptime = 100.0
numpoints = 250
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
# Pack up the parameters and initial conditions:
p = [m1, m2, k1, k2, kc]
w0 = [x1, y1, x2, y2]
# Call the ODE solver.
wsol = odeint(vectorfield, w0, t, args=(p,), atol=abserr, rtol=relerr)
# Print solution
data = np.array([[t1, w1[0], w1[1], w1[2], w1[3]] for t1, w1 in zip(t, wsol)])
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(7.2, 7.2/2))
ax1.plot(data[:, 0], data[:, 1])
ax2.plot(data[:, 0], data[:, 3])
UNEXPOSED = '~'
POKEMON = "☺"
FLAG = "♥"
EXPOSED = "0"
possible_adjacent_amount = ["0", "1", "2" "3", "4", "5", "6", "7", "8"]
def draw_board(self, board):
self.delete()
index = 0
print(board)
for row in range(self._grid_size):
for column in range(self._grid_size):
x1 = column*self._cell_size
y1 = row * self._cell_size
x2 = x1 + self._cell_size
y2 = y1 + self._cell_size
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
#bounding_box = ((int (x1), int (y1)), (int (x2), int (y2)))
centre_pixel = (x1 + (x2 - x1) // 2, y1 + (y2 - y1) // 2)
self.pos_to_pixel[(row, column)] = centre_pixel
#tp = self.create_text((100, 100), text='1')
print(board[index])
if board[index] ==UNEXPOSED:
self.create_rectangle (x1, y1, x2, y2, fill="dark green", tags="rect")
if board[index] in possible_adjacent_amount :
# TODO why doesn't this work...?
self.create_text(self.position_to_pixel ((row, column)), text = board[index])
self.create_rectangle (x1, y1, x2, y2, fill="light green", tags="rect")
if board[index] == FLAG:
self.create_rectangle (x1, y1, x2, y2, fill="red", tags="rect")
if board[index] == POKEMON:
self.create_text ((centre_pixel), text=board[index])
self.create_rectangle (x1, y1, x2, y2, fill="yellow", tags="rect")
index += 1
The board input will be something like 0~~~1~~12~~3
The idea is that it will take the board index and then create text at the center pixel of the board index that will be the numbers which in this case would be 0, 1, 1, 2, 3
You if you want the numbers to be drawn on the rectangles you need to create the text after you create the rectangles otherwise you will create text behind the rectangles.
In the Python implementation of the Xiaolin Wu's line algorithm, a function is defined while being nested in another function. Part of the code:
def draw_line(img, p1, p2, color):
"""Draws an anti-aliased line in img from p1 to p2 with the given color."""
x1, y1 = p1
x2, y2 = p2
dx, dy = x2-x1, y2-y1
steep = abs(dx) < abs(dy)
p = lambda px, py: ((px,py), (py,px))[steep]
if steep:
x1, y1, x2, y2, dx, dy = y1, x1, y2, x2, dy, dx
if x2 < x1:
x1, x2, y1, y2 = x2, x1, y2, y1
grad = dy/dx
intery = y1 + _rfpart(x1) * grad
def draw_endpoint(pt):
x, y = pt
xend = round(x)
yend = y + grad * (xend - x)
xgap = _rfpart(x + 0.5)
px, py = int(xend), int(yend)
putpixel(img, p(px, py), color, _rfpart(yend) * xgap)
putpixel(img, p(px, py+1), color, _fpart(yend) * xgap)
return px
How does this work? Why didn't the programmer just define the code somewhere else and then call it in this function? If this function where to be called in a loop to draw multiple lines, wouldn't it be more efficient to just, as I said, define the nested function somewhere else?
try this:
class Humans():
def health(self, weight, height, age):
self.weight = weight
self.height = height
self.age = age
def health_health(self):
print(f'''This human is {self.age} years old; weighs {self.weight},
and has a height of {self.height}''')
Harar = Humans()
Harar.health(1,2,3)
Harar.health_health()
The reason why is because you are calling the function from the class definition, as opposed to the initialized object. You can do two things to fix this:
Call the function from the object that has been initialized:
class Foo:
def bar(x):
print(x)
a = Foo()
a.bar(10)
Or, define the function as a staticmethod:
class Foo:
#staticmethod
def bar(x):
print(x)
Foo.bar(10)
Both will output:
10
I'm enrolled in a Data Science course, and I'm trying to solve some programming problems, I haven't worked with Python in a long time, but I'm trying to improve my knowledge of the language.
Here is my problem:
def find_slope(x1, y1, x2, y2):
if (x1) == (x2):
return "inf"
else:
return ((float)(y2-y1)/(x2-x1))
Here is my driver code:
x1 = 1
y1 = 2
x2 = -7
y2 = -2
print(find_slope(x1, y1, x2, y2))
This is my output:
0.5
I'm not sure how to get it in the correct format, such as (((1, 2), .5), (3, 4))
NOTE: I wrote the code for the driver.
You can do this:
def find_slope(input):
x1 = input[0][0]
y1 = input[0][1]
x2 = input[1][0]
y2 = input[1][1]
if (x1) == (x2):
slope = "inf"
else:
slope = ((float)(y2-y1)/(x2-x1))
output = (((x1, y1), slope), (x2, y2))
return output
I changed the input to match the input format given in the screenshot.
Now the input is a single tuple, containing two tuples. Each of the inner tuples contain a x coordinate and a y coordinate.
You can call the function using
input = ((1, 2), (-7, -2))
output = find_slope(input)
The output will be in the format ((A, slope), B), where A and B are tuples containing the x and y coords.