PROJET PREMIERE 2000
Pour les motivés (et un peu matheux !)
Ecrire une fonction qui prend en argument une expression algébrique préfixée une variable et retourne la dérivée en préfixée également de cette expression par rapport à cette variable...
>>> (deriver '(+ 3 5) 'x) 0
>>> (deriver '(+ (+ (* a (* x x)) (* b x)) c ) 'x) (+ (* a (+ x x)) b)
>>> (deriver '(+ (+ (* a (* x x)) (* b x)) c ) 'b) x
Dans une première version, on peut supposer que l'expression algébrique ne comporte que les 4 opérations (+ ,-,*,/); on peut ensuite compliquer à souhait en rajoutant des fonctions (sin, cos, log, exp, etc...)
Texte derivation
;partie III la dérivation .... !!!
;---
; la dérivation
(define (deriver_in fonct var) ;derivee d'expression infixee (pre->in2 (deriver (in->pre2 fonct) var)))
; sous réserve de reprendre les utilitaires
; attention le fichier doit être dans le même dossier (load "pre-inf.scm")
;EVIDEMMENT AVEC LES UTILITAIRES VUS DANS LE PREMIER TD
; passage notation infixée <-> prefixée
;ON PEUT DERIVER...
; SOIT UNE EXPRESSION PREFIXEE, SOIT UNE EXPRESSION INFIXEE
; deriver ,d'apres l'enoncé, doit travailler sur une expression prefixée
; mais on peut faire toute manipulation sur la donnée comme sur le resultat
; MAINTENANT LES CHOSES SERIEUSES ....
; la dérivation est fondamentalement une opération récursive
; alors.... il suffit d'envisager les différents cas de dérivation
; constante --> 0
; x --> 1
; u + v --> u' + v'
; u . v --> u'.v + v'. u
; u / v --> (u'.v - v'. u) / v2
; f(u) --> u'. f'(u)
(define (deriver fonct var) ; derivee d'expression prefixee (cond ((constante? fonct) 0)
((variable? fonct) (if (meme_variable? fonct var) 1 0)) ((somme? fonct)
(effectuer_somme2
(car fonct)
(deriver (term1 fonct) var) (deriver (term2 fonct) var))) ((produit? fonct)
(effectuer_somme2 '+
(effectuer_produit2 (multiplicat fonct)
(deriver (multiplicand fonct) var)) (effectuer_produit2
(deriver (multiplicat fonct) var) (multiplicand fonct))))
((quotient? fonct) (deriver_quot fonct var)) ((exponent? fonct) (deriver_exp fonct var)) ;on a alors une fonction
(else (effectuer_produit2
(deriver (arg fonct) var) (deriver_fonct (nature fonct)
(arg fonct) var))))) (define (deriver_quot fonct var)
(if (fonction? (denom fonct) var) ;denom fonction de var ?
(effectuer_quotient (effectuer_somme2 '-
(effectuer_produit2
(deriver (num fonct) var) (denom fonct))
(effectuer_produit2 (num fonct)
(deriver (denom fonct) var))) (list '** (denom fonct) 2))
(effectuer_quotient (deriver (num fonct) var) (denom fonct))))
;** sert à représenter l'exponentiation ...
(define (deriver_exp fonct var)
(if (not (fonction? (exposant fonct) var))
;expo non fonction de var ? (effectuer_produit2
(effectuer_produit2 (exposant fonct)
(deriver(mant fonct) var)) (effectuer_expo (mant fonct)
(effectuer_somme2 '-
(exposant fonct) 1)))
(deriver (list 'exp (list '*
(exposant fonct)
(list 'log (mant fonct)))) var)))
(define (deriver_fonct fonct arg var)
(cond ((eq? fonct 'sin) (list 'cos arg)) ((eq? fonct 'cos) (list '- 'sin arg)) ((eq? fonct 'tan) (list '+ 1
(list '**
(list fonct arg ) 2))) ((eq? fonct 'log) (effectuer_quotient 1 arg))
((eq? fonct 'exp) (if (and (produit? arg) (log_arg? arg)) ; un des arg est log
(cons '** (list_arg_expo arg)) (list 'exp arg)))))
(define (constante? x)
(number? x))
(define (variable? x) (symbol? x))
(define (meme_variable? x y)
(and (variable? x) (variable? y) (eq? x y))) (define (somme? fonct)
(and (not (atom? fonct))(or (eq? (car fonct) '+) (eq? (car fonct) '-))))
(define (atom? x) (not (list? x))) (define (produit? fonct)
(and (not (atom? fonct))(eq? (car fonct) '*))) (define (quotient? fonct)
(and (not (atom? fonct))(eq? (car fonct) '/))) (define (exponent? fonct)
; la puissance s'écrit par une double étoile (and (not (atom? fonct))(eq? (car fonct) '**))) (define (term1 fonct)
(cadr fonct))
(define (term2 fonct) (caddr fonct))
(define (multiplicat fonct) (cadr fonct))
(define (multiplicand fonct) (caddr fonct))
(define (num fonct) (cadr fonct))
(define (denom fonct) (caddr fonct)) (define (mant fonct) (cadr fonct))
(define (exposant fonct) (caddr fonct))
(define (nature fonct) (car fonct))
(define (log_arg? arg) ; arg est un produit verifie si existe un log (let ((arg1 (multiplicat arg))
(arg2 (multiplicand arg))) (or (and (not (atom? arg1))
(eq? 'log (car arg1))) (and (not (atom? arg2))
(eq? 'log (car arg2))))))
(define (list_arg_expo arg)
; arg est un produit dont un argument est log, et retourne ; une liste dont le car est l'arg du log
; et le cdr l'autre arg listé (let ((arg1 (multiplicat arg))
(arg2 (multiplicand arg))) (if (eq? (car arg1) 'log) (list (cadr arg1) arg2) (list (cadr arg2) arg1)))) (define (arg fonct)
(cadr fonct))
(define (fonction? fonct var)
; cherche si var appartient à la fonction (if (atom? fonct)
(eq? fonct var)
(or (fonction? (cadr fonct) var) (fonction? (caddr fonct) var)))) (define (effectuer_somme oper x y)
(list oper x y))
(define (effectuer_somme2 oper x y) (cond ((and (number? x)
(number? y)) (if (eq? oper '+) (+ x y)(- x y))) ((and (number? x)(zero? x)) (if (eq? oper '-)
(list '- y) y)) ((and (number? y)(zero? y)) x)
(else (list oper x y)))) (define (effectuer_produit x y) ;on peut simplifier;
(list '* x y))
(define (effectuer_produit2 x y) (cond ((and (number? x)
(number? y) (* x y))) ((number? x)(cond ((zero? x) 0) ((= 1 x) y)
((= -1 x) (list '- y)) (else (list '* x y)))) ((number? y) (cond ((zero? y) 0)
((= 1 y) x)
((= -1 y) (list '- x)) (else (list '* x y)))) ((and (quotient? x)(= 1 (cadr x)))
(list '/ y (caddr x))) ((and (quotient? y)(= 1 (cadr y))) (list '/ x (caddr y) )) (else (list '* x y))))
(define (effectuer_quotient x y) (cond ((and (number? x)
(number? y)) (/ x y)) ((and(number? y)(= 1 y) x))
(else (list '/ x y)))) (define (effectuer_expo x y) (cond ((and (number? x)
(number? y)) (expt x y)) ((number? y)(cond ((zero? y) 1) ((= 1 y) x)
((= -1 y) (list '/ 1 x)) (else (list '** x y)))) (else (list '** x y))))
; execution version 1 de effectuer-sommme et produit
;...les simplifications ne sont pas faites !
;>>> (define fonct '(* (+ x a) (+ x y)))
;fonct
;>>> fonct
;(* (+ x a) (+ x y))
;>>>(deriver fonct 'x)
;(+ (* (+ x a) (+ 1 0)) (* (+ 1 0) (+ x y)))
; execution version 2 pour somme , version 1 pour produit
;>>>(deriver fonct 'x)
;(+ (* (+ x a) 1) (* 1 (+ x y)))
; execution version 2 pour somme et produit
;>>>(deriver fonct 'x)
;(+ (+ x a) (+ x y))
;>>> (define trinome '(+ (+ (* a (* x x)) (* b x)) c))
;trinome
;>>> (deriver trinome 'x)
;(+ (* a (+ x x)) b)