Risolvere le equazioni non รจ sempre un’operazione facile. Le equazioni lineari di primo o di secondo grado si possono facilmente risolvere con metodi veloci ed elementari. Ma altre tipologie di equazioni (con alto grado oppure o non lineari) risultano oltremodo complicate e la relativa risoluzione potrebbe risultare un’operazione alquanto difficoltosa. Vediamo come la programmazione di un linguaggio di programmazione aiuti in questo senso e come il metodo Montecarlo contribuisca ad arrivare alla determinazione delle soluzioni, anche se non si conoscono le metodologie di risoluzione matematiche. Si puรฒ pensare, dunque, di abbandonare momentaneamente i vari metodi di sostituzione, di Cramer, di confronto, di bisezione, di Newton, di Jacobi e Gauss-Seidel, del Gradiente Coniugato e altri per raggiungere, ugualmente, la risoluzione finale.
Primo esempio: passiamo subito al sodo
Molto spesso sui social si vedono dei post di amici che propongono quiz e indovinelli matematici. Il piรน delle volte si tratta di equazioni complicate, magari di grado superiore a 5. Si supponga di leggere il seguente quesito al fine di risolvere lโequazione:
prevedendo soluzioni intere e reali. Risolvere unโequazione di quinto grado non รจ poi cosรฌ semplice. Vediamo come procedere. Abbiamo bisogno di forza bruta e velocitร massima. Il metodo Montecarlo, nel nostro caso, si basa sulla generazione di un numero casuale intero e positivo che possa sostituire il valore dellโincognita e calcolare, di conseguenza, lโequazione. Si comprende subito come tale metodologia distolga lโutente dal conoscere i metodi risolutivi necessari. Occorre solo insegnare la tecnica di sostituzione al calcolatore, e il gioco รจ fatto. Per le prove utilizziamo, ovviamente, il linguaggio C, che risulta il piรน veloce di tutti gli altri linguaggi di programmazione. Lo scopo, infatti, รจ quello di generare il piรน alto numero di valori casuali, che vadano a sostituire le variabili dellโesercizio, nel modo piรน rapido possibile.
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { long x,e; srand(time(NULL)); printf("Inizio\n"); while(1) { x=rand(); e=x*x*x*x*x-2*x*x*x*x-x*x*x+8*x*x-x+8; if(e==2875188) printf("Valore di X: %ld\n",x); } }
Come si vede, invece di usare la funzione pow(), appartenente alla libreria โmathโ, lโelevamento รจ stato effettuato moltiplicando โnโ volte il valore della x. L’algoritmo non termina mai perchรฉ staziona in un ciclo infinito. Pertanto si deve bloccarlo premendo i tasti <CTRL><C>. Essendo generati dei numeri casuali si potrebbero ripetere le soluzioni giร proposti in precedenza, ma questo problema รจ irrilevante. Purtroppo la funzione rand() genera numeri casuali interi da 0 a RAND_MAX, di solito pari a 32767, ma รจ possibile raggirare tale โlimiteโ. Come si vede dal risultato, una delle 5 possibili soluzioni che ammette lโequazione รจ di tipo reale e intera, le altre sono immaginarie.
Secondo esempio: coefficienti negativi
Eโ sempre consigliabile prevedere una generazione stocastica di cifre negative. Lโalgoritmo che segue genera numeri anche negativi, oltre che positivi, e utilizza anche la funzione pow() per effettuare lโelevamento a potenza, ottenendo una codifica piรน comoda. Si debba risolvere, ad esempio, la seguente equazione:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> int main() { long x,e; srand(time(NULL)); printf("Inizio\n"); while(1) { x=rand()-16384; e=12*pow(x,8)+2*pow(x,7)-5*pow(x,6)-pow(x,5)-2*pow(x,4) pow(x,3)+8*pow(x,2)-x+8; if(e==4455338) printf("Valore di X: %ld\n",x); } }
Anche questa volta lโequazione prevede una soluzione intera e reala. Risolvere unโequazione di ottavo grado risulta abbastanza complicato. Eโ utilizzata la funzione pow() per lโelevamento a potenza. Lโesecuzione deve essere sempre bloccata premendo i tasti <CTRL><C>. Anche in questo dato la soluzione viene visualizzata sul monitor.
Terzo esempio: avvicinamento successivo
Il terzo esempio รจ piรน complesso, prevede radici non intere positive e una visualizzazione progressiva per avvicinamento alla risoluzione finale. Si debba risolvere la seguente equazione:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> int main() { long ParteIntera,ParteDecimale; char st[20]; double x,e,diff,maxdiff; srand(time(NULL)); printf("Inizio\n"); maxdiff=99999999.9; while(1) { ParteIntera=rand()%100; ParteDecimale=rand(); sprintf(st,"%ld.%ld",ParteIntera,ParteDecimale); x=atof(st); e=pow(2,x)+pow(x,2)+47*pow(x,2); diff=fabs(e-23420.3454396); if(diff<maxdiff) { maxdiff=diff; printf("Valore di X:%3.9f. Massima differenza:%f\n",x,maxdiff); } } }
Il codice รจ molto interessante e introduce un primo tentativo di algoritmo genetico, ovviamente estremamente primitivo e non migliorativo. La videata finale fa comprendere come il punto di partenza della ricerca possa essere il piรน diversificato, data lโaleatorietร dellโapproccio, ma il punto finale converge sempre verso la soluzione.