是否可以使用Matplotlib绘制隐式方程?

时间:2010-03-20 20:00:30

标签: python matplotlib equation implicit sympy

我想在Matplotlib中绘制隐式方程(形式为f(x,y)= g(x,y),例如X ^ y = y ^ x)。这可能吗?

8 个答案:

答案 0 :(得分:25)

我不相信对此有很好的支持,但你可以尝试像

这样的东西
import matplotlib.pyplot
from numpy import arange
from numpy import meshgrid

delta = 0.025
xrange = arange(-5.0, 20.0, delta)
yrange = arange(-5.0, 20.0, delta)
X, Y = meshgrid(xrange,yrange)

# F is one side of the equation, G is the other
F = Y**X
G = X**Y

matplotlib.pyplot.contour(X, Y, (F - G), [0])
matplotlib.pyplot.show()

请参阅API docs contour:如果第四个参数是一个序列,则它指定要绘制的轮廓线。但是情节只会与你的范围的分辨率一样好,并且有些特征可能永远不会正确,通常是在自相交点。

答案 1 :(得分:19)

由于你用sympy标记了这个问题,我将举一个这样的例子。

来自文档:http://docs.sympy.org/latest/modules/plotting.html

from sympy import var, plot_implicit
var('x y')
plot_implicit(x*y**3 - y*x**3)

答案 2 :(得分:7)

matplotlib不绘制方程;它描绘了积分。您可以使用scipy​.optimize之类的工具以数字方式从数值计算隐含方程的x值(反之亦然)或任意数量的其他工具来计算y点。


例如,这是一个我在某个区域绘制隐式方程x ** 2 + x * y + y ** 2 = 10的例子。

from functools import partial

import numpy
import scipy.optimize
import matplotlib.pyplot as pp

def z(x, y):
    return x ** 2 + x * y + y ** 2 - 10

x_window = 0, 5
y_window = 0, 5

xs = []
ys = []
for x in numpy.linspace(*x_window, num=200):
    try:
        # A more efficient technique would use the last-found-y-value as a 
        # starting point
        y = scipy.optimize.brentq(partial(z, x), *y_window)
    except ValueError:
        # Should we not be able to find a solution in this window.
        pass
    else:
        xs.append(x)
        ys.append(y)

pp.plot(xs, ys)
pp.xlim(*x_window)
pp.ylim(*y_window)
pp.show()

答案 3 :(得分:4)

在同情中有一个隐式方程(和不等式)绘图仪。它是作为GSoC的一部分创建的,它以matplotlib图形实例的形式生成图。

http://docs.sympy.org/latest/modules/plotting.html#sympy.plotting.plot_implicit.plot_implicit

的文档

自从症状版本0.7.2以来,它可以作为:

>>> from sympy.plotting import plot_implicit
>>> p = plot_implicit(x < sin(x)) # also creates a window with the plot
>>> the_matplotlib_axes_instance = p._backend._ax

答案 4 :(得分:3)

如果你愿意使用matplotlib以外的东西(但仍然是python),那就是圣人:

示例:http://sagenb.org/home/pub/1806

Documentation for implicit_plot

The Sage Homepage

答案 5 :(得分:1)

非常感谢Steve,Mike,Alex。我已经接受了史蒂夫的解决方案(请参阅下面的代码)。我唯一剩下的问题是轮廓图出现在我的网格线后面,而不是常规的情节,我可以用zorder强制到前面。任何更多的halp非常感谢。

干杯, 格迪斯

import matplotlib.pyplot as plt 
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import numpy as np 

fig = plt.figure(1) 
ax = fig.add_subplot(111) 

# set up axis 
ax.spines['left'].set_position('zero') 
ax.spines['right'].set_color('none') 
ax.spines['bottom'].set_position('zero') 
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom') 
ax.yaxis.set_ticks_position('left') 

# setup x and y ranges and precision
x = np.arange(-0.5,5.5,0.01) 
y = np.arange(-0.5,5.5,0.01)

# draw a curve 
line, = ax.plot(x, x**2,zorder=100) 

# draw a contour
X,Y=np.meshgrid(x,y)
F=X**Y
G=Y**X
ax.contour(X,Y,(F-G),[0],zorder=100)

#set bounds 
ax.set_xbound(-1,7)
ax.set_ybound(-1,7) 

#produce gridlines of different colors/widths
ax.xaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.yaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.xaxis.grid(True,'minor',linestyle='-')
ax.yaxis.grid(True,'minor',linestyle='-') 

minor_grid_lines = [tick.gridline for tick in ax.xaxis.get_minor_ticks()] 
for idx,loc in enumerate(ax.xaxis.get_minorticklocs()): 
    if loc % 2.0 == 0:
        minor_grid_lines[idx].set_color('0.3')
        minor_grid_lines[idx].set_linewidth(2)
    elif loc % 1.0 == 0:
        minor_grid_lines[idx].set_c('0.5')
        minor_grid_lines[idx].set_linewidth(1)
    else:
        minor_grid_lines[idx].set_c('0.7')
        minor_grid_lines[idx].set_linewidth(1)

minor_grid_lines = [tick.gridline for tick in ax.yaxis.get_minor_ticks()] 
for idx,loc in enumerate(ax.yaxis.get_minorticklocs()): 
    if loc % 2.0 == 0:
        minor_grid_lines[idx].set_color('0.3')
        minor_grid_lines[idx].set_linewidth(2)
    elif loc % 1.0 == 0:
        minor_grid_lines[idx].set_c('0.5')
        minor_grid_lines[idx].set_linewidth(1)
    else:
        minor_grid_lines[idx].set_c('0.7')
        minor_grid_lines[idx].set_linewidth(1)

plt.show()

答案 6 :(得分:1)

编辑:如果使用plt.plot()绘制双曲线,则会获得不希望的分支效果。 plt.scatter()仍然可以正常工作。这样就无需反转负值或正值的顺序,但是如果您出于某种原因(而不是使用scipy的等高线图)使用此代码,则无论如何都可以使用plt.scatter()

二维隐式函数通常可以写为:

f(x,y)= 0

由于我们不能将其写为f(x)= y,所以我们无法根据易于编程的离散x集合计算y。但是,有可能看到从网格生成的点与真实函数的距离有多近。

因此,将x和y栅格化为自定义点密度,并查看每个点与满足方程式的接近程度。

换句话说,如果我们不能使f(x,y)= 0,也许我们可以接近0。而不是寻找f(x,y)= 0,而是寻找f(x,y) >-\ epsilon和f(x,y)<\ epsilon。

\ epsilon是您的公差,如果此条件适合您的公差0,并适当调整网格,则可以绘制函数。

下面的代码仅对半径为1的圆(f(x,y)= x ^ 2 + y ^ 2 -1 = 0)进行处理。我将符号dr用作\ epsilon。

此外,为确保plt.plot函数以正确的顺序连接线,我将x值的反向版本用于y负值。这样,f(x,y)的求值是在顺时针循环中完成的,因此最接近的值是一个接一个的。如果没有此功能,则来自该功能相反两侧的线将连接起来,并且看起来将被略微填充。

import numpy as np
import matplotlib.pyplot as plt
r = 1 #arbitrary radius to set up the span of points
points = 250 
dr = r/points #epsilon window 

x=list(np.linspace(-5*r,5*r,5*points+1)) #setting up the x,y grid
y=x

xreversed = reversed(x) #reversing the array

x_0=[] #placeholder arrays
y_0=[]

for i in x:
    for j in y:
        if i**2 + j**2 -1 < dr and i**2+j**2 -1 > -dr  and j >= 0: #positive values of y
            x_0.append(i)
            y_0.append(j)
for i in xreversed:            
    for j in y:
        if i**2+j**2 -1 < dr and i**2+j**2 -1 > -dr  and j < 0: #negative values of y, using x reversed
            x_0.append(i)
            y_0.append(j)

plt.plot(x_0,y_0)
plt.show()

答案 7 :(得分:0)

所有圆锥形截面的示例(使用轮廓法)可在http://blog.mmast.net/conics-matplotlib

中找到。