Advertisement
Guest User

Untitled

a guest
Mar 29th, 2020
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.63 KB | None | 0 0
  1. import matplotlib.pyplot as plt
  2. import scipy.optimize as opt
  3. import numpy as np
  4. import copy
  5. def quadratic_to_piecewise(a,a0,a00,xmin,xmax,piece_number=2,steps_ize=0.1,mode_hanging=False,hanging_sigma=0.01,show_result=False):
  6.     '''
  7.    Convert quadratic into piecewise (linear function) of:
  8.        y = m*x_delta + y_ref, where:
  9.            x_delta=x-x_ref
  10.            x_ref,y_ref is point of piecewise
  11.            ...
  12.  
  13.    ## Example:
  14.    xmin=0
  15.    xmax=100
  16.    a=0.1
  17.    a0=1
  18.    a00=10
  19.    w=quadratic_to_piecewise(a,a0,a00,xmin,xmax)  
  20.    print(w)
  21.    '''
  22.  
  23.     def func_2piecewise(x, m_0, x_1, y_1, m_1):
  24.         y = np.piecewise(x, [x <= x_1, x > x_1],
  25.                         [lambda x:m_0*(x-x_1) + y_1, lambda x:m_1*(x-x_1) + y_1])
  26.         return y
  27.  
  28.     def func_3piecewise(x, m_0, x_1, y_1, x_2, y_2, m_2):
  29.         y = np.piecewise(x, [x <= x_1, (x > x_1) & (x <= x_2), x > x_2],
  30.                         [lambda x:m_0*(x-x_1) + y_1, lambda x:y_1+(y_2-y_1)*(x-x_1)/(x_2-x_1), lambda x:m_2*(x-x_2) + y_2])
  31.         return y
  32.  
  33.     def func_quadratic(x,a,a0,a00):
  34.         y=a*x*x+a0*x+a00
  35.         return y    
  36.  
  37.     def func_gradients(x_list,y_list):
  38.         if isinstance(x_list, list):
  39.             m_list=[]
  40.             for idx in range(len(x_list)-1):
  41.                 m_list.append((y_list[idx+1]-y_list[idx])/(x_list[idx+1]-x_list[idx]))
  42.             return m_list
  43.         else:
  44.             m_list=y_list/x_list
  45.             return m_list
  46.  
  47.     def func_linear(x_delta,y_ref,m):
  48.         y=y_ref+m*x_delta
  49.         return y
  50.  
  51.     def func_piecewise(x_list,result):
  52.         idx=0
  53.         x_piece=[]
  54.         y_piece=[]
  55.         m_piece=[]
  56.         while idx < piece_number*3:
  57.             x_piece.append(result[idx])
  58.             y_piece.append(result[idx+1])
  59.             m_piece.append(result[idx+2])
  60.             idx=idx+3
  61.         piece=0
  62.         y_list=[]
  63.         for x in x_list:
  64.             for piece in range(piece_number):
  65.                 if piece == piece_number-1:
  66.                     y_list.append(func_linear(x-x_piece[piece],y_piece[piece],m_piece[piece]))
  67.                 elif x <= x_piece[piece+1]:
  68.                     y_list.append(func_linear(x-x_piece[piece],y_piece[piece],m_piece[piece]))
  69.                     break
  70.         return y_list
  71.  
  72.     def func_show_result(a,a0,a00,xmin,xmax,w,marker_number=20):
  73.         # Get points
  74.         x_sample_show=np.linspace(xmin,xmax,marker_number)
  75.         y_real_show = func_quadratic (x_sample_show,a,a0,a00)
  76.         y_model_show = func_piecewise (x_sample_show,result)
  77.  
  78.         # Plot
  79.         plt.plot(x_sample_show,y_real_show,c='#1f77b4',marker='+',label="Data")
  80.         plt.plot(x_sample_show,y_model_show,c='#ff7f0e',marker='*',label="Fit")
  81.         plt.title("Piecewise to Real Comparison")
  82.         plt.legend(loc="upper left")
  83.         plt.show()
  84.         pass
  85.  
  86.     ## Get sample
  87.     numberOfStep=int(1+(xmax-xmin)/steps_ize)
  88.     x_sample=np.linspace(xmin,xmax,numberOfStep)
  89.     y_sample=[a*x*x+a0*x+a00 for x in x_sample]
  90.  
  91.     ## Sigma (wighting)
  92.     sigma=np.ones(numberOfStep)
  93.     if mode_hanging==True:
  94.         sigma[[0,-1]]=hanging_sigma
  95.  
  96.     ## Solve
  97.     if piece_number==2:
  98.         lower_bounds=[-np.inf,xmin,-np.inf,-np.inf]
  99.         upper_bounds=[np.inf,xmax,np.inf,np.inf]
  100.  
  101.         w, _ = opt.curve_fit(func_2piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
  102.         x_0=copy.deepcopy(xmin)
  103.         y_0=func_2piecewise(x_0, *w).tolist()
  104.         [m_0, x_1, y_1, m_1]=w
  105.         result=[x_0,y_0,m_0,x_1,y_1,m_1]
  106.  
  107.     elif piece_number==3:
  108.         lower_bounds=[-np.inf,xmin,-np.inf,xmin,-np.inf,-np.inf]
  109.         upper_bounds=[np.inf,xmax,np.inf,xmax,np.inf,np.inf]
  110.         w, _ = opt.curve_fit(func_3piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
  111.         x_0=copy.deepcopy(xmin)
  112.         y_0=func_3piecewise(x_0, *w).tolist()
  113.         [m_0, x_1, y_1, x_2, y_2, m_2]=w
  114.         m_1=func_gradients(x_2-x_1,y_2-y_1)
  115.         result=[x_0,y_0,m_0,x_1,y_1,m_1, x_2, y_2, m_2]
  116.     else:
  117.         print('Number of piece is unsupported')
  118.         return []
  119.    
  120.     ## Show result
  121.     if show_result==True:
  122.         func_show_result(a,a0,a00,xmin,xmax,w)
  123.    
  124.     return result
  125.  
  126. ## Uncomment for example
  127. # xmin=0
  128. # xmax=100
  129. # a=0.1
  130. # a0=1
  131. # a00=10
  132. # result=quadratic_to_piecewise(a,a0,a00,xmin,xmax,piece_number=3,steps_ize=0.01,mode_hanging=True,show_result=True)
  133. # result=quadratic_to_piecewise(a,a0,a00,xmin,xmax,piece_number=2,steps_ize=0.01,mode_hanging=True,show_result=True)
  134. # result=quadratic_to_piecewise(a,a0,a00,xmin,xmax,piece_number=2,steps_ize=0.01,show_result=True)  
  135. # print(result)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement