// 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:   Exkor.java

package lt.ktu.gmj.methods;

import java.io.PrintStream;
import lt.ktu.gmj.*;

// Referenced classes of package lt.ktu.gmj.methods:
//			ExkorMethodBase

public class Exkor extends ExkorMethodBase
{

	private static final int I100 = 100;
	private static final double CON = 1.28D;
	private static final double LTONE = 7D;
	private static final double UTZERO = 18.66D;
	private static final double V1 = 0.39894228044399999D;
	private static final double V2 = 0.39990343850400001D;
	private static final double V3 = 5.7588548045800003D;
	private static final double V4 = 29.821355780800001D;
	private static final double V5 = 2.6243312167899999D;
	private static final double V6 = 48.6959930692D;
	private static final double V7 = 5.9288572443799996D;
	private static final double V11 = 0.39894228038500001D;
	private static final double V12 = 3.8052000000000002E-08D;
	private static final double V13 = 1.00000615302D;
	private static final double V14 = 0.00039806379400000001D;
	private static final double V15 = 1.9861538136400001D;
	private static final double V16 = 0.151679116635D;
	private static final double V17 = 5.2933032492600001D;
	private static final double V18 = 4.8385912808000002D;
	private static final double V19 = 15.150897245099999D;
	private static final double V20 = 0.74238092402699996D;
	private static final double V21 = 30.789933034000001D;
	private static final double V22 = 3.9901941701100001D;
	private double RMAXS;
	private double RMAX;
	private int K;
	private double CUND;
	private double K1;
	private double CP5;
	private double CP6;
	private double CM6;
	private double CM5;
	private double DM17;
	private double CM17;
	private int n_of_points;
	private double x1[];
	private double x2[];
	private double y2[];
	private double y3[];

	public Exkor()
	{
		x1 = new double[106];
		x2 = new double[106];
		y2 = new double[106];
		y3 = new double[106];
		RMAXS = Math.sqrt(1.7976931348623157E+308D);
		RMAX = Math.log(1.7976931348623157E+308D) / Math.log(10D);
		K = (int)RMAX + 1;
		CUND = -2D * (double)K;
		K1 = K / 3;
		CP5 = Math.pow(10D, K1 - 1.0D);
		CP6 = 10D * CP5;
		CM6 = 1.0D / CP6;
		CM5 = 1.0D / CP5;
		DM17 = Math.pow(10D, 2D - (double)K);
		CM17 = DM17;
		System.out.println("Exkor. (Nerijus Remeikis, 1999, Kaunas)");
	}

	private double alnorm(double d)
	{
		boolean flag = false;
		if(d < 0.0D)
		{
			d = -d;
			flag = true;
		}
		double d1;
		if(d <= 7D || flag && d <= 18.66D)
		{
			double d2 = 0.5D * d * d;
			if(d <= 1.28D)
			{
				d1 = d2 + 5.9288572443799996D;
				d1 = d2 + 2.6243312167899999D + 48.6959930692D / d1;
				d1 = (d2 + 5.7588548045800003D) - 29.821355780800001D / d1;
				d1 = 0.5D - d * (0.39894228044399999D - (0.39990343850400001D * d2) / d1);
			} else
			{
				d1 = d + 3.9901941701100001D;
				d1 = d + 0.74238092402699996D + 30.789933034000001D / d1;
				d1 = (d + 4.8385912808000002D) - 15.150897245099999D / d1;
				d1 = (d - 0.151679116635D) + 5.2933032492600001D / d1;
				d1 = d + 0.00039806379400000001D + 1.9861538136400001D / d1;
				d1 = (d - 3.8052000000000002E-08D) + 1.00000615302D / d1;
				d1 = (0.39894228038500001D * Math.exp(-d2)) / d1;
			}
		} else
		{
			d1 = 0.0D;
		}
		if(!flag)
			d1 = 1.0D - d1;
		return d1;
	}

	protected int array_maximum(double ad[], int i, int j)
	{
		double d = ad[--j + i];
		int k = j;
		while(j-- > 0) 
		{
			double d1 = ad[j + i];
			if(d1 > d)
			{
				d = d1;
				k = j;
			}
		}
		return k;
	}

