// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) fieldsfirst 
// Source File Name:   LBayes.java

package lt.ktu.gmj.methods;

import lt.ktu.gmj.*;

// Referenced classes of package lt.ktu.gmj.methods:
//			LBayesMethodBase, MethodBase

public class LBayes extends LBayesMethodBase
{

	private double aniu;
	private double beta;
	private static final double EPS0 = 0.5D;
	private static final double A0 = 1D;
	private static final double GAMA0 = 0.20000000000000001D;
	private static final double COEF = 0.80000000000000004D;
	private static final double EPS2 = 9.9999999999999995E-07D;
	private static final double EPS3 = 9.9999999999999995E-07D;
	private static final double EPS4 = 1E-10D;
	private static final double B1 = 9.9999999999999995E-07D;
	private static final double V1 = 9.9999999999999995E-07D;
	private static final double B2 = 0.01D;
	private static final double V2 = 1D;
	private static final int CONV = 1;
	private static final int SL_CONV = 2;
	private double M1;
	private int N2;
	private Point x1Pnt;
	private Point x2Pnt;
	private Point dmlPnt;
	private Point dml1Pnt;
	private Point abPnt;

	public LBayes()
	{
		super.iterations = 500;
		aniu = 0.050000000000000003D;
		beta = 0.90000000000000002D;
	}

	private void FillPoint(Point xPnt, double val)
	{
		for(int i = 0; i < xPnt.x.length; i++)
			xPnt.x[i] = val;

	}

	private void dispersion(double x[], int n_of_pnts, double meandisp[])
	{
		meandisp[0] = 0.0D;
		meandisp[1] = 0.0D;
		for(int i = 0; i < n_of_pnts; i++)
		{
			meandisp[0] += x[i];
			meandisp[1] += x[i] * x[i];
		}

		meandisp[0] /= n_of_pnts;
		meandisp[1] = (meandisp[1] - (double)n_of_pnts * meandisp[0] * meandisp[0]) / (double)(n_of_pnts - 1);
	}

	protected double increment(double x, double a, double b, double dx)
	{
		x += dx;
		return dx <= 0.0D ? x >= a ? x : a : x <= b ? x : b;
	}

	private void lbayes_dispersion(Point xPnt, Point x1Pnt, double meandisp[], int n2, Task task)
	{
		double x[] = new double[n2];
		for(int i = 0; i < n2; i++)
			x1Pnt.x[i >= x1Pnt.x.length ? 0 : i] = x[i] = task.f(xPnt).fx();

		dispersion(x, n2, meandisp);
	}

