/* * RILASSAMENTO * Da scrivere dopo aver completato Bisezione, PassoFisso e Grossolana */ /* * STEEPEST * Da scrivere dopo aver completato Bisezione, PassoFisso e Grossolana */ /* * PASSOFISSO * Analoga a Bisezione (stessi parametri o quasi...) * Usa pero` il gradiente come condizione di uscita al posto della distanza (oltre alla f) */ /// <summary> /// Incrementa contatori /// </summary> /// <param name="contatori">Colonna (n,1) con i contatori</param> /// <param name="passi">Colonna (n,1) con i passi massimi</param> /// <param name="indIncrementato">Indice incrementato, oppure -1 se variato piu` di uno</param> /// <returns>true se ha incrementato un indice, false se era gia` l'ultimo passo</returns> public static bool Incrementa(ref MatrixBase <int> contatori, MatrixBase <int> passi, ref int indIncrementato) { bool fine = false; // Flag finale int n; // Dimensione dei vettori n = contatori.Row; if ((passi.Row != n) || (passi.Col != 1) || (contatori.Col != 1)) { return(fine); // Verifica gli indici } int indice = 0; // Inizia con il primo indice indIncrementato = 0; // Indice da ricalcolare (-1 se tutti) while (indice < n) { int c; c = contatori.Get(indice, 0) + 1; // Calcola indice incrementato if (c < passi.Get(indice, 0)) // Se entro i limiti... { contatori.Set(indice, 0, c); // Aggiorna indice if (indIncrementato != -1) // Lo salva, per aggiornamento calcoli... { indIncrementato = indice; // ... ma solo se non erano gia` cambiati piu` indici } fine = true; // Raggiunta uscita prima della fine break; // Esce dal ciclo while } else { // ...se superato i limiti contatori.Set(indice, 0, 0); // Azzera contatore indice += 1; // Passa all'indice successivo indIncrementato = -1; continue; // Continua il ciclo while } } // Se esce normalmente dal while, fine resta true if (indice >= n) { fine = false; // Se superato ultimo indice: ultimo passo, false } return(fine); }
/* * * NOTA GENERALE. * * I metodi precedenti, steepest descent, rilassamento (per la scelta delle direzioni) e * passo fisso e bisezione (per la ricerca del minimo (o del massimo) * non sono sufficienti da soli. * * E' ragionevole scrivere prima alcune funzioni che lavorino separatamente. * Tutte sono incluse nella classe Fmin e hanno gia` implicito il delegate alla funzione * Tutte devono prima verificare che il delegate non sia nullo. * */ /// <summary> /// Ricerca per punti /// </summary> /// <param name="xk">Punto centrale</param> /// <param name="range">Meta` ampiezza di ricerca (ammessi valori nulli)</param> /// <param name="passiU">Numero di passi unilaterali (almeno 1)</param> /// <param name="xmin">Punto con il valore minore</param> /// <param name="cicli">Numero di punti calcolati</param> /// <returns></returns> public bool Campionamento(Matrix xk, Matrix range, MatrixBase <int> passiU, ref Matrix xmin, ref int cicli) { bool found = false; int n; // Dimensioni dei vettori int i; // Contatore n = xk.Row; if ((range.Row != n) || (passiU.Row != n) || (xmin.Row != n) || (xk.Col != 1) || (range.Col != 1) || (passiU.Col != 1) || (xmin.Col != 1)) { return(found); // Verifica indici } for (i = 0; i < n; i++) // Verifica intervalli (ammessi valori nulli) { if (range.Get(i, 0) < 0.0) { return(found); } } for (i = 0; i < n; i++) // Verifica passi (almeno 1 per lato) { if (passiU.Get(i, 0) < 1) { return(found); } } MatrixBase <int> passi = new MatrixBase <int>(n, 1); // Matrice dei passi for (i = 0; i < n; i++) // Calcola i passi effettivi (segmenti, non punti) { passi.Set(i, 0, passiU.Get(i, 0) * 2); } Matrix step = new Matrix(n, 1); for (i = 0; i < n; i++) // Calcola i passi effettivi { step.Set(i, 0, range.Get(i, 0) / passi.Get(i, 0)); } Matrix xo = new Matrix(n, 1); for (i = 0; i < n; i++) // Calcola i punti di partenza { xo.Set(i, 0, xk.Get(i, 0) - step.Get(i, 0) * passiU.Get(i, 0)); } MatrixBase <int> contatori = new MatrixBase <int>(n, 1, 0); // Vettore dei contatotri (tutti a 0) Matrix x = new Matrix(n, 1); // Vettore dei valori effettivi int iinc = -1; double minimo = double.MaxValue; double f; cicli = 0; bool fine = false; while (!fine) { if (iinc >= 0) // ricalcola nuovo vettore x { x.Set(iinc, 0, xo.Get(iinc, 0) + step.Get(iinc, 0) * contatori.Get(iinc, 0)); } else { for (i = 0; i < n; i++) { x.Set(i, 0, xo.Get(i, 0) + step.Get(i, 0) * contatori.Get(i, 0)); } } f = Funzione(x); // Calcola la f del punto x attuale if (f < minimo) // Vede se e` minima (rispetto ai valori trovati finora) { minimo = f; xmin = x.Copy(); found = true; } fine = !Incrementa(ref contatori, passi, ref iinc); cicli++; } return(found); }