	protected int array_minimum(double ad[], int i, int j)
	{
		double d = ad[--j + i];
		int k = j;
		while(j-- > 0) 
		{
			double d1 = ad[j + i];
			if(d1 < d)
			{
				d = d1;
				k = j;
			}
		}
		return k;
	}

	private double calculate_yh(double d, double d1)
	{
		return d - 0.5D * (d1 - d);
	}

	protected void copy_array(double ad[], double ad1[], int i)
	{
		while(i-- > 0) 
			ad[i] = ad1[i];
	}

	private void cor(double d, double d1, double d2, double d3, double d4, double d5, double ad[], int i, 
			double ad1[], int j)
	{
		double d6 = d1 - d;
		ad[i] = 0.5D * (d + d1 + (d6 * (d2 - d3)) / ((d2 + d3) - 2D * d5));
		double d7 = d1 - ad[i];
		double d8 = ad[i] - d;
		double d9 = (d2 * d7 + d3 * d8) / d6;
		double d10 = Math.sqrt((d7 * d8) / d6) * d4;
		ad1[j] = -alnorm((d5 - d9) / d10);
	}

	protected void double_array_fill(double ad[], int i, double d)
	{
		while(i-- > 0) 
			ad[i] = d;
	}

	protected void double_array_fill(double ad[], int i, int j, double d)
	{
		while(j-- > 0) 
			ad[j + i] = d;
	}

	private Result exkor(ResultLogger resultlogger, Task task)
	{
		int ai[] = new int[1];
		int i = iterations();
		int j = initialPoints();
		int k = it_w();
		Domain domain = task.domain();
		int l = domain.min.length;
		Point point = new Point(task.domain());
		Result result = new Result(n_of_points, point, task.f(point));
		resultlogger.log(result);
		n_of_points++;
		i--;
		int i1;
		if(k == 0)
		{
			i1 = 100;
		} else
		{
			i1 = k;
			if(i < k * l)
				i = k * l;
		}
		int j1 = Math.min(i1, i);
		for(int k1 = 0; k1 < l; k1++)
		{
			if(extrk0(domain.min[k1], domain.max[k1], result, j1, j, 9.9999999999999995E-07D, 9.9999999999999995E-07D, k1, x1, y3, y2, x2, ai, resultlogger, task) == -1)
				return result;
			i -= ai[0];
			if(i <= 0 || k != 0 && k1 == l - 1)
				return result;
			j1 = Math.min(i1, i);
		}

		return result;
	}

	private double extrapolate(double d, double d1)
	{
		return 0.5D * (3D * d - d1);
	}

