ngmf.util.cosu.BranchAndBound Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ngmf.util.cosu;
import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;
import java.util.Vector;
/**
*
* @author od
*/
public class BranchAndBound {
class HyperCube {
protected Sample a;
protected Sample b;
protected Sample midPoint;
protected double L;
protected ArrayList InCubeSamples;
public double goodOneFactor;
protected HyperCube parent;
protected double highestLowBound;
HyperCube(Sample a, Sample b, Sample midPoint, HyperCube parent) {
this.a = a;
this.b = b;
this.midPoint = midPoint;
this.parent = parent;
this.InCubeSamples = new ArrayList();
InCubeSamples.add(a);
InCubeSamples.add(b);
InCubeSamples.add(midPoint);
this.L = ApproxL(a, b, this);
if (parent != null) {
highestLowBound = Math.max(Math.max(-1000000000000.0,
Math.max(a.fx, b.fx) - VectorNorm2(VectorMul(VectorSub(b.x, a.x), L))),
midPoint.fx - VectorNorm2(VectorMul(VectorSub(b.x, a.x), L)) / 2.0);
}
double minimum = Math.min(Math.min(a.fx, b.fx), midPoint.fx);
if (highestLowBound > minimum) {
highestLowBound = minimum;
}
goodOneFactor = ((midPoint.fx - a.fx) + (midPoint.fx - b.fx));
}
public void addCubeSample(Sample x) {
this.InCubeSamples.add(x);
}
double CalculateLForTarget(double target) {
//look which L value can realize highestLowBound
double L_theo1 = (Math.max(a.fx, b.fx) - target) / VectorNorm(VectorSub(b.x, a.x));
double L_theo2 = 2.0 * (midPoint.fx - target) / VectorNorm(VectorSub(b.x, a.x));
return Math.min(L_theo1, L_theo2);
}
double bound() {
return highestLowBound;
}
public String compactDescriptionString() {
String s = "";
s += a.x[0] + "\t";
s += a.x[1] + "\t";
s += highestLowBound + "\n";
s += b.x[0] + "\t";
s += a.x[1] + "\t";
s += highestLowBound + "\n";
s += b.x[0] + "\t";
s += b.x[1] + "\t";
s += highestLowBound + "\n";
s += a.x[0] + "\t";
s += b.x[1] + "\t";
s += highestLowBound + "\n";
return s;
}
public String toString() {
return "a:" + a.toString() + "\nb:" + b.toString() + "\nmidPoint:" + midPoint.toString() + "\nbound:" + highestLowBound;
}
}
double[] VectorAdd(double[] a, double[] b) {
double sum[] = new double[a.length];
for (int i = 0; i < a.length; i++) {
sum[i] = a[i] + b[i];
}
return sum;
}
double[] VectorAdd(double[] a, double b) {
double sum[] = new double[a.length];
for (int i = 0; i < a.length; i++) {
sum[i] = a[i] + b;
}
return sum;
}
double[] VectorSub(double[] a, double[] b) {
double sum[] = new double[a.length];
for (int i = 0; i < a.length; i++) {
sum[i] = a[i] - b[i];
}
return sum;
}
double[] VectorMul(double[] a, double mul) {
double result[] = new double[a.length];
for (int i = 0; i < a.length; i++) {
result[i] = a[i] * mul;
}
return result;
}
double[] VectorMul(double[] a, double[] mul) {
double result[] = new double[a.length];
for (int i = 0; i < a.length; i++) {
result[i] = a[i] * mul[i];
}
return result;
}
boolean VectorLessEq(double[] x, double[] y) {
for (int i = 0; i < x.length; i++) {
if (x[i] > y[i] - 0.000001) {
return false;
}
}
return true;
}
double VectorNorm(double[] v) {
double sum = 0;
for (int i = 0; i < v.length; i++) {
sum += Math.abs(v[i]);//*v[i];
}
return sum;//Math.sqrt(sum);
}
double VectorNorm2(double[] v) {
double sum = 0;
for (int i = 0; i < v.length; i++) {
sum += (v[i] * v[i]);//*v[i];
}
return Math.sqrt(sum);//Math.sqrt(sum);
}
double VectorMaxNorm(double[] v) {
double sum = 0;
for (int i = 0; i < v.length; i++) {
sum = Math.max(Math.abs(v[i]), sum);//*v[i];
}
return sum;//Math.sqrt(sum);
}
double VectorMin(double[] v) {
double sum = 0;
for (int i = 0; i < v.length; i++) {
sum = Math.min(v[i], sum);//*v[i];
}
return sum;//Math.sqrt(sum);
}
int getMin(Vector Q) {
double min = Double.MAX_VALUE;
int index = 0;
for (int i = 0; i < Q.size(); i++) {
if (Q.get(i).fx < min) {
min = Q.get(i).fx;
index = i;
}
}
return index;
}
double test = 0;
double[] lowBound;
double[] upBound;
int mode;
int currentSampleCount;
double effValue;
int maxn;
int n;
double[] parameters;
Vector sampleList = new Vector();
Random generator = new Random();
Sample getSample(double[] x) {
Sample s = new Sample(x, funct(x));
sampleList.add(s);
return s;
}
double funct(double x[]) {
//RefreshDataHandles();
for (int j = 0; j < parameters.length; j++) {
try {
parameters[j] = x[j];
} catch (Exception e) {
throw new RuntimeException("Error! Parameter No. " + j + " wasn^t found" + e.toString());
}
}
// singleRun();
double value = effValue;
//sometimes its a bad idea to calculate with NaN or Infty
double bigNumber = 10000000;
effValue = Math.max(effValue, -bigNumber);
effValue = Math.min(effValue, bigNumber);
if (Double.isNaN(effValue)) {
effValue = -bigNumber;
}
currentSampleCount++;
switch (mode) {
case Efficiencies.MINIMIZATION:
return value;
case Efficiencies.MAXIMIZATION:
return -value;
case Efficiencies.ABSMINIMIZATION:
return Math.abs(value);
case Efficiencies.ABSMAXIMIZATION:
return -Math.abs(value);
default:
return 0.0;
}
}
double[] randomSample() {
double[] sample = new double[n];
for (int i = 0; i < n; i++) {
sample[i] = (lowBound[i] + generator.nextDouble() * (upBound[i] - lowBound[i]));
}
return sample;
}
double ApproxL(Sample a, Sample b, HyperCube myCube) {
lowBound = a.x;
upBound = b.x;
ArrayList list = myCube.InCubeSamples;
if (myCube.parent != null) {
for (int i = 0; i < myCube.parent.InCubeSamples.size(); i++) {
Sample x = myCube.parent.InCubeSamples.get(i);
if (VectorLessEq(a.x, x.x) && VectorLessEq(x.x, b.x) && !list.contains(x)) {
boolean contains = false;
for (int j = 0; j < list.size(); j++) {
if (VectorNorm(VectorSub(list.get(j).x, x.x)) < 0.0001) {
contains = true;
break;
}
}
if (!contains) {
myCube.addCubeSample(x);
}
}
}
}
while (list.size() < 3 * n + 1) {
Sample rnd_point = getSample(randomSample());
if (rnd_point.fx < a.fx && rnd_point.fx < b.fx) {
test = a.fx - rnd_point.fx + b.fx - rnd_point.fx;
}
myCube.addCubeSample(rnd_point);
}
//single value L
double variance = 0;
double mean = 0;
//Stack tmp = new Stack();
double sL = 0;
double size = (list.size() - 1) * (list.size()) / 2.0;
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
double d = VectorNorm2(VectorSub(list.get(i).x, list.get(j).x));
sL = Math.max(Math.abs((list.get(i).fx - list.get(j).fx) / d), sL);
mean += sL;
//tmp.push(new Double(sL));
}
}
mean /= size;
return sL;
}
public void run() {
Vector Q = new Vector();
Vector cubes = new Vector();
int xCount = 0;
final double epsilon1 = 0.1; //app-error
double gamma, myR, my;
int k = 1;
System.out.println("***************************");
System.out.println("****start optimization ****");
System.out.println("***************************");
Sample a = getSample(lowBound);
Sample b = getSample(upBound);
//add upperleft und lowerright corner of cube
Q.add(a);
Q.add(b);
//midpoint xr
double xR_tmp[] = VectorMul(VectorAdd(lowBound, upBound), 0.5);
Sample xR = getSample(xR_tmp);
Q.add(xR);
//gamma holds minimum of samples
int IndexWithMinimum = getMin(Q);
Sample v = Q.get(IndexWithMinimum);
gamma = v.fx;
//calculate a lower approximation my
HyperCube R = new HyperCube(a, b, xR, null);
cubes.add(R);
double L = R.L;
myR = Math.max(Math.max(a.fx, b.fx) - VectorNorm(VectorMul(VectorSub(a.x, b.x), L)),
xR.fx - (VectorNorm(VectorMul(VectorSub(a.x, b.x), L)) / 2.0));
my = myR;
Stack queue = new Stack();
queue.push(R);
while (true) {
R = queue.pop();
a = R.a;
b = R.b;
my = R.highestLowBound;
//System.out.println("Processing next cube:\nR:" + R.toString() + "\nMinimum:" + gamma + "\nk:" + k + "\nSampleCount:" + currentSampleCount);
//SaveCubes(cubes,"cubedump" + xCount + ".dat");
if (maxn > 0) {
if (sampleList.size() >= maxn) {
break;
}
}
//current minimum and lower approximation are close
if (gamma - my < epsilon1) {
//break;
}
int sel_j = 0;
double max = 0;
for (int i = 0; i < n; i++) {
if (b.x[i] - a.x[i] > max) {
max = b.x[i] - a.x[i];
sel_j = i;
}
}
Sample a1 = a;
double b1_tmp[] = new double[n];
double a2_tmp[] = new double[n];
Sample b2 = b;
for (int i = 0; i < n; i++) {
if (i == sel_j) {
b1_tmp[i] = (a.x[i] + b.x[i]) / 2.0;
a2_tmp[i] = (a.x[i] + b.x[i]) / 2.0;
} else {
b1_tmp[i] = b.x[i];
a2_tmp[i] = a.x[i];
}
}
Sample b1 = getSample(b1_tmp);
Sample a2 = getSample(a2_tmp);
double xR1_tmp[] = VectorMul(VectorAdd(a1.x, b1.x), 0.5);
double xR2_tmp[] = VectorMul(VectorAdd(a2.x, b2.x), 0.5);
Sample xR1 = getSample(xR1_tmp);
Sample xR2 = getSample(xR2_tmp);
//approx L
HyperCube R1 = new HyperCube(a1, b1, xR1, R);
double L1 = R1.L;
double tmp1 = test;
HyperCube R2 = new HyperCube(a2, b2, xR2, R);
double L2 = R2.L;
double tmp2 = test;
Q.clear();
Q.add(v);
Q.add(b1);
Q.add(xR1);
Q.add(a2);
Q.add(xR2);
IndexWithMinimum = getMin(Q);
v = Q.get(IndexWithMinimum);
gamma = v.fx;
if (R1.goodOneFactor < tmp1) {
R1.goodOneFactor = tmp1;
}
if (R2.goodOneFactor < tmp2) {
R2.goodOneFactor = tmp2;
}
cubes.remove(R);
cubes.add(R1);
cubes.add(R2);
my = Double.MAX_VALUE;//gamma;
xCount++;
if (!queue.empty()) {
continue;
}
//double T[] = {0,0.0001,0.001,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.15,0.20,0.25,0.3,0.4,0.5,0.75,1.0,1.5,2.0,3.0,6.0};
double T[] = {0.0};
//double T[] = {0,0.0001,0.001,0.01,0.05,0.10,0.25,0.5,1.0,2.0,5.0};
int IndexForT[] = new int[T.length];
for (int t = 0; t < T.length; t++) {
int best = -1;
double bestLdiff = 10000000000.0;
for (int i = 0; i < cubes.size(); i++) {
HyperCube c = cubes.get(i);
double Lstar = c.CalculateLForTarget(gamma - T[t]);
//double Ldiff = Lstar - c.L;//VectorSub(Lstar , c.L);
double Ldiff = c.highestLowBound;
if (Ldiff < bestLdiff) {
best = i;
bestLdiff = Ldiff;
}
if (xCount % 20 == 19) {
best = 0;
bestLdiff = Ldiff;
break;
}
}
IndexForT[t] = best;
}
for (int i = 0; i < IndexForT.length; i++) {
if (IndexForT[i] == -1) {
continue;
}
for (int j = i + 1; j < IndexForT.length; j++) {
if (IndexForT[i] == IndexForT[j]) {
IndexForT[j] = -1;
}
}
//System.out.println("add T =" + T[i]);
queue.push(cubes.get(IndexForT[i]));
}
k++;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy