예제 #1
0
 /// <summary>
 /// Costruttore
 /// (da migliorare, T : IClonable)
 /// </summary>
 /// <param name="m">Matrice di partenza</param>
 /// <param name="copy">Ricopia i dati se true</param>
 public MatrixBase(MatrixBase <T> m, bool copy)              // Costruttore (se true, ricopia i dati)
 {
     row = m.row;                                            // Copia le dimensioni
     col = m.col;
     if ((row > 0) && (col > 0))
     {
         dat = new T[row, col];                                      // Alloca nuovi dati
         if (copy)                                                   // Se richiesto...
         {                                                           // ...copia il contenuto
             int r, c;
             for (r = 0; r < row; r++)
             {
                 for (c = 0; c < col; c++)
                 {
                     dat[r, c] = m.dat[r, c];                                // Nota (*) : usa l'operatore = ma dovrebbe usare Clone()
                 }
             }
             // Opportuno mettere un controllo su T, se ICloneable
             // Ma Clone() fa una copia superficiale come object
         }
     }
     else
     {
         dat = null;
     }
 }
예제 #2
0
 /// <summary>
 /// Confronta dimensioni
 /// </summary>
 /// <param name="m">Matrice da confrontare</param>
 /// <returns>true se stesse dimensioni</returns>
 public bool SameSize(MatrixBase <T> m)
 {
     if ((this.Col == m.Col) && (this.Row == m.Row))
     {
         return(true);
     }
     return(false);
 }
예제 #3
0
        /// <summary>
        /// Trasposta
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public static MatrixBase <T> operator !(MatrixBase <T> m)       // Trasposta
        {
            MatrixBase <T> res = new MatrixBase <T>(m.Col, m.Row);      // Crea matrice con dimensioni scambiate
            int            ir, ic;

            for (ir = 0; ir < m.row; ir++)                                  // Ricopia i valori, scambiandone le posizioni
            {
                for (ic = 0; ic < m.col; ic++)
                {
                    res.dat[ic, ir] = m.dat[ir, ic];
                }
            }
            return(res);
        }
예제 #4
0
        /*
         * 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);
        }
예제 #5
0
        /// <summary>
        /// Restituisce una riga
        /// Se indice errato o matrice nulla: ArgumentOutOfRangeException
        /// </summary>
        /// <param name="irow"></param>
        /// <returns></returns>
        public MatrixBase <T> GetRow(int irow)                          // Restituisce una riga
        {
            MatrixBase <T> m;
            int            i;

            if ((irow < 0) || (irow >= row))                            // Se indici non corretti o matrice iniziale con dimensione nulla...
            {
                throw new ArgumentOutOfRangeException(Error.OutOfRange.ToString());
            }
            else if (col <= 0)
            {
                throw new ArgumentOutOfRangeException(Error.NullMatrix.ToString());
            }
            m = new MatrixBase <T>(1, col);                             // Crea matrice con una riga a tante colonne quanto la matrice dipartenza
            for (i = 0; i < col; i++)                                   // Ricopia i valori della riga irow per tutte le colonne i
            {
                m.dat[0, i] = dat[irow, i];
            }
            return(m);                                                      // Restituisce il riferimento all'oggetto allocato
        }
예제 #6
0
        /// <summary>
        /// Restituisce una colonna
        /// Se indice errato o matrice nulla: ArgumentOutOfRangeException
        /// </summary>
        /// <param name="icol"></param>
        /// <returns></returns>
        public MatrixBase <T> GetCol(int icol)                          // Restituisce una colonna
        {
            MatrixBase <T> m;
            int            i;

            if ((icol < 0) || (icol >= col))                            // Se indici non corretti o matrice iniziale con dimensione nulla...
            {
                throw new ArgumentOutOfRangeException(Error.OutOfRange.ToString());
            }
            else if (row <= 0)
            {
                throw new ArgumentOutOfRangeException(Error.NullMatrix.ToString());
            }

            m = new MatrixBase <T>(row, 1);                             // Crea matrice con una colonna a tante righe quanto la matrice dipartenza
            for (i = 0; i < row; i++)                                   // Ricopia i valori della colonna icol per tutte le righe i
            {
                m.dat[i, 0] = dat[i, icol];
            }
            return(m);                                                      // Restituisce il riferimento all'oggetto allocato
        }
예제 #7
0
        public bool Factor(Matrix A)                                        // Fattorizza la matrice A con il metodo di Gauss con pivoting parziale
        {
            int n;                                                          // Dimensione matrice

            if (A.Row != A.Col)                                             // Verifica che A sia quadrata
            {
                return(false);
            }
            n = A.Row;                                                          // Legge dimensione
            if (n < 1)                                                          // Verifica dimensione
            {
                return(false);
            }
            pivot = new MatrixBase <int>(n - 1, 1);                         // Inizializza dimensioni matrici
            a     = new Matrix(A, true);                                    // Crea nuova matrice idntica ad A
            if (n == 1)                                                     // Se di ordine 1...
            {
                det = a[0, 0];
                if (System.Math.Abs(det) <= LinearSys.Epsilon)                      // Se det nullo, esce con errore
                {
                    return(false);
                }
                return(true);                                                   // Se det non nullo, esce regolarmente
            }
            int    k, i, io, j;                                                 // Ciclo di calcolo
            double amax;
            double tmp;

            for (io = 0, det = Matrix.One, k = 0; k < n - 1; k++)               // Ciclo 1
            {
                for (amax = 0.0, i = k; i < n; i++)                             // Cerca la riga io con il massimo amax sulla colonna k
                {
                    if (System.Math.Abs(a[i, k]) >= amax)
                    {
                        io   = i;
                        amax = System.Math.Abs(a[i, k]);
                    }
                }
                pivot[k, 0] = io;
                if (amax <= LinearSys.Epsilon)                                      // Se amax è nullo, esce con errore
                {
                    det = 0.0;
                    return(false);
                }
                if (io != k)                                                        // Se l'indice non è k...
                {
                    for (j = k; j < n; j++)                                         // Scambia le righe k e io
                    {
                        tmp      = a[k, j];
                        a[k, j]  = a[io, j];
                        a[io, j] = tmp;
                    }
                    det = -det;                                                         // e cambia segno al determinante
                }
                for (i = k + 1; i < n; i++)                                             // Ciclo 2
                {
                    a[i, k] = -a[i, k] / a[k, k];
                    for (j = k + 1; j < n; j++)
                    {
                        a[i, j] = a[i, j] + a[i, k] * a[k, j];
                    }
                }                                                                   // Fine ciclo 2
                det = det * a[k, k];
            }                                                                       // Fine ciclo 1
            if (System.Math.Abs(a[n - 1, n - 1]) <= LinearSys.Epsilon)
            {
                det = 0.0;
                return(false);
            }
            det = det * a[n - 1, n - 1];
            return(true);
        }
예제 #8
0
 /// <summary>
 /// Confronta dimensioni
 /// </summary>
 /// <param name="m1">Prima matrice</param>
 /// <param name="m2">Seconda matrice</param>
 /// <returns>true se stesse dimensioni</returns>
 public static bool SameSize(MatrixBase <T> m1, MatrixBase <T> m2)
 {
     return(m1.SameSize(m2));
 }
예제 #9
0
        /*
         *
         * 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);
        }