	private int extrk0(double d, double d1, Result result, int i, int j, 
			double d2, double d3, int k, double ad[], double ad1[], 
			double ad2[], double ad3[], int ai[], ResultLogger resultlogger, Task task)
	{
		System.out.println(" lb = " + d + " ub = " + d1);
		Domain domain = task.domain();
		boolean flag = false;
		double d4 = d1 - d;
		int ai1[] = new int[1];
		int ai2[] = new int[1];
		double ad4[] = new double[1];
		double ad5[] = new double[1];
		double ad6[] = new double[1];
		double ad7[] = new double[1];
		double ad8[] = new double[1];
		double ad9[] = new double[result.point.x.length];
		copy_array(ad9, result.point.x, ad9.length);
		ai1[0] = 0;
		ai2[0] = 0;
		ad4[0] = result.point.x[k];
		double d5 = ad4[0];
		double d6 = result.value.fx();
		double d7 = d4 * 0.040000000000000001D;
		if(d4 < CM5 || d4 > CP5)
		{
			ai[0] = ai2[0];
			ad9[k] = ad4[0];
			return 0;
		}
		double d8 = d4 / (double)(j - 1);
		ad5[0] = d;
		for(int l = 3; l < j + 3; l++)
		{
			ad9[k] = ad[l] = ad5[0];
			ai1[0]++;
			Point point = new Point(domain);
			copy_array(point.x, ad9, ad9.length);
			ad6[0] = ad1[l] = task.f(point).fx();
			Result result1 = new Result(n_of_points, point, new SimpleResult(ad6[0]));
			resultlogger.log(result1);
			ai2[0]++;
			if(Math.abs(ad6[0]) > RMAXS)
			{
				ai[0] = ai2[0];
				ad9[k] = ad4[0];
				return -1;
			}
			if(ad6[0] < result.value.fx())
			{
				result.value = new SimpleResult(ad6[0]);
				ad4[0] = ad5[0];
				copy_array(result.point.x, ad9, ad9.length);
			}
			n_of_points++;
			ad5[0] += d8;
		}

		double d9 = wiener_process_parameter(ad, 3, ad1, 3, j) * 20D;
		if(d9 < CM6 || d9 > CP6)
		{
			ai[0] = ai2[0];
			ad9[k] = ad4[0];
			return 0;
		}
		int i1 = array_maximum(ad1, 3, j);
		double d10 = ad1[i1 + 3];
		ad8[0] = calculate_yh(result.value.fx(), d10);
		int j1 = 0;
		d2 = Math.min(d2, 0.10000000000000001D * d9 * Math.sqrt(d7));
		ad5[0] = d5;
		double d11 = d4 * 0.001D;
		for(int k1 = 3; k1 < ai1[0] + 3; k1++)
		{
			if(ad5[0] > ad[k1 + 1])
				continue;
			if(ad5[0] > ad[k1] + d11 && ad5[0] < ad[k1 + 1] - d11)
			{
				for(int l1 = ai1[0] + 2; l1 > k1; l1--)
				{
					ad[l1 + 1] = ad[l1];
					ad1[l1 + 1] = ad1[l1];
				}

				ai1[0]++;
				ad[k1 + 1] = ad5[0];
				ad1[k1 + 1] = d6;
				if(d6 < result.value.fx())
				{
					result.value = new SimpleResult(d6);
					ad4[0] = ad5[0];
					ad8[0] = calculate_yh(result.value.fx(), d10);
				}
			}
			break;
		}

		double_array_fill(ad3, i + 6, 0.0D);
		do
		{
			for(int i2 = 3; i2 < ai1[0] + 2; i2++)
				if(ad3[i2] <= 0.0D)
					cor(ad[i2], ad[i2 + 1], ad1[i2], ad1[i2 + 1], d9, ad8[0], ad2, i2, ad3, i2);

			byte byte0;
			do
			{
				int j2 = array_minimum(ad3, 3, ai1[0] - 1);
				ad7[0] = ad3[j2 + 3];
				j2 += 3;
				for(int k2 = ai1[0] + 2; k2 > j2; k2--)
				{
					ad[k2 + 1] = ad[k2];
					ad1[k2 + 1] = ad1[k2];
					ad2[k2] = ad2[k2 - 1];
					ad3[k2] = ad3[k2 - 1];
				}

				ad[j2 + 1] = ad9[k] = ad5[0] = ad2[j2];
				ai1[0]++;
				Point point1 = new Point(domain);
				copy_array(point1.x, ad9, ad9.length);
				ad1[j2 + 1] = ad6[0] = task.f(point1).fx();
				Result result2 = new Result(n_of_points, point1, new SimpleResult(ad6[0]));
				resultlogger.log(result2);
				n_of_points++;
				ai2[0]++;
				if(Math.abs(ad6[0]) > RMAXS)
				{
					ai[0] = ai2[0];
					result.point.x[k] = ad9[k] = ad4[0];
					return -1;
				}
				if(ad6[0] < result.value.fx())
				{
					result.value = new SimpleResult(ad6[0]);
					ad4[0] = ad5[0];
					byte0 = 2;
					copy_array(result.point.x, ad9, ad9.length);
				} else
				{
					byte0 = 1;
				}
				if(ai2[0] >= i)
				{
					ai[0] = ai2[0];
					ad9[k] = ad4[0];
					return 0;
				}
				d10 = Math.max(d10, ad6[0]);
				double d12 = probability(ad, 3, ad1, 3, result.value.fx(), d2, d9, ad3, 3, ai1[0]);
				ad8[0] = calculate_yh(result.value.fx(), d10);
				if(Math.abs(result.value.fx() - ad6[0]) < 4.9406564584124654E-321D)
				{
					byte0 = 2;
					d9 = wiener_process_parameter(ad, 3, ad1, 3, ai1[0]) * 20D;
				} else
				{
					if(d12 >= 0.94999999999999996D)
					{
						ai[0] = ai2[0];
						ad9[k] = ad4[0];
						return 0;
					}
					if(ai1[0] % 5 == 0 && j1 == 0)
					{
						byte0 = 2;
						d9 = wiener_process_parameter(ad, 3, ad1, 3, ai1[0]) * 20D;
					}
				}
				ad[0] = ad[1] = ad[2] = extrapolate(ad[3], ad[4]);
				ad[ai1[0] + 3] = ad[ai1[0] + 4] = ad[ai1[0] + 5] = extrapolate(ad[ai1[0] + 2], ad[ai1[0] + 1]);
				ad1[0] = ad1[1] = ad1[2] = ad1[4];
				ad1[ai1[0] + 3] = ad1[ai1[0] + 4] = ad1[ai1[0] + 5] = ad1[ai1[0] + 1];
				double d13 = d4 * 0.20000000000000001D;
				boolean flag1 = false;
				int l2;
				for(l2 = Math.max(0, j2 - 5); l2 < Math.min(ai1[0], j2 + 2); l2++)
				{
					if(ad1[l2] < ad1[l2 + 1] || ad1[l2 + 1] < ad1[l2 + 2] || ad1[l2 + 2] <= ad1[l2 + 3] || ad1[l2 + 3] >= ad1[l2 + 4] || ad1[l2 + 4] > ad1[l2 + 5] || ad1[l2 + 5] > ad1[l2 + 6] || ad[l2 + 6] - ad[l2] > d13)
						continue;
					flag1 = true;
					break;
				}

				if(flag1)
				{
					double_array_fill(ad3, l2, 6, 1.0D);
					l2 += 3;
					j1++;
					int i3 = local_optimization(ai2, ad4, result, l2, ad5, ad6, ad, ad1, ad7, k, ai1, ad8, d10, i, d3, d2, task, resultlogger, ad9);
					if(i3 < 1)
					{
						ai[0] = ai2[0];
						ad9[k] = ad4[0];
						return i3;
					}
					ad[l2] = ad5[0];
					ad1[l2] = ad6[0];
					byte0 = 2;
				}
				if(byte0 == 2)
					break;
				for(int j3 = j2; j3 < j2 + 2; j3++)
					if(ad[j3 + 1] - ad[j3] < d7 && ad3[j3 - 1] > 0.0D && ad1[j3] < ad1[j3 + 1])
						ad3[j3] = 1.0D;
					else
						cor(ad[j3], ad[j3 + 1], ad1[j3], ad1[j3 + 1], d9, ad8[0], ad2, j3, ad3, j3);

				unimodality(ad3, ad, ad1, j2 + 1, d7);
				unimodality(ad3, ad, ad1, j2, d7);
			} while(byte0 == 1);
		} while(true);
	}

