From 8d6e214f254c655f7128a6669eb49d306634cc02 Mon Sep 17 00:00:00 2001 From: Tanya Cheremkhina <53428519+tcheremkhina@users.noreply.github.com> Date: Mon, 12 Apr 2021 21:41:28 +0300 Subject: [PATCH] FastestDescent & ConjugateGradientMethod FastestDescent and ConjugateGradientMethod implemented. Need check --- Lab1/Lab1.iml | 11 +++ Lab2/.idea/.gitignore | 8 ++ Lab2/.idea/misc.xml | 6 ++ Lab2/.idea/modules.xml | 8 ++ Lab2/.idea/vcs.xml | 6 ++ Lab2/Lab2.iml | 11 +++ Lab2/src/RunMethod.java | 18 ++-- Lab2/src/elements/MyFunction.java | 1 - Lab2/src/elements/Vector.java | 22 ++++- Lab2/src/methods/ConjugateGradientMethod.java | 37 ++++++++ Lab2/src/methods/Dichotomy.java | 39 ++++++++ Lab2/src/methods/FastestDescent.java | 39 ++++++++ Lab2/src/methods/GradientDescent.java | 3 +- Lab2/src/methods/Method.java | 15 ++++ .../result/DefaultIterationResult.java | 69 ++++++++++++++ Lab2/src/methods/result/IterationResult.java | 6 ++ .../result/ParabolaIterationResult.java | 90 +++++++++++++++++++ Lab2/src/methods/result/Result.java | 60 +++++++++++++ 18 files changed, 440 insertions(+), 9 deletions(-) create mode 100644 Lab1/Lab1.iml create mode 100644 Lab2/.idea/.gitignore create mode 100644 Lab2/.idea/misc.xml create mode 100644 Lab2/.idea/modules.xml create mode 100644 Lab2/.idea/vcs.xml create mode 100644 Lab2/Lab2.iml create mode 100644 Lab2/src/methods/ConjugateGradientMethod.java create mode 100644 Lab2/src/methods/Dichotomy.java create mode 100644 Lab2/src/methods/FastestDescent.java create mode 100644 Lab2/src/methods/Method.java create mode 100644 Lab2/src/methods/result/DefaultIterationResult.java create mode 100644 Lab2/src/methods/result/IterationResult.java create mode 100644 Lab2/src/methods/result/ParabolaIterationResult.java create mode 100644 Lab2/src/methods/result/Result.java diff --git a/Lab1/Lab1.iml b/Lab1/Lab1.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/Lab1/Lab1.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Lab2/.idea/.gitignore b/Lab2/.idea/.gitignore new file mode 100644 index 0000000..d897254 --- /dev/null +++ b/Lab2/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../../../:\Users\Tanya Cheremkhina\Documents\GitHub\Met-opt\Lab2\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/Lab2/.idea/misc.xml b/Lab2/.idea/misc.xml new file mode 100644 index 0000000..c07f4d8 --- /dev/null +++ b/Lab2/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Lab2/.idea/modules.xml b/Lab2/.idea/modules.xml new file mode 100644 index 0000000..dd47d37 --- /dev/null +++ b/Lab2/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Lab2/.idea/vcs.xml b/Lab2/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/Lab2/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Lab2/Lab2.iml b/Lab2/Lab2.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/Lab2/Lab2.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Lab2/src/RunMethod.java b/Lab2/src/RunMethod.java index 44a8203..1210027 100644 --- a/Lab2/src/RunMethod.java +++ b/Lab2/src/RunMethod.java @@ -1,23 +1,31 @@ import elements.MyFunction; import elements.Vector; +import methods.ConjugateGradientMethod; import methods.GradientDescent; +import methods.FastestDescent; import java.util.List; public class RunMethod { public static void main(final String[] args) { - final GradientDescent method = new GradientDescent(0.01); + final GradientDescent gradientDescent = new GradientDescent(0.01); + final FastestDescent fastestDescent = new FastestDescent(0.01); + final ConjugateGradientMethod conjugateGradientMethod = new ConjugateGradientMethod(); final MyFunction function = new MyFunction( list -> { final double first = list.get(0), second = list.get(1); - return first * first + second * second + second; + return first * first + 40 * second * second + second; }, List.of( list -> 2 * list.get(0), - list -> 2 * list.get(1) + 1. + list -> 80 * list.get(1) + 1. ) ); - final Vector x = new Vector(List.of(3., -4.)); - method.calc(function, x); + final Vector x = new Vector(List.of(1., 1.)); + gradientDescent.calc(function, x); + System.out.println("-----------------------"); + fastestDescent.calc(function, x); + System.out.println("-----------------------"); + conjugateGradientMethod.calc(function, x); } } diff --git a/Lab2/src/elements/MyFunction.java b/Lab2/src/elements/MyFunction.java index 7d7671d..e9c031e 100644 --- a/Lab2/src/elements/MyFunction.java +++ b/Lab2/src/elements/MyFunction.java @@ -1,7 +1,6 @@ package elements; import java.util.List; -import java.util.function.DoubleUnaryOperator; import java.util.function.Function; import java.util.stream.Collectors; diff --git a/Lab2/src/elements/Vector.java b/Lab2/src/elements/Vector.java index 7465b99..ad7ea62 100644 --- a/Lab2/src/elements/Vector.java +++ b/Lab2/src/elements/Vector.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.function.DoubleUnaryOperator; import java.util.stream.Collectors; public class Vector { @@ -24,6 +23,14 @@ public Vector multiply(final double mul) { ); } + public Vector negate() { + final List value = new ArrayList<>(); + for (int i = 0; i < point.size(); ++i) { + value.add(-point.get(i)); + } + return new Vector(value); + } + public Vector subtract(final Vector vector) { final List value = new ArrayList<>(); for (int i = 0; i < point.size(); ++i) { @@ -32,10 +39,23 @@ public Vector subtract(final Vector vector) { return new Vector(value); } + public Vector add(final Vector vector) { + final List value = new ArrayList<>(); + for (int i = 0; i < point.size(); ++i) { + value.add(point.get(i) + vector.point.get(i)); + } + return new Vector(value); + } + + public double abs() { return Math.sqrt(point.stream().reduce(0., (arg1, arg2) -> arg1 + arg2 * arg2)); } + public double absSqr() { + return point.stream().reduce(0., (arg1, arg2) -> arg1 + arg2 * arg2); + } + @Override public String toString() { return "Vector{" + diff --git a/Lab2/src/methods/ConjugateGradientMethod.java b/Lab2/src/methods/ConjugateGradientMethod.java new file mode 100644 index 0000000..2e24936 --- /dev/null +++ b/Lab2/src/methods/ConjugateGradientMethod.java @@ -0,0 +1,37 @@ +package methods; + +import elements.MyFunction; +import elements.Vector; +import methods.result.IterationResult; +import methods.result.Result; + +import java.util.function.DoubleUnaryOperator; + +public class ConjugateGradientMethod { + + public void calc(final MyFunction function, Vector x) { + Vector gradientFX = function.applyGradient(x); + Double fx = null; + Vector p = function.applyGradient(x).negate(); + System.out.println("gradient abs: " + gradientFX.abs()); + for (int cnt = 0; cnt <= x.getPoint().size(); cnt++) { + Vector finalGradientFX = gradientFX; + Vector finalX = x; + DoubleUnaryOperator fAlpha = alpha -> function.applyFunction(finalX.subtract(finalGradientFX.multiply(alpha))); + Method method = new Dichotomy(1e-9); + Result result = method.calcAllIterations(fAlpha, 0, 100); + double alpha = result.getPoint(); + + Vector xNext = x.add(p.multiply(alpha)); + double beta = function.applyGradient(xNext).absSqr() / function.applyGradient(x).absSqr(); + Vector pNext = function.applyGradient(xNext).negate().add(p.multiply(beta)); + x = xNext; + p = pNext; + fx = function.applyFunction(x); + gradientFX = function.applyGradient(x); + System.out.println(String.format("%s val: %.10f", x, fx)); + System.out.println("gradient abs: " + gradientFX.abs()); + } + System.out.println(String.format("Result:\n%s val: %.10f", x, fx)); + } +} diff --git a/Lab2/src/methods/Dichotomy.java b/Lab2/src/methods/Dichotomy.java new file mode 100644 index 0000000..7c88a18 --- /dev/null +++ b/Lab2/src/methods/Dichotomy.java @@ -0,0 +1,39 @@ +package methods; + +import methods.result.DefaultIterationResult; +import methods.result.Result; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.DoubleUnaryOperator; + +public class Dichotomy implements Method { + private final double epsilon; + private final double delta; + + public Dichotomy(double epsilon) { + this.epsilon = epsilon; + this.delta = epsilon / 2; + } + + @Override + public Result calcAllIterations(DoubleUnaryOperator f, double a, double b) { + double x1, x2, e = (b - a) / 2; + List results = new ArrayList<>(); + while (compare(e, epsilon)) { + x1 = (a + b - delta) / 2; + x2 = (a + b + delta) / 2; + double f1 = f.applyAsDouble(x1); + double f2 = f.applyAsDouble(x2); + results.add(new DefaultIterationResult(a, b, x1, x2, f1, f2)); + if (compare(f2, f1)) { + b = x2; + } else { + a = x1; + } + e = (b - a) / 2; + } + return new Result<>((a + b) / 2, f.applyAsDouble((a + b) / 2), results); + } + +} diff --git a/Lab2/src/methods/FastestDescent.java b/Lab2/src/methods/FastestDescent.java new file mode 100644 index 0000000..347b16a --- /dev/null +++ b/Lab2/src/methods/FastestDescent.java @@ -0,0 +1,39 @@ +package methods; + +import elements.MyFunction; +import elements.Vector; +import methods.Dichotomy; +import methods.result.IterationResult; +import methods.result.Result; + +import java.util.function.DoubleUnaryOperator; +import java.util.function.UnaryOperator; + + +public class FastestDescent { + private final double epsilon; + + public FastestDescent(final double epsilon) { + this.epsilon = epsilon; + } + + public void calc(final MyFunction function, Vector x) { + Vector gradientFX = function.applyGradient(x); + Double fx = null; + System.out.println("gradient abs: " + gradientFX.abs()); + while (epsilon < gradientFX.abs()) { + Vector finalGradientFX = gradientFX; + Vector finalX = x; + DoubleUnaryOperator fAlpha = alpha -> function.applyFunction(finalX.subtract(finalGradientFX.multiply(alpha))); + Method method = new Dichotomy(epsilon); + Result result = method.calcAllIterations(fAlpha, 0, 100); + double alpha = result.getPoint(); + x = x.subtract(gradientFX.multiply(alpha)); + fx = function.applyFunction(x); + gradientFX = function.applyGradient(x); + System.out.println(String.format("%s val: %.10f", x, fx)); + System.out.println("gradient abs: " + gradientFX.abs()); + } + System.out.println(String.format("Result:\n%s val: %.10f", x, fx)); + } +} diff --git a/Lab2/src/methods/GradientDescent.java b/Lab2/src/methods/GradientDescent.java index 7c5fbef..95938e4 100644 --- a/Lab2/src/methods/GradientDescent.java +++ b/Lab2/src/methods/GradientDescent.java @@ -1,7 +1,7 @@ package methods; -import elements.MyFunction; import elements.Vector; +import elements.MyFunction; public class GradientDescent { private final double epsilon; @@ -30,7 +30,6 @@ public void calc(final MyFunction function, Vector x) { System.out.println(String.format("%s val: %.10f", x, fx)); System.out.println("gradient abs: " + gradientFX.abs()); } - System.out.println(String.format("Result:\n%s val: %.10f", x, fx)); } } diff --git a/Lab2/src/methods/Method.java b/Lab2/src/methods/Method.java new file mode 100644 index 0000000..326e945 --- /dev/null +++ b/Lab2/src/methods/Method.java @@ -0,0 +1,15 @@ +package methods; + +import methods.result.IterationResult; +import methods.result.Result; + +import java.util.function.DoubleUnaryOperator; + +public interface Method { + + Result calcAllIterations(DoubleUnaryOperator f, double a, double b); + + default boolean compare(double x, double y) { + return x - y >= 0; + } +} diff --git a/Lab2/src/methods/result/DefaultIterationResult.java b/Lab2/src/methods/result/DefaultIterationResult.java new file mode 100644 index 0000000..cdfb5d9 --- /dev/null +++ b/Lab2/src/methods/result/DefaultIterationResult.java @@ -0,0 +1,69 @@ +package methods.result; + +public class DefaultIterationResult implements IterationResult { + private final double a; + private final double b; + private final double x1; + private final double x2; + + private final double fx1; + private final double fx2; + + public DefaultIterationResult(double a, double b, double x1, double x2, double fx1, double fx2) { + this.a = a; + this.b = b; + this.x1 = x1; + this.x2 = x2; + this.fx1 = fx1; + this.fx2 = fx2; + } + + public double getA() { + return a; + } + + public double getB() { + return b; + } + + public double getX1() { + return x1; + } + + public double getX2() { + return x2; + } + + public double getFx1() { + return fx1; + } + + public double getFx2() { + return fx2; + } + + public String tableArgs() { + return "A & B & X1 & X2 & F(X1) & F(X2) & B - A"; + } + + public String asTable() { + return String.format("%.7f & %.7f & %.7f & %.7f & %.7f & %.7f & %.7f", + getA(), + getB(), + getX1(), + getX2(), + getFx1(), + getFx2(), + getB() - getA()); + } + + public String toString() { + return String.format("%.16f %.16f %.16f %.16f %.16f %.16f", + getA(), + getB(), + getX1(), + getX2(), + getFx1(), + getFx2()); + } +} diff --git a/Lab2/src/methods/result/IterationResult.java b/Lab2/src/methods/result/IterationResult.java new file mode 100644 index 0000000..0dcc033 --- /dev/null +++ b/Lab2/src/methods/result/IterationResult.java @@ -0,0 +1,6 @@ +package methods.result; + +public interface IterationResult { + String asTable(); + String tableArgs(); +} diff --git a/Lab2/src/methods/result/ParabolaIterationResult.java b/Lab2/src/methods/result/ParabolaIterationResult.java new file mode 100644 index 0000000..599587b --- /dev/null +++ b/Lab2/src/methods/result/ParabolaIterationResult.java @@ -0,0 +1,90 @@ +package methods.result; + + +public class ParabolaIterationResult implements IterationResult { + private final double x1; + private final double x2; + private final double x3; + + private final double fx1; + private final double fx2; + private final double fx3; + + private final double minX; + private final double fMinX; + + public ParabolaIterationResult(double x1, double x2, double x3, double minX, + double fx1, double fx2, double fx3, double fMinX) { + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + this.fx1 = fx1; + this.fx2 = fx2; + this.fx3 = fx3; + this.minX = minX; + this.fMinX = fMinX; + } + + public double getX1() { + return x1; + } + + public double getX2() { + return x2; + } + + public double getX3() { + return x3; + } + + public double getFx1() { + return fx1; + } + + public double getFx2() { + return fx2; + } + + public double getFx3() { + return fx3; + } + + public double getMinX() { + return minX; + } + + public double getfMinX() { + return fMinX; + } + + public String tableArgs() { + return "X1 & X2 & X3 & F(X1) & F(X2) & F(X3) & Minimal X & F(Minimal) & X3 - X1"; + } + + public String asTable() { + return String.format("%.7f & %.7f & %.7f & %.7f & %.7f & %.7f & %.7f & %.7f & %.7f", + getX1(), + getX2(), + getX3(), + getFx1(), + getFx2(), + getFx3(), + getMinX(), + getfMinX(), + getX3() - getX1() + ); + } + + public String toString() { + return String.format("%.16f %.16f %.16f %.16f %.16f %.16f %.16f %.16f", + getX1(), + getX2(), + getX3(), + getFx1(), + getFx2(), + getFx3(), + getMinX(), + getfMinX() + ); + } +} \ No newline at end of file diff --git a/Lab2/src/methods/result/Result.java b/Lab2/src/methods/result/Result.java new file mode 100644 index 0000000..c77feec --- /dev/null +++ b/Lab2/src/methods/result/Result.java @@ -0,0 +1,60 @@ +package methods.result; + + +import java.util.List; + +public class Result { + private final double point; + + private final double value; + + private final List iterations; + + public Result(double ans, double value, List iterations) { + this.point = ans; + this.value = value; + this.iterations = iterations; + } + + public double getPoint() { + return point; + } + + public double getValue() { + return value; + } + + public List getIterations() { + return iterations; + } + + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append( + String.format("Результат: точка: [ %.10f ], value [ %.10f ]\nКоличество итераций: %d\n", + getPoint(), + getValue(), + getIterations().size()) + ); + for (IterationResult result : getIterations()) { + stringBuilder.append(result.asTable()).append('\n'); + } + return stringBuilder.toString(); + } + public String asTable() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append( + String.format("Результат: точка: [ %.10f ], value [ %.10f ]\nКоличество итераций: %d\n", + getPoint(), + getValue(), + getIterations().size()) + ).append("\\begin{tabular}[b]{| l | l | l | l | l | l | l | l | l |}") + .append("\\hline\n").append(getIterations().get(0).tableArgs()).append("\\\\\\hline\n"); + + for (IterationResult result : getIterations()) { + stringBuilder.append(result.asTable()).append("\\\\\n"); + } + stringBuilder.append("\\hline\n\\end{tabular}"); + return stringBuilder.toString(); + } +}