From 7efcc9dc641b2723c6c87149ba97cff0f88b92af Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 16:54:15 +0300 Subject: [PATCH 1/7] Add Heun's method implementation to NumericalMethods --- .../java/com/solver/NumericalMethods.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/solver-common/src/main/java/com/solver/NumericalMethods.java b/solver-common/src/main/java/com/solver/NumericalMethods.java index e043801..9e99cc2 100644 --- a/solver-common/src/main/java/com/solver/NumericalMethods.java +++ b/solver-common/src/main/java/com/solver/NumericalMethods.java @@ -81,6 +81,29 @@ public static double[] methodRungeKutta(BiFunction f return result; } + public static double[] methodHeun(BiFunction f, double x_0, double[] y_0, double h) { + double[] y_next = new double[y_0.length]; + + double[] k1 = f.apply(x_0, y_0); + double[] temp = new double[y_0.length]; + + for (int i = 0; i < y_0.length; i++) { + temp[i] = y_0[i] + h * k1[i]; + } + + double[] k2 = f.apply(x_0 + h, temp); + + for (int i = 0; i < y_0.length; i++) { + y_next[i] = y_0[i] + (h / 2) * (k1[i] + k2[i]); + } + + double[] result = new double[y_0.length + 1]; + result[0] = x_0 + h; + System.arraycopy(y_next, 0, result, 1, y_0.length); + + return result; + } + public static double[] methodMidpoint(BiFunction f, double x_0, double[] y_0, double h) { double[] y_next = new double[y_0.length]; From b751a2530ce8fa6d3af53c93be291c14f08ba9cd Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:09:30 +0300 Subject: [PATCH 2/7] Refactor method type from int to String in Main and SolverRequest classes --- solver-common/src/main/java/com/solver/Main.java | 13 +++++++------ .../src/main/java/com/solver/SolverRequest.java | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/solver-common/src/main/java/com/solver/Main.java b/solver-common/src/main/java/com/solver/Main.java index 91d41cd..4c029a9 100644 --- a/solver-common/src/main/java/com/solver/Main.java +++ b/solver-common/src/main/java/com/solver/Main.java @@ -14,12 +14,12 @@ public class Main { private double[] initial_y; private double reach_point; private double step_size; - private int method; + private String method; private List xValues; private List yValues; - public void setMethod(int method) { + public void setMethod(String method) { this.method = method; } @@ -58,10 +58,11 @@ public double[] getSolution() { while (x < reach_point - 1e-10) { double[] result = switch (method) { - case 1 -> NumericalMethods.methodEuler(equationFunction, x, y, step_size); - case 2 -> NumericalMethods.methodMidpoint(equationFunction, x, y, step_size); - case 4 -> NumericalMethods.methodRungeKutta(equationFunction, x, y, step_size); - case 7 -> NumericalMethods.methodDormandPrince(equationFunction, x, y, step_size); + case "euler" -> NumericalMethods.methodEuler(equationFunction, x, y, step_size); + case "midpoint" -> NumericalMethods.methodMidpoint(equationFunction, x, y, step_size); + case "heun" -> NumericalMethods.methodHeun(equationFunction, x, y, step_size); + case "rungeKutta" -> NumericalMethods.methodRungeKutta(equationFunction, x, y, step_size); + case "dormandPrince" -> NumericalMethods.methodDormandPrince(equationFunction, x, y, step_size); default -> throw new IllegalArgumentException("Invalid method value: " + method); }; x = result[0]; diff --git a/solver-common/src/main/java/com/solver/SolverRequest.java b/solver-common/src/main/java/com/solver/SolverRequest.java index 0ec878e..27c19ad 100644 --- a/solver-common/src/main/java/com/solver/SolverRequest.java +++ b/solver-common/src/main/java/com/solver/SolverRequest.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; public class SolverRequest { - private int method; + private String method; private int order; private String userEquation; private String formattedEquation; @@ -13,8 +13,8 @@ public class SolverRequest { private double reachPoint; private double stepSize; - public int getMethod() { return method; } - public void setMethod(int method) { this.method = method; } + public String getMethod() { return method; } + public void setMethod(String method) { this.method = method; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } From f67d131c876428656a7ffde35ad9c86e0218be0c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:12:27 +0300 Subject: [PATCH 3/7] Refactor numerical method names in NumericalMethods --- solver-common/src/main/java/com/solver/Main.java | 10 +++++----- .../src/main/java/com/solver/NumericalMethods.java | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/solver-common/src/main/java/com/solver/Main.java b/solver-common/src/main/java/com/solver/Main.java index 4c029a9..28313e7 100644 --- a/solver-common/src/main/java/com/solver/Main.java +++ b/solver-common/src/main/java/com/solver/Main.java @@ -58,11 +58,11 @@ public double[] getSolution() { while (x < reach_point - 1e-10) { double[] result = switch (method) { - case "euler" -> NumericalMethods.methodEuler(equationFunction, x, y, step_size); - case "midpoint" -> NumericalMethods.methodMidpoint(equationFunction, x, y, step_size); - case "heun" -> NumericalMethods.methodHeun(equationFunction, x, y, step_size); - case "rungeKutta" -> NumericalMethods.methodRungeKutta(equationFunction, x, y, step_size); - case "dormandPrince" -> NumericalMethods.methodDormandPrince(equationFunction, x, y, step_size); + case "euler" -> NumericalMethods.euler(equationFunction, x, y, step_size); + case "midpoint" -> NumericalMethods.midpoint(equationFunction, x, y, step_size); + case "heun" -> NumericalMethods.heun(equationFunction, x, y, step_size); + case "rungeKutta" -> NumericalMethods.rungeKutta(equationFunction, x, y, step_size); + case "dormandPrince" -> NumericalMethods.dormandPrince(equationFunction, x, y, step_size); default -> throw new IllegalArgumentException("Invalid method value: " + method); }; x = result[0]; diff --git a/solver-common/src/main/java/com/solver/NumericalMethods.java b/solver-common/src/main/java/com/solver/NumericalMethods.java index 9e99cc2..4186168 100644 --- a/solver-common/src/main/java/com/solver/NumericalMethods.java +++ b/solver-common/src/main/java/com/solver/NumericalMethods.java @@ -3,7 +3,7 @@ import java.util.function.BiFunction; public class NumericalMethods { - public static double[] methodDormandPrince(BiFunction f, double x_0, double[] y_0, double h) { + public static double[] dormandPrince(BiFunction f, double x_0, double[] y_0, double h) { double[] k1 = new double[y_0.length]; double[] k2 = new double[y_0.length]; double[] k3 = new double[y_0.length]; @@ -53,7 +53,7 @@ public static double[] methodDormandPrince(BiFunction f, double x_0, double[] y_0, double h) { + public static double[] rungeKutta(BiFunction f, double x_0, double[] y_0, double h) { double[] k1 = new double[y_0.length]; double[] k2 = new double[y_0.length]; double[] k3 = new double[y_0.length]; @@ -81,7 +81,7 @@ public static double[] methodRungeKutta(BiFunction f return result; } - public static double[] methodHeun(BiFunction f, double x_0, double[] y_0, double h) { + public static double[] heun(BiFunction f, double x_0, double[] y_0, double h) { double[] y_next = new double[y_0.length]; double[] k1 = f.apply(x_0, y_0); @@ -104,7 +104,7 @@ public static double[] methodHeun(BiFunction f, doub return result; } - public static double[] methodMidpoint(BiFunction f, double x_0, double[] y_0, double h) { + public static double[] midpoint(BiFunction f, double x_0, double[] y_0, double h) { double[] y_next = new double[y_0.length]; double[] k1 = f.apply(x_0, y_0); @@ -127,7 +127,7 @@ public static double[] methodMidpoint(BiFunction f, return result; } - public static double[] methodEuler(BiFunction f, double x_0, double[] y_0, double h) { + public static double[] euler(BiFunction f, double x_0, double[] y_0, double h) { double[] y_next = new double[y_0.length]; double[] k1 = f.apply(x_0, y_0); From 90df42a1d8a030e6a7dcc88f24f20b21485103be Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:38:24 +0300 Subject: [PATCH 4/7] Refactor variable names in Main --- .../src/main/java/com/solver/Main.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/solver-common/src/main/java/com/solver/Main.java b/solver-common/src/main/java/com/solver/Main.java index 28313e7..bf551dd 100644 --- a/solver-common/src/main/java/com/solver/Main.java +++ b/solver-common/src/main/java/com/solver/Main.java @@ -10,10 +10,10 @@ public class Main { private int order; private BiFunction equationFunction; - private double initial_x; - private double[] initial_y; - private double reach_point; - private double step_size; + private double initialX; + private double[] initialY; + private double reachPoint; + private double stepSize; private String method; private List xValues; @@ -33,36 +33,36 @@ public void setEquation(String equation) { this.equationFunction = CreateEquationFunction.create(equation, this.order); } - public void setInitialX(double initial_x) { - this.initial_x = initial_x; + public void setInitialX(double initialX) { + this.initialX = initialX; } - public void setInitialY(double... initial_y) { - this.initial_y = initial_y; + public void setInitialY(double... initialY) { + this.initialY = initialY; } - public void setReachPoint(double reach_point) { - this.reach_point = reach_point; + public void setReachPoint(double reachPoint) { + this.reachPoint = reachPoint; } - public void setStepSize(double step_size) { - this.step_size = step_size; + public void setStepSize(double stepSize) { + this.stepSize = stepSize; } public double[] getSolution() { xValues = new ArrayList<>(); yValues = new ArrayList<>(); - double x = initial_x; - double[] y = initial_y.clone(); + double x = initialX; + double[] y = initialY.clone(); - while (x < reach_point - 1e-10) { + while (x < reachPoint - 1e-10) { double[] result = switch (method) { - case "euler" -> NumericalMethods.euler(equationFunction, x, y, step_size); - case "midpoint" -> NumericalMethods.midpoint(equationFunction, x, y, step_size); - case "heun" -> NumericalMethods.heun(equationFunction, x, y, step_size); - case "rungeKutta" -> NumericalMethods.rungeKutta(equationFunction, x, y, step_size); - case "dormandPrince" -> NumericalMethods.dormandPrince(equationFunction, x, y, step_size); + case "euler" -> NumericalMethods.euler(equationFunction, x, y, stepSize); + case "midpoint" -> NumericalMethods.midpoint(equationFunction, x, y, stepSize); + case "heun" -> NumericalMethods.heun(equationFunction, x, y, stepSize); + case "rungeKutta" -> NumericalMethods.rungeKutta(equationFunction, x, y, stepSize); + case "dormandPrince" -> NumericalMethods.dormandPrince(equationFunction, x, y, stepSize); default -> throw new IllegalArgumentException("Invalid method value: " + method); }; x = result[0]; From e117e0127ec0da02bc0c89ce8c2a7e7b41db2192 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:38:55 +0300 Subject: [PATCH 5/7] Add Heun's Method translations to language file --- solver-bot/src/main/python/languages.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/solver-bot/src/main/python/languages.json b/solver-bot/src/main/python/languages.json index a3e745f..18d611b 100644 --- a/solver-bot/src/main/python/languages.json +++ b/solver-bot/src/main/python/languages.json @@ -56,6 +56,7 @@ "method_euler": "Euler's Method", "method_midpoint": "Midpoint Method", + "method_heun": "Heun's Method", "method_runge_kutta": "Runge-Kutta Method", "method_dormand_prince": "Dormand-Prince Method", @@ -124,6 +125,7 @@ "method_euler": "Метод Эйлера", "method_midpoint": "Метод Средней Точки", + "method_heun": "Метод Хойна", "method_runge_kutta": "Метод Рунге-Кутта", "method_dormand_prince": "Метод Дормана-Принса", @@ -192,6 +194,7 @@ "method_euler": "欧拉法", "method_midpoint": "中点法", + "method_heun": "休恩法", "method_runge_kutta": "龙格-库塔法", "method_dormand_prince": "多曼德-普林斯法", From 255f4b7973417a96466a9e7cb12bc9a13241a0fc Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:39:28 +0300 Subject: [PATCH 6/7] Refactor method mapping in set_parameters to use string identifiers --- solver-bot/src/main/python/spring_client.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/solver-bot/src/main/python/spring_client.py b/solver-bot/src/main/python/spring_client.py index c5fc5ce..c3c8e0c 100644 --- a/solver-bot/src/main/python/spring_client.py +++ b/solver-bot/src/main/python/spring_client.py @@ -15,14 +15,15 @@ async def set_parameters( initial_x, initial_y, reach_point, step_size ): method_mapping = { - "method_euler": 1, - "method_midpoint": 2, - "method_runge_kutta": 4, - "method_dormand_prince": 7 + "method_euler": "euler", + "method_midpoint": "midpoint", + "method_heun": "heun", + "method_runge_kutta": "rungeKutta", + "method_dormand_prince": "dormandPrince", } payload = { - "method": method_mapping.get(method, 1), + "method": method_mapping.get(method, "euler"), "order": int(order), "userEquation": user_equation, "formattedEquation": formatted_equation, From 3c0592ef276e3a838872f0b9e03f817541d7de4c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 21 May 2025 17:39:45 +0300 Subject: [PATCH 7/7] Add Heun's Method to settings and method mapping --- solver-bot/src/main/python/shell.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/solver-bot/src/main/python/shell.py b/solver-bot/src/main/python/shell.py index 33f5662..ab2811b 100644 --- a/solver-bot/src/main/python/shell.py +++ b/solver-bot/src/main/python/shell.py @@ -214,6 +214,12 @@ async def settings_method(update: Update, context: ContextTypes.DEFAULT_TYPE): if current_method == "method_midpoint" else InlineKeyboardButton( LANG_TEXTS[current_language]["method_midpoint"], callback_data="method_midpoint")], + [InlineKeyboardButton( + f"→ {LANG_TEXTS[current_language]["method_heun"]} ←", + callback_data="method_heun") + if current_method == "method_heun" else InlineKeyboardButton( + LANG_TEXTS[current_language]["method_heun"], + callback_data="method_heun")], [InlineKeyboardButton( f"→ {LANG_TEXTS[current_language]["method_runge_kutta"]} ←", callback_data="method_runge_kutta") @@ -472,10 +478,11 @@ async def solve_history_details(update: Update, context: ContextTypes.DEFAULT_TY initial_y_str = str(initial_y) method_mapping = { - 1: LANG_TEXTS[current_language]["method_euler"], - 2: LANG_TEXTS[current_language]["method_midpoint"], - 4: LANG_TEXTS[current_language]["method_runge_kutta"], - 7: LANG_TEXTS[current_language]["method_dormand_prince"] + "euler": LANG_TEXTS[current_language]["method_euler"], + "midpoint": LANG_TEXTS[current_language]["method_midpoint"], + "heun": LANG_TEXTS[current_language]["method_heun"], + "rungeKutta": LANG_TEXTS[current_language]["method_runge_kutta"], + "dormandPrince": LANG_TEXTS[current_language]["method_dormand_prince"] } method_display = method_mapping.get(method, method) @@ -952,7 +959,7 @@ def main() -> None: CallbackQueryHandler(settings_language, pattern="^settings_language$"), CallbackQueryHandler( method, - pattern="^method_(euler|midpoint|runge_kutta|dormand_prince)$" + pattern="^method_(euler|midpoint|heun|runge_kutta|dormand_prince)$" ), CallbackQueryHandler(rounding, pattern="^(4|6|8|16)$"), CallbackQueryHandler(language, pattern="^(en|ru|zh)$"),