	private int local_optimization(int ai[], double ad[], Result result, int i, double ad1[], double ad2[], double ad3[], 
			double ad4[], double ad5[], int j, int ai1[], double ad6[], double d, 
			int k, double d1, double d2, Task task, ResultLogger resultlogger, 
			double ad7[])
	{
		boolean flag = false;
		boolean flag1 = false;
		double d3 = ad3[0];
		double d4 = ad3[i - 1];
		double d5 = ad3[i];
		double d6 = ad3[i + 1];
		double d7 = ad4[i - 1];
		double d8 = ad4[i];
		double d9 = ad4[i + 1];
		do
		{
			double d10 = d7 - d8;
			double d11 = d4 - d5;
			if(Math.abs(d10) <= DM17 || Math.abs(d11) <= DM17)
				break;
			double d12 = d7 - d9;
			double d13 = d4 - d6;
			double d14 = 2D * (d12 / d10 - d13 / d11);
			if(Math.abs(d14) <= DM17)
				break;
			ad1[0] = (((d4 + d5) * d12) / d10 - ((d4 + d6) * d13) / d11) / d14;
			d12 = d5 - ad1[0];
			d11 = d4 - ad1[0];
			if(Math.abs(d11) < DM17)
			{
				ad5[0] = d7;
			} else
			{
				d12 = 1.0D - (d12 / d11) * (d12 / d11);
				if(Math.abs(d12) < DM17)
					ad5[0] = d10 <= Math.abs(d12) * 1000000D ? d7 - d10 / d12 : d7 - 100000D;
				else
					ad5[0] = d7 - d10 / d12;
			}
			ad7[j] = ad1[0];
			Point point = new Point(task.domain());
			copy_array(point.x, ad7, ad7.length);
			ad2[0] = task.f(point).fx();
			Result result1 = new Result(n_of_points, point, new SimpleResult(ad2[0]));
			resultlogger.log(result1);
			n_of_points++;
			ai[0]++;
			if(Math.abs(ad2[0]) > RMAXS)
				return -1;
			if(ad2[0] < result.value.fx())
			{
				result.value = new SimpleResult(ad2[0]);
				ad[0] = ad1[0];
				copy_array(result.point.x, ad7, ad7.length);
				ad6[0] = calculate_yh(result.value.fx(), d);
			}
			if(ai[0] >= k)
				return 0;
			d3 = Math.abs(ad1[0] - d3);
			byte byte0 = (byte)(ad1[0] <= d5 ? 1 : 2);
			ad5[0] = Math.abs(ad5[0] - ad2[0]);
			if(ad5[0] <= d2 && d3 <= d1 || ad5[0] <= CM17 || d3 <= CM17)
				break;
			if(ad2[0] < d8)
			{
				if(byte0 == 2)
				{
					d4 = d5;
					d7 = d8;
					d5 = ad1[0];
					d8 = ad2[0];
					if(i == ai1[0] + 2 && !flag)
					{
						d6 = extrapolate(d5, d4);
						d9 = d7;
					} else
					{
						flag = true;
					}
				} else
				{
					d6 = d5;
					d9 = d8;
					d5 = ad1[0];
					d8 = ad2[0];
					if(i == 3 && !flag)
					{
						d4 = extrapolate(d5, d6);
						d7 = d9;
					} else
					{
						flag = true;
					}
				}
			} else
			if(byte0 == 2)
			{
				d6 = ad1[0];
				d9 = ad2[0];
				if(i == 3 && !flag)
				{
					d4 = extrapolate(d5, d6);
					d7 = d9;
				} else
				{
					flag = true;
				}
			} else
			{
				d4 = ad1[0];
				d7 = ad2[0];
				if(i == ai1[0] + 2 && !flag)
				{
					d6 = extrapolate(d5, d4);
					d9 = d7;
				} else
				{
					flag = true;
				}
			}
			d3 = ad1[0];
		} while(true);
		return 1;
	}

