using System;
using System.Data;
using System.Data.OleDb;
using System.ComponentModel;
using System.Windows.Forms;
using Andromeda.clases;
namespace Andromeda.clases
{
/// <summary>
/// Descripción breve de Amoeba.
/// </summary>
public class Amoeba
{
/* Definiciones de Variables y Constantes*/
public Amoeba(){}
/* Devuelve punto de evaluacion*/
public static void Get_Msum(int n,double[] Msum)
{
int ndim = n; // Curva oscuridad, n = 6; mpts = 7
int mpts = ndim + 1;
double sum;
int i;
for(int j=0;j<=ndim-1;j++) // Recorre las 6 columnas de M
{
for(sum = 0.0, i=0;i<=mpts-1;i++) // Recorre las 7 filas de M
sum = sum + Andromeda.clases.comun.M[i,j];
Msum[j]=sum; //Msum tiene 6 posiciones
}
}
/* Intercambio de valores*/
public static void SWAP(double a, double B)
{
double aux = 0;
aux = a;
a = b;
b = aux;
}
/* Función "Amotry"*/
public static double amotry(int ident,double cte,double[,] M,double[] y,double Msum,int n,int ihi,int nfunk,double fac)
{
int j;
double fac1; double fac2;
double ytry;
double[] ptry;
int ndim = n;
ptry = new double[ndim+1];
fac1 = (1.0-fac)/ndim;
fac2 = fac1-fac;
for(j=0;j<=ndim-1;j++)
ptry[j]=Msum[j]*fac1-M[ihi,j]*fac2;
ytry = Andromeda.clases.comun.funcionE(ident,cte,ptry); //Función a minimizar
if(ytry < y[ihi])
{
y[ihi]=ytry;
for(j=0;j<=ndim-1;j++)
{
Msum[j] = Msum[j] + ptry[j]-M[ihi,j];
M[ihi,j]= ptry[j];
}
}
return ytry;
}//endmethod
/*FUNCION "amoeba" */
public static void amoeba(int ident,double cte,double[,] M,double[] y,int ndim,double ftol)
{
// Zona de declaración de variables
int i,ihi,ilo,inhi,j,mpts;
double rtol,ysave,ytry; // sum?
int nfunk;
// Zona de declaración de constantes
const int NMAX = 5000;
const int ITMAX = 100;
const double TINY = 1.0E-10;
// Zona de inicialización de variables
double[] Msum = new double[ndim+1];
mpts = ndim +1;
nfunk = 0;
Get_Msum(ndim,Msum);
for(;;)
{
ilo = 0;
if(y[0]>y[1])
{
inhi = 1;
ihi = 0;
}
else
{
inhi = 0;
ihi = 1;
}
for(i=0; i<=mpts-1; i++)
{
if(y[i] <= y[ilo]) ilo = i;
if(y[i]>y[ihi])
{
inhi = ihi;
ihi = i;
}else if(y[i]>y[inhi] && i!=ihi) inhi = i;
}//endfor
rtol = 2.0*Math.Abs(y[ihi]-y[ilo])/(Math.Abs(y[ihi])+Math.Abs(y[ilo])+TINY);
if(rtol < ftol)
{
SWAP(y[0],y[ilo]);
for(i=0; i<=ndim-1; i++)
SWAP(M[0,i],M[ilo,i]);
break;
}//endif
if( nfunk >= NMAX)
{
// EN CASO DE ERROR:
return;
}
nfunk= nfunk+2;
// Aquí comienza una nueva iteración
ytry = amotry(ident,cte,M,y,Msum,ndim,ihi,nfunk,-1.0);
if(ytry <= y[ilo])
{
ytry = amotry(ident,cte,M,y,Msum,ndim,ihi,nfunk,2.0);
}
else if(ytry >= y[inhi])
{
ysave = y[ihi];
ytry = amotry(ident,cte,M,y,Msum,ndim,ihi,nfunk,0.5);
if(ytry >= ysave)
{
for(i=0; i<=mpts-1; i++)
{
if(i!=ilo)
{
for(j=0; j<=ndim-1; j++)
M[i,j] = Msum[j]=0.5*(M[i,j]+M[ilo,j]);
y[i] = Andromeda.clases.comun.funcionE(ident,cte,Msum);
}//endif
}//endfor
nfunk = nfunk + ndim;
Get_Msum(ndim,Msum);
}//endif
}//endif
else --nfunk;
}//endfor
}
}