All Functions Expect The Last

You might also like

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 4

/**

* METHOD TO IMPLEMENT
* Search the next direction to follow when the current point P
* is in the strict interior of the domain.
* If the descent is not finished, put the next direction in the attribute
this.direction
* (it is mandatory to use this attribute).
* <br> WARNING: if the descent method is finished, the method must set to
true the attribute this.finished.
* @see Couple#norm()
* @see Couple#mult(double)
* @see Pb#gradientf(Couple)
* @see #threshold
*/
private void directionToFollowIfPInside() {
if (pb.gradientf(P).norm() < threshold) finished = true;
else direction = pb.gradientf(P).mult(-1 / pb.gradientf(P).norm());
}

/**
* METHOD TO IMPLEMENT
* Search the next direction to follow when the current point P
* is on an edge of the domain but not in a corner.
* If the descent is not finished, put the next direction in the attribute
this.direction
* (it is mandatory to use this attribute).
* <br> According to the direction of the gradient of f and if the descent is
not completed, the next direction
* may be towards the strict interior of the domain or along the edge in one
direction or the other.
* <br> WARNING: if the descent method is finished, the method must set to
true the attribute this.finished.
* @see Couple#norm()
* @see Couple#scalarProduct(Couple)
* @see Couple#isPerpendicular(Couple)
* @see Couple#mult(double)
* @see Constraint#getGradient()
* @see Constraint#getUnitaryEdgeVector()
* @see Pb#gradientf(Couple)
* @see #threshold *
* @param c the constraint saturated by the current point P
*/
private void directionToFollowIfPOnEdge(Constraint c) {
if (pb.gradientf(P).mult(-1).scalarProduct(c.getGradient()) ==
pb.gradientf(P).norm() * c.getGradient().norm()) {
finished = true;
} else {
if (pb.gradientf(P).norm() < threshold) finished = true;
else {
if (pb.gradientf(P).mult(-1).scalarProduct(c.getGradient())
<= 0) {
direction = pb.gradientf(P).mult(-1 /
pb.gradientf(P).norm());
} else {
if (pb.gradientf(P).mult(-
1).scalarProduct(c.getUnitaryEdgeVector()) > 0) {
direction = c.getUnitaryEdgeVector();
} else {
direction = c.getUnitaryEdgeVector().mult(-1);
}
}
}
}
}

/**
* METHOD TO IMPLEMENT
* Search the next direction to follow when the current point P
* is in a corner of the domain.
* If the descent is not finished, put the next direction in the attribute
this.direction
* (it is mandatory to use this attribute).
* <br> WARNING: if the descent method is finished, the method must set to
true the attribute this.finished.
* <br> See the subject on
http://www.infres.enst.fr/~hudry/optim/descentEnglish/index.html for explanations.
* The method decompose being static, it is called with Couple.decompose...
* @see Couple#norm()
* @see Couple#scalarProduct(Couple)
* @see Couple#mult(double)
* @see Couple#decompose(Couple, Couple, Couple)
* @see Constraint#getGradient()
* @see Constraint#getUnitairyEdgeVector()
* @see Pb#gradientf(Couple)
* @param corner an array with two boxes for the two constraints saturated by
the current point P
*/
private void directionToFollowIfPOnCorner(Constraint[] corner) {
double prod1, prod2;
prod1 = pb.gradientf(P).mult(-
1).scalarProduct(corner[0].getGradient());
prod2 = pb.gradientf(P).mult(-
1).scalarProduct(corner[1].getGradient());

Couple coef = Couple.decompose(pb.gradientf(P).mult(-1),


corner[0].getGradient(), corner[1].getGradient());
if (coef.x > 0 || coef.y > 0 || pb.gradientf(P).norm() < threshold) {
finished = true;
} else {
if (prod1 < 0 && prod2 < 0) { // gradiente de f aponta pra
dentro: so seguir a direcao do gradiente
direction = pb.gradientf(P).mult(-1 /
pb.gradientf(P).norm());
} else {
if (prod1 < 0) { // prod2 > 0
if (pb.gradientf(P).mult(-
1).scalarProduct(corner[1].getUnitaryEdgeVector()) > 0) {
direction = corner[1].getUnitaryEdgeVector();
} else {
direction = corner[1].getUnitaryEdgeVector().mult(-
1);
}
} else {
if (pb.gradientf(P).mult(-
1).scalarProduct(corner[0].getUnitaryEdgeVector()) > 0) {
direction = corner[0].getUnitaryEdgeVector();
} else {
direction = corner[0].getUnitaryEdgeVector().mult(-
1);
}
}
}
}
}