	private double probability(double ad[], int i, double ad1[], int j, double d, double d1, double d2, double ad2[], int k, int l)
	{
		double d3 = 1.0D;
		double d4 = (-800D / d2) * d2;
		for(l--; l-- > 0;)
			if(ad2[l + k] < 0.0D)
			{
				double d5 = d4;
				d5 *= ((ad1[l + j + 1] - d) + d1) * ((ad1[l + j] - d) + d1);
				d5 /= ad[l + i + 1] - ad[l + i];
				if(d5 > CUND)
					d3 *= 1.0D - Math.exp(d5);
			}

		return d3;
	}

	public Result run(ResultLogger resultlogger, Task task)
	{
		return exkor(resultlogger, task);
	}

	private void unimodality(double ad[], double ad1[], double ad2[], int i, double d)
	{
		if(ad[i + 1] > 0.0D && ad2[i] > ad2[i + 1] && ad1[i + 1] - ad1[i] < d)
			ad[i] = 1.0D;
	}

	private double wiener_process_parameter(double ad[], int i, double ad1[], int j, int k)
	{
		double d = 0.0D;
		for(int l = 1; l < k; l++)
		{
			double d1 = ad1[l + j] - ad1[(l + j) - 1];
			d += (d1 * d1) / (ad[l + i] - ad[(l + i) - 1]);
		}

		return Math.sqrt(d / (double)(k - 1));
	}
}
