Problèmes fréquents concernant les fonctions¶
La définition de fonctions, par exemple pour calculer leurs dérivées ou tracer leurs courbes représentatives, donne lieu à un certain nombre de confusions. Le but de cette section est de clarifier quelques points à l’origine de ces confusions.
Il y a plusieurs façons de définir un objet que l’on peut légitimement appeler « fonction ».
1. Définir une fonction Python, comme expliqué dans la section Fonctions, indentation et itération. Les fonctions Python peuvent être utilisées pour tracer des courbes, mais pas dérivées ou intégrées symboliquement:
sage: def f(z): return z^2
sage: type(f)
<... 'function'>
sage: f(3)
9
sage: plot(f, 0, 2)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> def f(z): return z**Integer(2)
>>> type(f)
<... 'function'>
>>> f(Integer(3))
9
>>> plot(f, Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
def f(z): return z^2 type(f) f(3) plot(f, 0, 2)
Remarquez la syntaxe de la dernière ligne. Écrire plutôt plot(f(z), 0, 2)
provoquerait une erreur : en effet, le z
qui apparaît dans
la définition de f
est une variable muette qui n’a pas de sens
en dehors de la définition. Un simple f(z)
déclenche la même erreur.
En l’occurrence, faire de z
une variable symbolique comme dans
l’exemple ci-dessous fonctionne, mais cette façon de faire soulève
d’autres problèmes (voir le point 4 ci-dessous), et il vaut mieux
s’abstenir de l’utiliser.
sage: var('z') # on définit z comme variable symbolique
z
sage: f(z)
z^2
sage: plot(f(z), 0, 2)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> var('z') # on définit z comme variable symbolique
z
>>> f(z)
z^2
>>> plot(f(z), Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
var('z') # on définit z comme variable symbolique f(z) plot(f(z), 0, 2)
L’appel de fonction f(z)
renvoie ici l’expression symbolique
z^2
, qui est alors utilisée par la fonction plot
.
2. Définir une expression symbolique fonctionnelle (« appelable »). Une telle expression représente une fonction dont on peut tracer le graphe, et que l’on peut aussi dériver ou intégrer symboliquement
sage: g(x) = x^2
sage: g # g envoie x sur x^2
x |--> x^2
sage: g(3)
9
sage: Dg = g.derivative(); Dg
x |--> 2*x
sage: Dg(3)
6
sage: type(g)
<class 'sage.symbolic.expression.Expression'>
sage: plot(g, 0, 2)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> __tmp__=var("x"); g = symbolic_expression(x**Integer(2)).function(x)
>>> g # g envoie x sur x^2
x |--> x^2
>>> g(Integer(3))
9
>>> Dg = g.derivative(); Dg
x |--> 2*x
>>> Dg(Integer(3))
6
>>> type(g)
<class 'sage.symbolic.expression.Expression'>
>>> plot(g, Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
g(x) = x^2 g # g envoie x sur x^2 g(3) Dg = g.derivative(); Dg Dg(3) type(g) plot(g, 0, 2)
Notez que, si g
est une expression symbolique fonctionnelle
(x |--> x^2
), l’objet g(x)
(x^2
) est d’une nature un
peu différente. Les expressions comme g(x)
peuvent aussi être
tracées, dérivées, intégrées, etc., avec cependant quelques difficultés
illustrées dans le point 5 ci-dessous.
sage: g(x)
x^2
sage: type(g(x))
<class 'sage.symbolic.expression.Expression'>
sage: g(x).derivative()
2*x
sage: plot(g(x), 0, 2)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> g(x)
x^2
>>> type(g(x))
<class 'sage.symbolic.expression.Expression'>
>>> g(x).derivative()
2*x
>>> plot(g(x), Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
g(x) type(g(x)) g(x).derivative() plot(g(x), 0, 2)
3. Utiliser une fonction usuelle prédéfinie de Sage. Celles-ci peuvent servir à tracer des courbes, et, indirectement, être dérivées ou intégrées
sage: type(sin)
<class 'sage.functions.trig.Function_sin'>
sage: plot(sin, 0, 2)
Graphics object consisting of 1 graphics primitive
sage: type(sin(x))
<class 'sage.symbolic.expression.Expression'>
sage: plot(sin(x), 0, 2)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> type(sin)
<class 'sage.functions.trig.Function_sin'>
>>> plot(sin, Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
>>> type(sin(x))
<class 'sage.symbolic.expression.Expression'>
>>> plot(sin(x), Integer(0), Integer(2))
Graphics object consisting of 1 graphics primitive
type(sin) plot(sin, 0, 2) type(sin(x)) plot(sin(x), 0, 2)
Il n’est pas possible de dériver la fonction sin
tout court pour
obtenir cos
sage: f = sin
sage: f.derivative()
Traceback (most recent call last):
...
AttributeError: ...
>>> from sage.all import *
>>> f = sin
>>> f.derivative()
Traceback (most recent call last):
...
AttributeError: ...
f = sin f.derivative()
Une possibilité est de remplacer f = sin
par f = sin(x)
, mais il
est généralement préférable de définir une expression symbolique
fonctionnelle f(x) = sin(x)
sage: S(x) = sin(x)
sage: S.derivative()
x |--> cos(x)
>>> from sage.all import *
>>> __tmp__=var("x"); S = symbolic_expression(sin(x)).function(x)
>>> S.derivative()
x |--> cos(x)
S(x) = sin(x) S.derivative()
Examinons maintenant quelques problèmes fréquents.
4. Évaluation accidentelle
sage: def h(x):
....: if x < 2:
....: return 0
....: else:
....: return x-2
>>> from sage.all import *
>>> def h(x):
... if x < Integer(2):
... return Integer(0)
... else:
... return x-Integer(2)
def h(x): if x < 2: return 0 else: return x-2
Problème : plot(h(x), 0, 4)
trace la droite \(y = x - 2\), et non pas la
fonction affine par morceaux définie par h
. Pourquoi ? Lors de l’exécution,
plot(h(x), 0, 4)
évalue d’abord h(x)
: la fonction
Python h
est appelée avec le paramètre x
, et la condition x < 2
est donc évaluée.
sage: type(x < 2)
<class 'sage.symbolic.expression.Expression'>
>>> from sage.all import *
>>> type(x < Integer(2))
<class 'sage.symbolic.expression.Expression'>
type(x < 2)
Or, l’évaluation d’une inégalité symbolique renvoie False
quand la
condition n’est pas clairement vraie. Ainsi, h(x)
s’évalue en
x - 2
, et c’est cette expression-là qui est finalement tracée.
Solution : Il ne faut pas utiliser plot(h(x), 0, 4)
, mais plutôt
sage: def h(x):
....: if x < 2:
....: return 0
....: else:
....: return x-2
sage: plot(h, 0, 4)
Graphics object consisting of 1 graphics primitive
>>> from sage.all import *
>>> def h(x):
... if x < Integer(2):
... return Integer(0)
... else:
... return x-Integer(2)
>>> plot(h, Integer(0), Integer(4))
Graphics object consisting of 1 graphics primitive
def h(x): if x < 2: return 0 else: return x-2 plot(h, 0, 4)
5. Constante plutôt que fonction
sage: f = x
sage: g = f.derivative()
sage: g
1
>>> from sage.all import *
>>> f = x
>>> g = f.derivative()
>>> g
1
f = x g = f.derivative() g
Problème : g(3)
déclenche une erreur avec le message « ValueError:
the number of arguments must be less than or equal to 0 ».
sage: type(f)
<class 'sage.symbolic.expression.Expression'>
sage: type(g)
<class 'sage.symbolic.expression.Expression'>
>>> from sage.all import *
>>> type(f)
<class 'sage.symbolic.expression.Expression'>
>>> type(g)
<class 'sage.symbolic.expression.Expression'>
type(f) type(g)
En effet, g
n’est pas une fonction, mais une constante, sans
variable en laquelle on peut l’évaluer.
Solution : il y a plusieurs possibilités.
Définir
f
comme une expression symbolique fonctionnellesage: f(x) = x # au lieu de 'f = x' sage: g = f.derivative() sage: g x |--> 1 sage: g(3) 1 sage: type(g) <class 'sage.symbolic.expression.Expression'>
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(x ).function(x)# au lieu de 'f = x' >>> g = f.derivative() >>> g x |--> 1 >>> g(Integer(3)) 1 >>> type(g) <class 'sage.symbolic.expression.Expression'>
f(x) = x # au lieu de 'f = x' g = f.derivative() g g(3) type(g)
Ou, sans changer la définition de
f
, définirg
comme une expression symbolique fonctionnellesage: f = x sage: g(x) = f.derivative() # au lieu de 'g = f.derivative()' sage: g x |--> 1 sage: g(3) 1 sage: type(g) <class 'sage.symbolic.expression.Expression'>
>>> from sage.all import * >>> f = x >>> __tmp__=var("x"); g = symbolic_expression(f.derivative() ).function(x)# au lieu de 'g = f.derivative()' >>> g x |--> 1 >>> g(Integer(3)) 1 >>> type(g) <class 'sage.symbolic.expression.Expression'>
f = x g(x) = f.derivative() # au lieu de 'g = f.derivative()' g g(3) type(g)
Ou encore, avec
f
etg
définies comme dans l’exemple de départ, donner explicitement la variable à remplacer par sa valeursage: f = x sage: g = f.derivative() sage: g 1 sage: g(x=3) # au lieu de 'g(3)' 1
>>> from sage.all import * >>> f = x >>> g = f.derivative() >>> g 1 >>> g(x=Integer(3)) # au lieu de 'g(3)' 1
f = x g = f.derivative() g g(x=3) # au lieu de 'g(3)'
Nous terminons en mettant encore une fois en évidence la différence entre
les dérivées des expressions f
définies par f = x
et par f(x)
= x
sage: f(x) = x
sage: g = f.derivative()
sage: g.variables() # variables apparaissant dans g
()
sage: g.arguments() # paramètres auxquels on peut donner une valeur dans g
(x,)
sage: f = x
sage: h = f.derivative()
sage: h.variables()
()
sage: h.arguments()
()
>>> from sage.all import *
>>> __tmp__=var("x"); f = symbolic_expression(x).function(x)
>>> g = f.derivative()
>>> g.variables() # variables apparaissant dans g
()
>>> g.arguments() # paramètres auxquels on peut donner une valeur dans g
(x,)
>>> f = x
>>> h = f.derivative()
>>> h.variables()
()
>>> h.arguments()
()
f(x) = x g = f.derivative() g.variables() # variables apparaissant dans g g.arguments() # paramètres auxquels on peut donner une valeur dans g f = x h = f.derivative() h.variables() h.arguments()
Comme l’illustre cet exemple, h
n’accepte pas de paramètres. C’est
pour cela que h(3)
déclenche une erreur.