代码之家  ›  专栏  ›  技术社区  ›  DavidC.

求两条三次曲线之间的公共切线

  •  3
  • DavidC.  · 技术社区  · 8 年前

    给定两个函数,我想对两条曲线的公共切线进行排序:

    enter image description here

    公共切线的斜率可通过以下方式获得:

    slope of common tangent = (f(x1) - g(x2)) / (x1 - x2) = f'(x1) = g'(x2)
    

    最后我们得到了一个由两个方程组成的系统,其中有两个未知量:

    f'(x1) = g'(x2) # Eq. 1
    (f(x1) - g(x2)) / (x1 - x2) = f'(x1) # Eq. 2
    

    出于某种原因,我不理解,python没有找到解决方案:

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    import sys
    from sympy import *
    import sympy as sym
    
    
    # Intial candidates for fit 
    E0_init = -941.510817926696
    V0_init = 63.54960592453
    B0_init = 76.3746233515232
    B0_prime_init = 4.05340727164527
    
    # Data 1 (Red triangles): 
    V_C_I, E_C_I = np.loadtxt('./1.dat', skiprows = 1).T
    
    # Data 14 (Empty grey triangles):
    V_14, E_14 = np.loadtxt('./2.dat', skiprows = 1).T
    
    def BM(x, a, b, c, d):
            return  (2.293710449E+17)*(1E-21)* (a + b*x + c*x**2 + d*x**3 )
    
    def P(x, b, c, d):
        return -b - 2*c*x - 3 *d*x**2
    
    init_vals = [E0_init, V0_init, B0_init, B0_prime_init]
    popt_C_I, pcov_C_I = curve_fit(BM, V_C_I, E_C_I, p0=init_vals)
    popt_14, pcov_14 = curve_fit(BM, V_14, E_14, p0=init_vals)
    
    x1 = var('x1')
    x2 = var('x2')
    
    E1 = P(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) - P(x2, popt_14[1], popt_14[2], popt_14[3])
    print 'E1 = ', E1
    
    E2 = ((BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - BM(x2, popt_14[0], popt_14[1], popt_14[2], popt_14[3])) / (x1 - x2)) - P(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    
    sols = solve([E1, E2], [x1, x2])
    
    print 'sols = ', sols
    
    # Linspace for plotting the fitting curves:
    V_C_I_lin = np.linspace(V_C_I[0], V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0], V_14[-1], 10000)
    
    plt.figure()
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black', label='Cubic fit data 1' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b', label='Cubic fit data 2')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='Data 1', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='Data 2', s=100)
    
    plt.ticklabel_format(useOffset=False)
    plt.show()
    

    enter image description here

    1.dat 如下所示:

    61.6634100000000 -941.2375622594436
    62.3429030000000 -941.2377748739724
    62.9226515000000 -941.2378903605746
    63.0043440000000 -941.2378981684135
    63.7160150000000 -941.2378864590100
    64.4085050000000 -941.2377753645115
    65.1046835000000 -941.2375332100225
    65.8049585000000 -941.2372030376584
    66.5093925000000 -941.2367456992965
    67.2180970000000 -941.2361992239395
    67.9311515000000 -941.2355493856510
    

    2.dat 如下所示:

    54.6569312500000 -941.2300821583739
    55.3555152500000 -941.2312112888004
    56.1392347500000 -941.2326135552780
    56.9291575000000 -941.2338291772218
    57.6992532500000 -941.2348135408652
    58.4711572500000 -941.2356230099117
    59.2666985000000 -941.2362715934311
    60.0547935000000 -941.2367074271724
    60.8626545000000 -941.2370273047416
    

    更新: 使用@if。。。。方法:

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties
    
    # Intial candidates for fit, per FU: - thus, the E vs V input data has to be per FU
    E0_init = -941.510817926696   
    V0_init = 63.54960592453  
    B0_init = 76.3746233515232  
    B0_prime_init = 4.05340727164527 
    
    def BM(x, a, b, c, d):
             return  a + b*x + c*x**2 + d*x**3 
    
    def devBM(x, b, c, d):
             return  b + 2*c*x + 3*d*x**2 
    
    # Data 1 (Red triangles): 
    V_C_I, E_C_I = np.loadtxt('./1.dat', skiprows = 1).T
    
    # Data 14 (Empty grey triangles):
    V_14, E_14 = np.loadtxt('./2.dat', skiprows = 1).T
    
    init_vals = [E0_init, V0_init, B0_init, B0_prime_init]
    popt_C_I, pcov_C_I = curve_fit(BM, V_C_I, E_C_I, p0=init_vals)
    popt_14, pcov_14 = curve_fit(BM, V_14, E_14, p0=init_vals)
    
    from scipy.optimize import fsolve
    def equations(p):
        x1, x2 = p
        E1 = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) - devBM(x2, popt_14[1], popt_14[2], popt_14[3])
        E2 = ((BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - BM(x2, popt_14[0], popt_14[1], popt_14[2], popt_14[3])) / (x1 - x2)) - devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
        return (E1, E2)
    
    x1, x2 =  fsolve(equations, (50, 60))
    print 'x1 = ', x1
    print 'x2 = ', x2
    
    slope_common_tangent = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    print 'slope_common_tangent = ', slope_common_tangent
    
    def comm_tangent(x, x1, slope_common_tangent):
       return BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - slope_common_tangent * x1 + slope_common_tangent * x
    
    # Linspace for plotting the fitting curves:
    V_C_I_lin = np.linspace(V_C_I[0], V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0], V_14[-1], 10000)
    
    plt.figure()
    
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black', label='Cubic fit Calcite I' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b', label='Cubic fit Calcite II')
    
    xp = np.linspace(54, 68, 100)
    pcomm_tangent, = plt.plot(xp, comm_tangent(xp, x1, slope_common_tangent), 'green', label='Common tangent')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='Calcite I', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='Calcite II', s=100)
    
    fontP = FontProperties()
    fontP.set_size('13')
    
    plt.legend((p1, p2, p5, p6, pcomm_tangent), ("1", "Cubic fit 1", "2", 'Cubic fit 2', 'Common tangent'), prop=fontP)
    
    print 'devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) = ', devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    
    plt.ylim(-941.240, -941.225) 
    plt.ticklabel_format(useOffset=False)
    
    plt.show()
    

    我能够找到公切线,如下所示:

    enter image description here

    然而,该公共切线对应于数据范围之外区域中的公共切线,即使用

    V_C_I_lin = np.linspace(V_C_I[0]-30, V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0]-20, V_14[-1]+2, 10000)
    xp = np.linspace(40, 70, 100)
    plt.ylim(-941.25, -941.18)
    

    可以看到以下内容:

    enter image description here

    是否可以将解算器约束到有数据的范围,以找到所需的公切线?

    更新2.1 :使用@if。。。。范围约束方法,以下代码生成 x1 = 61.2569899 x2 = 59.7677843 . 如果我们绘制它:

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties
    import sys
    from sympy import *
    import sympy as sym
    import os
    
    # Intial candidates for fit, per FU: - thus, the E vs V input data has to be per FU
    E0_init = -941.510817926696  # -1882.50963222/2.0 
    V0_init = 63.54960592453 #125.8532/2.0 
    B0_init = 76.3746233515232 #74.49 
    B0_prime_init = 4.05340727164527 #4.15
    
    def BM(x, a, b, c, d):
             return  a + b*x + c*x**2 + d*x**3
    
    def devBM(x, b, c, d):
             return  b + 2*c*x + 3*d*x**2
    
    # Data 1 (Red triangles): 
    V_C_I, E_C_I = np.loadtxt('./1.dat', skiprows = 1).T
    
    # Data 14 (Empty grey triangles):
    V_14, E_14 = np.loadtxt('./2.dat', skiprows = 1).T
    
    init_vals = [E0_init, V0_init, B0_init, B0_prime_init]
    popt_C_I, pcov_C_I = curve_fit(BM, V_C_I, E_C_I, p0=init_vals)
    popt_14, pcov_14 = curve_fit(BM, V_14, E_14, p0=init_vals)
    
    def equations(p):
        x1, x2 = p
        E1 = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) - devBM(x2, popt_14[1], popt_14[2], popt_14[3])
        E2 = ((BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - BM(x2, popt_14[0], popt_14[1], popt_14[2], popt_14[3])) / (x1 - x2)) - devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
        return (E1, E2)
    
    from scipy.optimize import least_squares
    lb = (61.0, 59.0)   # lower bounds on x1, x2
    ub = (62.0, 60.0)    # upper bounds
    result = least_squares(equations, [61, 59], bounds=(lb, ub))
    print 'result = ', result
    
    # The result obtained is:
    # x1 = 61.2569899
    # x2 = 59.7677843
    
    slope_common_tangent = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    print 'slope_common_tangent = ', slope_common_tangent
    
    
    def comm_tangent(x, x1, slope_common_tangent):
       return BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - slope_common_tangent * x1 + slope_common_tangent * x
    
    # Linspace for plotting the fitting curves:
    V_C_I_lin = np.linspace(V_C_I[0]-2, V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0], V_14[-1]+2, 10000)
    
    
    fig_handle = plt.figure()
    
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b' )
    
    xp = np.linspace(54, 68, 100)
    pcomm_tangent, = plt.plot(xp, comm_tangent(xp, x1, slope_common_tangent), 'green', label='Common tangent')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='1', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='2', s=100)
    
    fontP = FontProperties()
    fontP.set_size('13')
    
    plt.legend((p1, p2, p5, p6, pcomm_tangent), ("1", "Cubic fit 1", "2", 'Cubic fit 2', 'Common tangent'), prop=fontP)
    
    
    plt.ticklabel_format(useOffset=False)
    
    plt.show()
    

    我们看到,我们没有获得公共切线:

    enter image description here

    2 回复  |  直到 8 年前
        1
  •  5
  •   user6655984 user6655984    8 年前

    符号根查找

    你的方程组由一个二次方程和一个三次方程组成。这种系统没有封闭形式的符号解。事实上,如果有,我们可以将其应用于一般的五次方程 x**5 + a*x**4 + ... = 0 通过介绍 y = x**2 (二次)并将原始方程改写为 x*y**2 + a*y**2 + ... = 0 (立方)。我们知道这一点 can't be done . 所以SymPy无法解决这一问题也就不足为奇了。你需要一个数值解算器(另一个原因是Symphy并不是专门用来解满是浮点常量的方程的,它们很难进行符号操作)。

    数字根查找

    SciPy fsolve 是我第一个想到的。您可以这样做:

    def F(x):
        x1, x2 = x[0], x[1]
        E1 = P(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) - P(x2, popt_14[1], popt_14[2], popt_14[3])
        E2 = ((BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - BM(x2, popt_14[0], popt_14[1], popt_14[2], popt_14[3])) / (x1 - x2)) - P(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
        return [E1, E2] 
    
    print fsolve(F, [50, 60])    # some reasonable initial point
    

    顺便说一下,我将从E2中的分母处移动(x1-x2),将E2重写为

    (...) - (x1 - x2) * P(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    

    所以系统是多项式的。这可能会使 fsolve 简单一点。

    范围约束:最小化

    也不 数值解 其亲属也不喜欢 root 支持在变量上设置边界。但你可以使用 least_squares 它将查找表达式E1,E2的平方和的最小值。它支持上限和下限,如果运气好的话,最小值(“成本”)将在机器精度范围内为0,表示您找到了根。一个抽象的例子(因为我没有你的数据):

    f1 = lambda x: 2*x**3 + 20
    df1 = lambda x: 6*x**2   # derivative of f1. 
    f2 = lambda x: (x-3)**3 + x
    df2 = lambda x: 3*(x-3)**2 + 1
    
    def eqns(x):
        x1, x2 = x[0], x[1]
        eq1 = df1(x1) - df2(x2)
        eq2 = df1(x1)*(x1 - x2) - (f1(x1) - f2(x2))
        return [eq1, eq2]
    
    from scipy.optimize import least_squares
    lb = (2, -2)   # lower bounds on x1, x2
    ub = (5, 3)    # upper bounds
    least_squares(eqns, [3, 1], bounds=(lb, ub))  
    

    输出:

     active_mask: array([0, 0])
            cost: 2.524354896707238e-29
             fun: array([7.10542736e-15, 0.00000000e+00])
            grad: array([1.93525199e-13, 1.34611132e-13])
             jac: array([[27.23625045, 18.94483256],
           [66.10672633, -0.        ]])
         message: '`gtol` termination condition is satisfied.'
            nfev: 8
            njev: 8
      optimality: 2.4802477446153134e-13
          status: 1
         success: True
               x: array([ 2.26968753, -0.15747203])
    

    成本非常小,所以我们有一个解决方案,它是x。通常,我们分配 最小二乘法 到某个变量 res 和访问 res.x 从那里开始。

        2
  •  2
  •   DavidC.    8 年前

    感谢所有@如果。。。。帮助,通过运行此答案末尾发布的以下代码,讨论了3条路径的结果:

    1) least_squares 默认公差:

    ####  ftol=1e-08, xtol=1e-08, gtol=1e-08  #####
    
    result =   active_mask: array([0, 0])
            cost: 4.7190963603923405e-10
             fun: array([  1.60076424e-05,   2.62216448e-05])
            grad: array([ -3.22762954e-09,  -4.72137063e-09])
             jac: array([[  2.70753295e-04,  -3.41257603e-04],
           [ -2.88378229e-04,   2.82727898e-05]])
         message: '`gtol` termination condition is satisfied.'
            nfev: 4
            njev: 4
      optimality: 2.398161337354571e-09
          status: 1
         success: True
               x: array([ 61.2569899,  59.7677843])
    result.x =  [ 61.2569899  59.7677843]
    
    
    
    slope_common_tangent =  -0.000533908881355
    

    成本为零,找到的公切线非常接近,但并不理想:

    enter image description here

    2) 最小二乘法 公差更紧:

    ####  ftol=1e-12, xtol=1e-12, gtol=1e-12  #####
    
    result_tight_tols =   active_mask: array([0, 0])
            cost: 4.3861335617475759e-20
             fun: array([  2.08437035e-10,   2.10420231e-10])
            grad: array([ -5.40980234e-16,  -7.19344843e-14])
             jac: array([[  2.69431398e-04,  -3.45167744e-04],
           [ -2.69462978e-04,   5.34965061e-08]])
         message: '`gtol` termination condition is satisfied.'
            nfev: 8
            njev: 8
      optimality: 7.6628451334260651e-15
          status: 1
         success: True
               x: array([ 61.35744106,  59.89347466])
    result_tight_tols.x =  [ 61.35744106  59.89347466]
    
    
    
    slope_common_tangent =  -0.000506777791299
    

    我原以为成本会更高,但由于某种原因我不明白,成本甚至更低。找到的公共切线更接近:

    enter image description here

    3) 使用 fsolve 但限制该地区

    我们在帖子中看到 x1, x2 = fsolve(equations, (50, 60)) ,找到的公共切线不正确(第2张和第3张图像)。然而,如果我们使用 x1, x2 = fsolve(equations, (61.5, 62)) :

    #### Using `fsolve`, but restricting the region:  ####
    
    
    x1 =  61.3574418449
    x2 =  59.8934758773
    slope_common_tangent =  -0.000506777580856
    

    我们发现,所发现的坡度与 最小二乘法 公差更严格。因此,找到的公切线也非常接近:

    enter image description here

    下表总结了结果:

    enter image description here

    产生以下三种途径的代码:

    import numpy as np
    from scipy.optimize import curve_fit
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties
    import sys
    from sympy import *
    import sympy as sym
    import os
    import pickle as pl
    
    
    # Intial candidates for fit, per FU: - thus, the E vs V input data has to be per FU
    E0_init = -941.510817926696  # -1882.50963222/2.0 
    V0_init = 63.54960592453 #125.8532/2.0 
    B0_init = 76.3746233515232 #74.49 
    B0_prime_init = 4.05340727164527 #4.15
    
    def BM(x, a, b, c, d):
             return  a + b*x + c*x**2 + d*x**3 
    
    def devBM(x, b, c, d):
             return  b + 2*c*x + 3*d*x**2 
    
    # Data 1 (Red triangles): 
    V_C_I, E_C_I = np.loadtxt('./1.dat', skiprows = 1).T
    
    # Data 14 (Empty grey triangles):
    V_14, E_14 = np.loadtxt('./2.dat', skiprows = 1).T
    
    init_vals = [E0_init, V0_init, B0_init, B0_prime_init]
    popt_C_I, pcov_C_I = curve_fit(BM, V_C_I, E_C_I, p0=init_vals)
    popt_14, pcov_14 = curve_fit(BM, V_14, E_14, p0=init_vals)
    
    
    def equations(p):
        x1, x2 = p
        E1 = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3]) - devBM(x2, popt_14[1], popt_14[2], popt_14[3])
        E2 = ((BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - BM(x2, popt_14[0], popt_14[1], popt_14[2], popt_14[3])) / (x1 - x2)) - devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
        return (E1, E2)
    
    from scipy.optimize import least_squares
    lb = (61.0, 59.0)   # lower bounds on x1, x2
    ub = (62.0, 60.0)   # upper bounds
    result = least_squares(equations, [61, 59], bounds=(lb, ub))
    result_tight_tols = least_squares(equations, [61, 59], ftol=1e-12, xtol=1e-12, gtol=1e-12, bounds=(lb, ub))
    
    print """
    ####  ftol=1e-08, xtol=1e-08, gtol=1e-08  #####
    """
    print 'result = ', result
    print 'result.x = ', result.x
    print """
    
    """
    x1 = result.x[0]
    x2 = result.x[1]
    
    slope_common_tangent = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    print 'slope_common_tangent = ', slope_common_tangent
    
    def comm_tangent(x, x1, slope_common_tangent):
       return BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - slope_common_tangent * x1 + slope_common_tangent * x
    
    # Linspace for plotting the fitting curves:
    V_C_I_lin = np.linspace(V_C_I[0]-2, V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0], V_14[-1]+2, 10000)
    
    
    plt.figure()
    
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b' )
    
    xp = np.linspace(54, 68, 100)
    pcomm_tangent, = plt.plot(xp, comm_tangent(xp, x1, slope_common_tangent), 'green', label='Common tangent')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='1', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='2', s=100)
    
    fontP = FontProperties()
    fontP.set_size('13')
    
    plt.legend((p1, p2, p5, p6, pcomm_tangent), ("1", "Cubic fit 1", "2", 'Cubic fit 2', 'Common tangent'), prop=fontP)
    plt.title('Least squares. Default tolerances: ftol=1e-08, xtol=1e-08, gtol=1e-08')
    
    plt.ticklabel_format(useOffset=False)
    
    ### Tighter tolerances:
    print """
    ####  ftol=1e-12, xtol=1e-12, gtol=1e-12  #####
    """
    print 'result_tight_tols = ', result_tight_tols
    print 'result_tight_tols.x = ', result_tight_tols.x
    print """
    
    """
    x1 = result_tight_tols.x[0]
    x2 = result_tight_tols.x[1]
    
    slope_common_tangent = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    print 'slope_common_tangent = ', slope_common_tangent
    
    def comm_tangent(x, x1, slope_common_tangent):
       return BM(x1, popt_C_I[0], popt_C_I[1], popt_C_I[2], popt_C_I[3]) - slope_common_tangent * x1 + slope_common_tangent * x
    
    # Linspace for plotting the fitting curves:
    V_C_I_lin = np.linspace(V_C_I[0]-2, V_C_I[-1], 10000)
    V_14_lin = np.linspace(V_14[0], V_14[-1]+2, 10000)
    
    
    plt.figure()
    
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b' )
    
    xp = np.linspace(54, 68, 100)
    pcomm_tangent, = plt.plot(xp, comm_tangent(xp, x1, slope_common_tangent), 'green', label='Common tangent')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='1', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='2', s=100)
    
    fontP = FontProperties()
    fontP.set_size('13')
    
    plt.legend((p1, p2, p5, p6, pcomm_tangent), ("1", "Cubic fit 1", "2", 'Cubic fit 2', 'Common tangent'), prop=fontP)
    plt.title('ftol=1e-08, xtol=1e-08, gtol=1e-08')
    
    plt.ticklabel_format(useOffset=False)
    
    plt.title('Lest Squares. Tightening tolerances: ftol=1e-12, xtol=1e-12, gtol=1e-12')
    
    print """
    #### Using `fsolve`, but restricting the region:  ####
    
    """
    
    from scipy.optimize import fsolve
    x1, x2 =  fsolve(equations, (61.5, 62))
    
    print 'x1 = ', x1
    print 'x2 = ', x2
    
    slope_common_tangent = devBM(x1, popt_C_I[1], popt_C_I[2], popt_C_I[3])
    print 'slope_common_tangent = ', slope_common_tangent
    
    plt.figure()
    
    # Plotting the fitting curves:
    p2, = plt.plot(V_C_I_lin, BM(V_C_I_lin, *popt_C_I), color='black' )
    p6, = plt.plot(V_14_lin, BM(V_14_lin, *popt_14), 'b' )
    
    xp = np.linspace(54, 68, 100)
    pcomm_tangent, = plt.plot(xp, comm_tangent(xp, x1, slope_common_tangent), 'green', label='Common tangent')
    
    # Plotting the scattered points: 
    p1 = plt.scatter(V_C_I, E_C_I, color='red', marker="^", label='1', s=100)
    p5 = plt.scatter(V_14, E_14, color='grey', marker="^", facecolors='none', label='2', s=100)
    
    fontP = FontProperties()
    fontP.set_size('13')
    
    plt.legend((p1, p2, p5, p6, pcomm_tangent), ("1", "Cubic fit 1", "2", 'Cubic fit 2', 'Common tangent'), prop=fontP)
    plt.ticklabel_format(useOffset=False)
    
    plt.title('Using `fsolve`, but restricting the region')
    
    
    
    plt.show()