0

I would like to fit parameters p1-p6 into the function f(x1, x2) with multiple discrete conditions - the math would look like that:

if (x1 > p4) & (x2 < p6):
  y = p1*x1
elif x1 > p5:
  y = p2*x2
else:
  y = p3 * np.maximum(x1, x2)

I know how to solve the problem if I do not have this part of the equation: & (x2 < p6) so something like this:

if x1 > p4:
  y = p1*x1
elif x1 > p5:
  y = p2*x2
else:
  y = p3 * np.maximum(x1, x2)

in such case I would have to convert the discrete part into the continuous using scipy.special.erf():

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from lmfit import Model, minimize, report_fit, Parameters
from scipy.special import erf # to convert discrete values

def if_else_model(x, p1, p2, p3, p4, p5):
    
    # I have two arguments in x:
    x_1 = x[0]
    x_2 = x[1]
     
    # I have three functions:
    y1 = p1*x_1
    y2 = p2*x_2 * np.ones(len(x_2))
    y3 = p3*np.maximum(x_1, x_2) * np.ones(len(x_2))
    
    # I change discrete to continuous by adding errror: (erf(x-parameter)+1)/2
    # And as I have if - elif - else: I used y_2 to split it to: if - else - if - else - I guess there is a  better way?
    y_2 = y2 * (erf(x_1-p5)+1)/2 + y3 * (1-erf(x_1-p5))/2    
    y = y1 * (erf(x_1-p4)+1)/2 + y_2 * (1-erf(x_1-p4))/2
  
    return y

# I add the noise to create fake data to fit the model:
def if_else_model_fakedata(x, p1, p2, p3, p4, p5):
    return if_else_model(x, p1, p2, p3, p4, p5) + np.random.normal(size=x.size, scale=1.2)+4

# Define my x data:
x1 = np.linspace(1,50,50)
x2 = np.linspace(10,20,50)
x = [x1, x2]`

# Create the fake data
y = if_else_model_fakedata(x2,2, 2, 5, 30, 10)

# We can visualize it based on one argument (x1):
plt.plot(x1,y,"ko")
plt.plot(x1, if_else_model(x, 1, 0.2, 2, 25, 15), "r--")

# Model definition and initiating parameters:
test_model = Model(if_else_model)
params = test_model.make_params(p1=1, p2 = 0.2, p3 = 2, p4 = 25, p5 = 15)

# Fitting
result = test_model.fit(y, params, x=x)

# Plotting results
plt.plot(x1,y,"ko")
plt.plot(x1,result.init_fit, "r--")
plt.plot(x1,result.best_fit, "g-")

Thus, again the question:

how to add another condition for the second part--> & (x2 < p6)?

I am lost with converting discrete conditions into continuous numbers - step by step guidance would be great as I'm a Python beginner.

Julita
  • 1
  • 1

0 Answers0