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": "多曼德-普林斯法", 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)$"), 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, diff --git a/solver-common/src/main/java/com/solver/Main.java b/solver-common/src/main/java/com/solver/Main.java index 91d41cd..bf551dd 100644 --- a/solver-common/src/main/java/com/solver/Main.java +++ b/solver-common/src/main/java/com/solver/Main.java @@ -10,16 +10,16 @@ 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 int method; + private double initialX; + private double[] initialY; + private double reachPoint; + private double stepSize; + private String method; private List xValues; private List yValues; - public void setMethod(int method) { + public void setMethod(String method) { this.method = method; } @@ -33,35 +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 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.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]; diff --git a/solver-common/src/main/java/com/solver/NumericalMethods.java b/solver-common/src/main/java/com/solver/NumericalMethods.java index e043801..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,30 @@ public static double[] methodRungeKutta(BiFunction f return result; } - public static double[] methodMidpoint(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); + 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[] 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); @@ -104,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); 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; }