	public Result run(ResultLogger logger, Task task)
	{
		Domain domain = task.domain();
		Result result = new Result();
		Result bestres = new Result();
		int n = domain.dimensions().length;
		M1 = 0.80000000000000004D * (double)super.iterations - 2D;
		N2 = 2 * n;
		x1Pnt = new Point(domain.defaultPoint);
		x2Pnt = new Point(domain);
		dmlPnt = new Point(domain);
		dml1Pnt = new Point(domain);
		abPnt = new Point(domain);
		double meandisp[] = new double[2];
		int n2 = N2;
		int am2 = 1;
		int an0 = 1;
		int lo = 1;
		int lb = 1;
		double a1 = 0.0D;
		result.point = x1Pnt;
		lbayes_dispersion(x1Pnt, x2Pnt, meandisp, n2, task);
		//result.value = meandisp[0];
		result.value = new SimpleResult(meandisp[0]);
		bestres = new Result(result.iteration, result.point, result.value);
		logger.log(result);
		double f13 = (double)n2 * meandisp[0];
		double f11 = meandisp[1];
		result.iteration++;
		for(int i = 0; i < n; i++)
			abPnt.x[i] = 0.5D * (domain.max[i] - domain.min[i]);

		for(int m = 0; m < super.iterations - 1;)
		{
			result = new Result(result.iteration, result.point, result.value);
			double hm0 = 0.20000000000000001D * Math.pow(m + 1, -aniu);
			double sig0 = Math.sqrt(f11);
			x1Pnt = new Point(result.point);
			x2Pnt = new Point(result.point);
			for(int i = 0; i < n; i++)
			{
				double dx = hm0 * abPnt.x[i];
				x1Pnt.x[i] = increment(result.point.x[i], domain.min[i], domain.max[i], dx);
				x2Pnt.x[i] = increment(result.point.x[i], domain.min[i], domain.max[i], -dx);
				dmlPnt.x[i] = 2D * dx * (task.f(x1Pnt).fx() - task.f(x2Pnt).fx());
				dmlPnt.x[i] /= x1Pnt.x[i] - x2Pnt.x[i];
				x1Pnt.x[i] = x2Pnt.x[i] = result.point.x[i];
			}

			if(lb > 1)
			{
				for(int i = 0; i < n; i++)
					dmlPnt.x[i] = (dmlPnt.x[i] + dml1Pnt.x[i] * (double)(lb - 1)) / (double)lb;

			}
			double s1 = dmlPnt.norma() + 1E-10D;
			double hm = Math.sqrt(hm0) / s1;
			for(int i = 0; i < n; i++)
			{
				double dx = hm * abPnt.x[i] * dmlPnt.x[i];
				x1Pnt.x[i] = increment(result.point.x[i], domain.min[i], domain.max[i], dx);
				x2Pnt.x[i] = increment(result.point.x[i], domain.min[i], domain.max[i], -dx);
			}

			double hs = 0.0D;
			double hs1 = 0.0D;
			double hs2 = 0.0D;
			for(int i = 0; i < n; i++)
			{
				hs += Math.pow((x2Pnt.x[i] - x1Pnt.x[i]) / abPnt.x[i], 2D);
				hs1 += Math.pow((x1Pnt.x[i] - result.point.x[i]) / abPnt.x[i], 2D) + 9.9999999999999995E-07D;
				hs2 += Math.pow((x2Pnt.x[i] - result.point.x[i]) / abPnt.x[i], 2D) + 9.9999999999999995E-07D;
			}

			hs = Math.sqrt(hs);
			hs1 = Math.sqrt(hs1);
			hs2 = Math.sqrt(hs2);
			double am = (task.f(x1Pnt).fx() * hs2 + task.f(x2Pnt).fx() * hs1) - result.value.fx() * hs;
			am *= 2D * hm0;
			am /= hs1 * hs2 * (hs1 + hs2);
			double d1 = am;
			if(am < 9.9999999999999995E-07D)
				d1 = 9.9999999999999995E-07D;
			if(am < 0.01D && m == 0)
				d1 = 1.0D;
			a1 += d1 / hm0;
			double epsm = (hm0 * a1) / (double)(m + 1);
			if((double)m < M1)
			{
				if((f11 * (double)(n2 - 1)) / (double)n2 < 9.9999999999999995E-07D)
				{
					f11 = 1.9999999999999999E-06D;
					n2 = 2;
				}
				sig0 = Math.sqrt(f11);
				double sigl = (hm0 * sig0 * Math.sqrt((double)n / (2D * (double)lb))) / d1;
				if(lo != 1)
				{
					if(s1 >= sigl)
						lo = 1;
					else
						an0++;
				} else
				if(s1 <= 0.5D * sigl)
				{
					lo = 2;
					an0++;
				}
			} else
			{
				an0++;
			}
			double a3 = (Math.pow(an0, beta) + 2D) * epsm;
			for(int i = 0; i < n; i++)
				x1Pnt.x[i] = increment(result.point.x[i], domain.min[i], domain.max[i], (-abPnt.x[i] * dmlPnt.x[i]) / a3);

			lbayes_dispersion(x1Pnt, x2Pnt, meandisp, n2, task);
			double f14 = (double)n2 * meandisp[0];
			if(meandisp[0] <= result.value.fx() + (0.5D * sig0) / Math.sqrt(n2))
			{
				result.point = x1Pnt;
				result.value = new SimpleResult(meandisp[0]);
				f13 = f14;
				f11 = (meandisp[1] + f11 * (double)(++am2 - 1)) / (double)am2;
				lb = 1;
			} else
			{
				f13 += task.f(result.point).fx();
				result.value = new SimpleResult(f13 / (double)(am2 != 1 ? lb + n2 : lb + 2 * n));
				lb++;
				dml1Pnt = new Point(dmlPnt);
			}
			if(result.value.fx() < bestres.value.fx())
				bestres = result;
			logger.log(result);
			m++;
			result.iteration++;
		}

		task.domain().defaultPoint = bestres.point;
		return bestres;
	}
}
