How to solve a cubic function without knowing the coefficients a b and c? - python-3.x

Apology for this silly question. In the cubie function below (as from a school project), I am given the value for x and f(x) while coefficients a, b ,c and constant of d are unknown.
f(x)=ax^3+bx^2+cx+d
In such case, is there a way to find out a, b and c by using any python package? I found good amount of python tutorial for solving cubic function but they seem to mainly focus on solving x while a, b and c value are given.

Here is an approach via sympy, Python's symbolic math library.
As an example, we are trying to find the formula for the sum of the first n triangular numbers. The triangular numbers (formula n*(n+1)/2) are 0, 1, 3, 6, 10, 15, 21, ..... The sums of the first n triangular numbers are thus 0, 1, 4, 10, 20, 35, 56, ....
from sympy import Eq, solve
from sympy.abc import a,b,c,d, x
formula = a*x**3 + b*x**2 + c*x + d # general cubic formula
xs = [0, 1, 2, 3] # some x values
fxs = [0, 1, 4, 10] # the corresponding function values
sol = solve([Eq(formula.subs(x, xi), fx) for xi, fx in zip(xs, fxs)])
print(sol) # {a: 1/6, b: 1/2, c: 1/3, d: 0}
You can use more x, fx pairs to check that a cubic formula suffices (this won't work with float values, as sympy needs exact symbolic equations).
Also sympy's interpolate can be interesting. This calculates a polynomial through some given points. Such code could look like:
from sympy import interpolate
from sympy.abc import x
xs = [0, 1, 2, 3]
fxs = [0, 1, 4, 10]
fx_dict = dict(zip(xs, fxs))
sol = interpolate(fx_dict, x)
print(sol) # x**3/6 + x**2/2 + x/3
print(sol.factor()) # x*(x + 1)*(x + 2)/6

Related

Finding a vector that is orthogonal to n columns of a matrix

Given a matrix B with shape (M, N), where M > N. How to find a vector v (with shape of M) that is perpendicular to all columns in B.
I tried using Numpy numpy.linalg.lstsq method to solve : Bx = 0. 0 here is a vector with M zeros.
It returns a vector of zeros with (N,) shape.
You can use sympy library, like
from sympy import Matrix
B = [[2, 3, 5], [-4, 2, 3], [0, 0, 0]]
V = A.nullspace()[0]
or to find whole nullspace
N = A.nullspace()
Here is what worked for me in case someone else need the answer:
u,s,vh=np.linalg.svd(B)
v=vh[-1:1]

List [0-1] to binary representation fast

I am trying to convert the rows [0-1] of a matrix to representation in number (binary equivalent), the code I have is the following:
import numpy as np
def generate_binary_matrix(matrix):
result = []
for i in matrix:
val = '0b' + ''.join([str(x) for x in i])
result.append(int(val, 2))
result = np.array(result)
return result
initial_matrix = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])
result = generate_binary_matrix(initial_matrix )
print(result)
This code works but it is very slow, does anyone know how to do it in a faster way?
You can convert a 0/1 list to binary using just arithmetic, which should be faster:
from functools import reduce
b = reduce(lambda r, x: 2*r + x, i)
Suppose you matrix numpy array is A with m rows and n columns.
Create a b vector with nelements by:
b = np.power(2, np.arange(n))[::-1]
then your answer is A # b
Example:
import numpy as np
A = np.array([[0, 0, 1], [1, 0, 1]])
n = A.shape[1]
b = np.power(2, np.arange(n))[::-1]
print(A # b) # --> [1 5]
update - I reversed b as the MSB (2^n-1) is A[:,0] + power arguments were mistakenly flipped + add an example.

How to repeat tensor in a specific new dimension in PyTorch

If I have a tensor A which has shape [M, N],
I want to repeat the tensor K times so that the result B has shape [M, K, N]
and each slice B[:, k, :] should has the same data as A.
Which is the best practice without a for loop.
K might be in other dimension.
torch.repeat_interleave() and tensor.repeat() does not seem to work. Or I am using it in a wrong way.
tensor.repeat should suit your needs but you need to insert a unitary dimension first. For this we could use either tensor.unsqueeze or tensor.reshape. Since unsqueeze is specifically defined to insert a unitary dimension we will use that.
B = A.unsqueeze(1).repeat(1, K, 1)
Code Description A.unsqueeze(1) turns A from an [M, N] to [M, 1, N] and .repeat(1, K, 1) repeats the tensor K times along the second dimension.
Einops provides repeat function
import einops
einops.repeat(x, 'm n -> m k n', k=K)
repeat can add arbitrary number of axes in any order and reshuffle existing axes at the same time.
Adding to the answer provided by #Alleo. You can use following Einops function.
einops.repeat(example_tensor, 'b h w -> (repeat b) h w', repeat=b)
Where b is the number of times you want your tensor to be repeated and h, w the additional dimensions to the tensor.
Example -
example_tensor.shape -> torch.Size([1, 40, 50])
repeated_tensor = einops.repeat(example_tensor, 'b h w -> (repeat b) h w', repeat=8)
repeated_tensor.shape -> torch.Size([8, 40, 50])
More examples here - https://einops.rocks/api/repeat/
Repeated values are memory heavy, in most cases best practice is to use broadcasting. So you would use A[:, None, :] which would make A.shape==(M, 1, N).
One case where I would agree to repeating the values, is that of in place operations in the following steps.
As numpy and torch differ in their implementations I like to agnostic (A * torch.ones(K, 1, 1))) followed by a transpose.
tensor.expand might be a better choice than tensor.repeat because according to this: "Expanding a tensor does not allocate new memory, but only creates a new view on the existing tensor where a dimension of size one is expanded to a larger size by setting the stride to 0."
However, be aware that: "More than one element of an expanded tensor may refer to a single memory location. As a result, in-place operations (especially ones that are vectorized) may result in incorrect behavior. If you need to write to the tensors, please clone them first."
M = N = K = 3
A = torch.arange(0, M * N).reshape((M, N))
B = A.unsqueeze(1).expand(M, K, N)
B
'''
tensor([[[0, 1, 2],
[0, 1, 2],
[0, 1, 2]],
[[3, 4, 5],
[3, 4, 5],
[3, 4, 5]],
[[6, 7, 8],
[6, 7, 8],
[6, 7, 8]]])
'''

Clip parts of a tensor

I have a theano tensor and I would like to clip its values, but each index to a different range.
For example, if I have a vector [a,b,c] , I want to clip a to [0,1] , clip b to [2,3] and c to [3,5].
How can I do that efficiently?
Thanks!
The theano.tensor.clip operation supports symbolic minimum and maximum values so you can pass three tensors, all of the same shape, and it will perform an element-wise clip of the first with respect to the second (minimum) and third (maximum).
This code shows two variations on this theme. v1 requires the minimum and maximum values to be passed as separate vectors while v2 allows the minimum and maximum values to be passed more like a list of pairs, represented as a two column matrix.
import theano
import theano.tensor as tt
def v1():
x = tt.vector()
min_x = tt.vector()
max_x = tt.vector()
y = tt.clip(x, min_x, max_x)
f = theano.function([x, min_x, max_x], outputs=y)
print f([2, 1, 4], [0, 2, 3], [1, 3, 5])
def v2():
x = tt.vector()
min_max = tt.matrix()
y = tt.clip(x, min_max[:, 0], min_max[:, 1])
f = theano.function([x, min_max], outputs=y)
print f([2, 1, 4], [[0, 1], [2, 3], [3, 5]])
def main():
v1()
v2()
main()

Unable to create lambda function in hierarchical pymc3 model

I'm trying to create the model shown below with PyMC 3 but can't figure out how to properly map probabilities to the observed data with a lambda function.
import numpy as np
import pymc as pm
data = np.array([[0, 0, 1, 1, 2],
[0, 1, 2, 2, 2],
[2, 2, 1, 1, 0],
[1, 1, 2, 0, 1]])
(D, W) = data.shape
V = len(set(data.ravel()))
T = 3
a = np.ones(T)
b = np.ones(V)
with pm.Model() as model:
theta = [pm.Dirichlet('theta_%s' % i, a, shape=T) for i in range(D)]
z = [pm.Categorical('z_%i' % i, theta[i], shape=W) for i in range(D)]
phi = [pm.Dirichlet('phi_%i' % i, b, shape=V) for i in range(T)]
w = [pm.Categorical('w_%i_%i' % (i, j),
p=lambda z=z[i][j], phi_=phi: phi_[z], # Error is here
observed=data[i, j])
for i in range(D) for j in range(W)]
The error I get is
AttributeError: 'function' object has no attribute 'shape'
In the model I'm attempting to build, the elements of z indicate which element in phi gives the probability of the corresponding observed value in data (placed in RV w). In other words,
P(data[i,j]) <- phi[z[i,j]][data[i,j]]
I'm guessing I need to define the probability with a Theano expression or use Theano as_op but I don't see how it can be done for this model.
You should specify your categorical p values as Deterministic objects before passing them on to w. Otherwise, the as_op implementation would look something like this:
#theano.compile.ops.as_op(itypes=[t.lscalar, t.dscalar, t.dscalar],otypes=[t.dvector])
def p(z=z, phi=phi):
return [phi[z[i,j]] for i in range(D) for j in range(W)]

Resources