/**
* METHOD TO IMPLEMENT
* We consider a half-line parameterized by t -> startingPoint + t.dir (t> =
0);
* we set phi(t) = f(startingPoint + t.dir); we suppose that we have phi'(0)
< 0;
* we look for a point P = startingPoint + t.dir, t> 0, with phi'(t) > 0.
* Recall that, by hypothesis, the function f is convex, which means that
phi' is increasing.
* You can first test t = 1 and then, if necessary, double the value of t
successively.
* The derivative of t -> f(startingPoint + t.dir) can be written :
pb.phiDerivative(startingPoint, dir, t);
* see Pb#phiDerivative (Couple, Couple, double)
* @param startingPoint the origin of the half-line.
* @param dir the direction of the half-line.
* @return if you do not find such a point with t < Double.MAX_VALUE/2, the
method returns -1;
* otherwise the method returns a value of t with phi'(t)> 0.
*/
public double searchSecondPoint(Couple startingPoint, Couple dir) {
for (int t = 1; t < Double.MAX_VALUE/2; t *= 2) {
if (pb.phiDerivative(startingPoint, dir, t) > 0) {
return t;
}
}
return -1;
}

/**
* METHOD TO IMPLEMENT
* We consider a half-line parameterized by t -> startingPoint + t.dir (t> =
0);
* We set phi(t) = f (startingPoint + t.dir); we suppose that we have phi'(0)
<0 and phi'(t1)> 0;
* We look for a point P = startingPoint + t * dir between startingPoint and
* startingPoint + t1 * dir with phi'(t) = 0.
* For this, we proceed by dichotomy.
* One can use the static method isNull of this class to test if a double
value is null or not.
* The derivative of t -> f(startingPoint + t.dir) can be written :
pb.phiDerivative(startingPoint, dir, t);
* @see Pb#phiDerivative (Couple, Couple, double)
* @see Descent#isNull
* @see Couple#add(Couple)
* @param startingPoint the origin of the half-line.
* @param dir the direction of the half-line.
* @param t1 parameter such that phi'(t1)> 0.
* @return the point P = startPoint + t * dir such that phi'(t) = 0 (or
nearly).
*/
public Couple dichotomy(Couple startingPoint, Couple dir, double t1) {
double t_left = 0;
double t_right = t1;
double t_medium = (t_left + t_right) / 2;
while (!isNull(pb.phiDerivative(startingPoint, dir, t_medium))) {
t_medium = (t_left + t_right) / 2;
if (pb.phiDerivative(startingPoint, dir, t_medium) < 0) {
t_left = t_medium;
} else {
t_right = t_medium;
}
}
// The return value is to be modified
return startingPoint.add(dir.mult(t_medium));
}

/**
* METHOD TO IMPLEMENT
* Check that this is a minimum using the condition of Karush, Kuhn and
Tucker
* @param P The point where we check that it is a minimum..
* @see Domain#isCorner(Constraint, Constraint)
* @see Domain#isOnEdge(Couple)
* @see Couple#norm()
* @see Couple#scalarProduct(Couple)
* @see Couple#isPerpendicular(Couple)
* @see Couple#decompose(Couple, Couple, Couple)
* @see Constraint#getUnitairyEdgeVector()
* @see Constraint#getGradient()
* @see Pb#gradientf(Couple)
* @return null if the condition of Karush, Kuhn et Tucker is not
satisfied
* <br>otherwise
* <br>- the couple of Lagrange multipliers if P
is in a corner
* <br>- the couple forms by the multiplier of
Lagrange and 0 if P is on an edge
* <br>- (0, 0) if P is inside
*
*/

You might also like