Reputation: 79
①Why is it that the above source code can be used to create a plot, but the following source code cannot?
②Can you point me to a web site that has a table comparing (matplotlib) and (SymPy Plotting Module)?
③(matplotlib) to (SymPy Plotting Module) converter and a (SymPy Plotting Module) to (matplotlib) converter would be helpful.
from sympy import *
def define_fn(n):
def fn(x):
if n <= x <= n + 1:
return float(x) - n
elif n + 1 <= x <= n + 2:
return 2.0 - x + n
else:
return 0.0
return fn
f3 = define_fn(3)
f8 = define_fn(8)
print("#",f3)
print("#",f8)
plot(f3,f8)
# <function define_fn.<locals>.fn at 0x000002474E838280>
# <function define_fn.<locals>.fn at 0x000002474E838310>
# SymPyDeprecationWarning: .............
Upvotes: 0
Views: 769
Reputation: 79
print("#",type(f3),f3)
print("#",type(f8),f8)
# <class 'function'> <function define_fn.<locals>.fn at 0x00000246464B9280>
# <class 'function'> <function define_fn.<locals>.fn at 0x00000246464B9310>
print("#",type(f3(x)),f3(x))
print("#",type(f8(x)),f8(x))
# Piecewise Piecewise((x - 3, (x >= 3) & (x <= 4)), (5 - x, (x >= 4) & (x <= 5)), (0, True))
# Piecewise Piecewise((x - 8, (x >= 8) & (x <= 9)), (10 - x, (x >= 9) & (x <= 10)), (0, True))
print("#",type(f3),f3)
print("#",type(f8),f8)
# Piecewise Piecewise((x - 3, (x >= 3) & (x <= 4)), (5 - x, (x >= 4) & (x <= 5)), (0, True))
# Piecewise Piecewise((x - 8, (x >= 8) & (x <= 9)), (10 - x, (x >= 9) & (x <= 10)), (0, True))
Upvotes: 0
Reputation: 231738
Let's make sure you understand what the link and your adaptation is doing. Your question about the difference in the plot packages suggests you don't have a clear idea of what package is doing what.
You have defined two python functions, that take one number.
In [11]: f3(4)
Out[11]: 1.0
In [12]: f8(9)
Out[12]: 1.0
With just python we can create a list of x
values:
In [17]: x = [i / 10 for i in range(120)]
the corresponding y
values:
In [18]: y1 = [f3(i) for i in x]
In [19]: y2 = [f8(i) for i in x]
and plot them with:
In [20]: plt.plot(x, y1, x, y2)
Out[20]:
[<matplotlib.lines.Line2D at 0x7fe2589385e0>,
<matplotlib.lines.Line2D at 0x7fe258938610>]
# plotted as you show
The link use np.linspace
to create the x
values as an array, and np.vectorize
to apply the function(s) to all these values. matplotlib
works with both arrays and lists.
There's nothing fancy about this use of matplotlib
.
Statements like:
if n <= x <= n + 1:
return float(x) - n
only work with single numbers. That's basic python. Using a numpy array for x
or a sympy symbol
or expression
will result in an error.
If x
is a sympy
symbol:
In [3]: f3(x)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [3], in <module>
----> 1 f3(x)
Input In [1], in define_fn.<locals>.fn(x)
2 def fn(x):
----> 3 if n <= x <= n + 1:
4 return float(x) - n
5 elif n + 1 <= x <= n + 2:
File /usr/local/lib/python3.8/dist-packages/sympy/core/relational.py:398, in Relational.__bool__(self)
397 def __bool__(self):
--> 398 raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational
and with an array:
In [4]: f3(np.arange(3))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [4], in <module>
----> 1 f3(np.arange(3))
Input In [1], in define_fn.<locals>.fn(x)
2 def fn(x):
----> 3 if n <= x <= n + 1:
4 return float(x) - n
5 elif n + 1 <= x <= n + 2:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Upvotes: 2
Reputation: 80524
①Why is it that the above source code can be used to create a plot, but the following source code cannot?
The linked example uses matplotlib which works with numeric inputs. Matplotlib doesn't know about sympy's world.
Sympy's plot module converts sympy expressions to numeric approximations and plots them using matplotlib. Sympy's plot module abstracts away a lot of intricacies to make this work, and hides these from the casual user.
②Can you point me to a web site that has a table comparing (matplotlib) and (SymPy Plotting Module)?
Matplotlib is very huge. Sympy's plotting module uses a subset of functionality, carefully and ingeniously adapted to the symbolic world. Differences don't fit into a table. Matplotlib's extensive documentation can be found at matplotlib.org, but most people only look into the subset they are using. Sympy's plotting documentation fits onto one large webpage. For both libraries you will need extra tutorials, StackOverlow, and maybe diving into the freely available source code if you need functionality that isn't readily available.
③(matplotlib) to (SymPy Plotting Module) converter and a (SymPy Plotting Module) to (matplotlib) converter would be helpful.
That would be a titanic work, with lots of undefined cases. Sympy (as well as matplotlib) is developed by very talented volunteers, with limited resources.
Note that, if you really want to, you can "move" sympy plots to the matplotlib world and extend the plot there.
Here is how your source code could look like in sympy. First some remarks:
if
-tests, you need symbolic functions such as PieceWise
instead.float(x)
doesn't work for sympy's symbolsfrom sympy import plot, Symbol, Piecewise, And
def define_fn(n):
def fn(x):
return Piecewise((x - n, (n <= x) & (x <= n + 1)),
(2 - x + n, (n + 1 <= x) & (x <= n + 2)),
(0, True))
return fn
f3 = define_fn(3)
f8 = define_fn(8)
x = Symbol('x', real=True)
plot(f3(x), f8(x), (x, -1, 11))
Although this works, it is not sympy's standard way. Usually, functions are written as expressions. Note how f3
is used as an expression that contains x
, instead of the less flexible f3(x)
of the previous example.
from sympy import plot, Symbol, Piecewise, And
x = Symbol('x', real=True)
n = Symbol('n', real=True)
fn = Piecewise((x - n, (n <= x) & (x <= n + 1)),
(2 - x + n, (n + 1 <= x) & (x <= n + 2)),
(0, True))
f3 = fn.subs(n, 3) # Piecewise((x - 3, (x >= 3) & (x <= 4)), (5 - x, (x >= 4) & (x <= 5)), (0, True))
f8 = fn.subs(n, 8) # Piecewise((x - 8, (x >= 8) & (x <= 9)), (10 - x, (x >= 9) & (x <= 10)), (0, True))
plot(f3, f8, (x, -1, 11))
Upvotes: 1