Domanda

Sto scrivendo un programma in Python e ho bisogno di trovare la derivata di una funzione (funzione espresso come stringa).

  • Per esempio: x^2+3*x
  • La sua derivata è: 2*x+3

Ci sono tutti gli script disponibili, o c'è qualcosa di utile si può dire di me?

È stato utile?

Soluzione

sympy lo fa bene.

Altri suggerimenti

Se si sono limitati a polinomi (che sembra essere il caso), ci sarebbero fondamentalmente tre fasi:

  1. Analizzare la stringa di input in un elenco di coefficienti per x ^ n
  2. Prendi questo elenco di coefficienti e li converte in un nuovo elenco di coefficienti in base alle regole per derivare un polinomio.
  3. Prendere l'elenco dei coefficienti per il derivato e creare una bella stringa che descrive la funzione polinomiale derivata.

Se è necessario gestire polinomi come a*x^15125 + x^2 + c, utilizzando un dict per l'elenco dei coefficienti può avere senso, ma richiedono un po 'più di attenzione quando si fa le iterazioni attraverso questa lista.

Potete trovare che cosa state cercando le risposte già fornite.Io, però, vorrei dare una breve spiegazione su come calcolare simbolico derivati.

Il business è basato su overload dell'operatore e la catena regola dei derivati.Per esempio, la derivata di v^n è n*v^(n-1)dv/dx, giusto?Quindi, se avete v=3*x e n=3, cosa sarebbe derivato essere?La risposta:se f(x)=(3*x)^3, quindi la derivata è:

f'(x)=3*(3*x)^2*(d/dx(3*x))=3*(3*x)^2*(3)=3^4*x^2

La catena regola consente di "catena" l'operazione:ogni singolo derivati è semplice, e basta "catena" la complessità.Un altro esempio, la derivata di u*v è v*du/dx+u*dv/dx, giusto?Se si ottiene una funzione complicata, è solo la catena a dire:

d/dx(x^3*sin(x))
u=x^3; v=sin(x)
du/dx=3*x^2; dv/dx=cos(x)
d/dx=v*du+u*dv

Come si può vedere, la differenziazione è solo una catena di operazioni semplici.

Ora, l'overload dell'operatore.

Se è possibile scrivere un parser (provare Pyparsing), allora si può chiedere di valutare sia la funzione e derivati!Questo l'ho fatto io (usando Flex/Bison) solo per divertimento, ed è abbastanza potente.Per voi per ottenere l'idea, il derivato è calcolata in modo ricorsivo per sovraccaricare il corrispondente operatore, e di applicare ricorsivamente la catena di regola, quindi, la valutazione di "*" corrisponderebbe a u*v per il valore della funzione e u*der(v)+v*der(u) per i derivati a valore di (provare in C++, è anche divertente).

Così ci si va, so che a te non significa scrivere il proprio parser - con tutti i mezzi utilizzare il codice esistente (visita www.autodiff.org per la differenziazione automatica di Fortran e il codice C/C++).Ma è sempre interessante sapere come questa roba funziona.

Ciao

Juan

differenziazione simbolica è un'introduzione impressionante con l'oggetto, almeno per non specialista come me :) Il codice è scritto in C ++ btw.

Meglio tardi che mai?

ho sempre fatto differenziazione simbolica in qualsiasi lingua, lavorando con un albero sintattico. Ma ho anche recentemente venuto a conoscenza di un altro metodo che utilizza numeri complessi .

L'approccio albero di analisi consiste nella traduzione il seguente codice Lisp piccolo in qualunque lingua che ti piace:

(defun diff (s x)(cond
  ((eq s x) 1)
  ((atom s) 0)
  ((or (eq (car s) '+)(eq (car s) '-))(list (car s)
    (diff (cadr s) x)
    (diff (caddr s) x)
    ))
  ; ... and so on for multiplication, division, and basic functions
  ))

e in seguito con un semplificatore del caso, in modo da sbarazzarsi di aggiunte di 0, moltiplicando per 1, ecc.

Ma il metodo complesso, mentre completamente numerico, ha una qualità magica. Invece di programmare il calcolo F a doppia precisione, farlo in doppia precisione complessa. Quindi, se è necessario il derivato del calcolo rispetto alla variabile X, impostare la parte immaginaria X per un numero molto piccolo h, come 1e-100. Poi fare il calcolo e ottenere il risultato R. Ora reale (R) è il risultato che normalmente ottenere, e imag (R) / h = dF / dx ad altissima precisione!

Come funziona? Prendiamo il caso di moltiplicare numeri complessi:

(a+bi)(c+di) = ac + i(ad+bc) - bd

Ora supponiamo parti immaginarie sono tutti a zero, tranne che vogliamo che la derivata rispetto al a. Abbiamo impostato b ad un numero molto piccolo h. Ora cosa otteniamo?

(a+hi)(c) = ac + hci

Quindi, la parte reale di questo è ac, come ci si aspetterebbe, e la parte immaginaria, divisa per h, è c, che è la derivata di ac rispetto alle a.

Lo stesso tipo di ragionamento sembra applicarsi a tutte le regole di differenziazione.

Se state pensando di scrivere il programma di differenziazione da zero, senza utilizzare altre librerie come l'aiuto, allora l'algoritmo / approccio di calcolare la derivata di un'equazione algebrica ho descritto nel il mio blog sarà utile.

Si può provare a creare una classe che rappresenterà un limite rigoroso e quindi valutare per (f (x) -f (a)) / (x-a) come x si avvicina a. Questo dovrebbe dare un valore abbastanza preciso del limite.

A meno che qualsiasi libreria già fatto deriva è abbastanza complesso perché è necessario analizzare e gestire le funzioni e le espressioni.

derivanti da sola è un compito facile, dal momento che è meccanica e può essere fatto algoritmicamente, ma è necessario una struttura di base per memorizzare una funzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top