#include #include #include #include #include #include #include #include // Тип функции из DLL typedef double (*TargetFunctionType)(double*, int); TargetFunctionType g_TargetFunction = nullptr; // Обертка для вызова целевой функции double CallTargetFunction(const std::vector& x) { if (!g_TargetFunction) return 0.0; return g_TargetFunction(const_cast(&x[0]), static_cast(x.size())); } void add_scaled(const std::vector& dir, std::vector& res, double lambda) { for (size_t i = 0; i < dir.size(); ++i) { res[i] += lambda * dir[i]; } } // Поиск интервала (из peyll.txt) void get_lambda_segment(const std::vector& point, const std::vector& dir, double step, double& a, double& c) { double left = 0, middle = 0, right = 0; double y_curr = CallTargetFunction(point); double y_next = y_curr; double r = (3.0 - std::sqrt(5.0)) / 2.0; r = (1.0 - r) / r; // ~ 1.618 int iterations = 0; do { y_curr = y_next; left = middle; middle = right; right += step; std::vector x = point; add_scaled(dir, x, right); y_next = CallTargetFunction(x); step *= r; iterations++; } while (y_next < y_curr && iterations < 100); a = left; c = right; } // Золотое сечение (из peyll.txt) double gold_method(const std::vector& point, const std::vector& dir, double a, double c, double eps) { double r = (3.0 - std::sqrt(5.0)) / 2.0; double b = a + r * (c - a); std::vector x_b = point; add_scaled(dir, x_b, b); double y_b = CallTargetFunction(x_b); while (std::abs(c - a) > eps) { double d = c + r * (a - c); std::vector x_d = point; add_scaled(dir, x_d, d); double y_d = CallTargetFunction(x_d); if (y_d < y_b) { a = b; b = d; y_b = y_d; } else { c = a; a = d; } } return (a + c) / 2.0; } // Поиск лучшей лямбды в обоих направлениях double get_best_lambda(const std::vector& point, const std::vector& dir, double eps, double initial_step) { double a, c; // Поиск в '+' get_lambda_segment(point, dir, initial_step, a, c); double l1 = gold_method(point, dir, a, c, eps); // Поиск в '-' get_lambda_segment(point, dir, -initial_step, a, c); double l2 = gold_method(point, dir, a, c, eps); std::vector x1 = point, x2 = point; add_scaled(dir, x1, l1); add_scaled(dir, x2, l2); return (CallTargetFunction(x1) < CallTargetFunction(x2)) ? l1 : l2; } int main(int argc, char* argv[]) { // ВАЖНО: argc - 1 (exe) - 1 (dll) - 1 (eps) - 1 (iter) - 1 (step) = N // Значит N = argc - 5 if (argc < 6) { std::cerr << "Error: Not enough arguments! Received: " << argc << std::endl; return 1; } HMODULE hLib = NULL; try { std::string dllPath = argv[1]; int numVars = argc - 5; std::vector x(numVars); for (int i = 0; i < numVars; i++) { x[i] = std::stod(argv[2 + i]); } double epsilon = std::stod(argv[argc - 3]); int maxIter = std::stoi(argv[argc - 2]); double userStep = std::stod(argv[argc - 1]); // Возвращенный параметр шага std::cout << "Starting Powell Optimization..." << std::endl; std::cout << "DLL: " << dllPath << " | Vars: " << numVars << std::endl; std::cout << "Eps: " << epsilon << " | MaxIter: " << maxIter << " | Step: " << userStep << std::endl; std::cout << "------------------------------------------" << std::endl; hLib = LoadLibraryA(dllPath.c_str()); if (!hLib) throw std::runtime_error("Could not load DLL: " + dllPath); g_TargetFunction = (TargetFunctionType)GetProcAddress(hLib, "targetFunction"); if (!g_TargetFunction) throw std::runtime_error("Function 'targetFunction' not found in DLL."); std::vector> directions(numVars, std::vector(numVars, 0.0)); for (int i = 0; i < numVars; ++i) directions[i][i] = 1.0; int iterations = 0; bool converged = false; while (iterations < maxIter) { double f_start = CallTargetFunction(x); std::vector p_start = x; // 1. Поиск по текущим направлениям for (int i = 0; i < numVars; ++i) { double lambda = get_best_lambda(x, directions[i], epsilon, userStep); add_scaled(directions[i], x, lambda); } // 2. Новое направление (сопряженное) std::vector new_dir(numVars); for (int i = 0; i < numVars; ++i) new_dir[i] = x[i] - p_start[i]; double lambda = get_best_lambda(x, new_dir, epsilon, userStep); add_scaled(new_dir, x, lambda); // 3. Обновление направлений for (int i = 0; i < numVars - 1; ++i) directions[i] = directions[i + 1]; directions[numVars - 1] = new_dir; iterations++; double f_end = CallTargetFunction(x); double delta = std::abs(f_start - f_end); std::cout << "Iteration " << iterations << ": F = " << f_end << " (delta: " << delta << ")" << std::endl; if (delta < epsilon) { converged = true; break; } } std::cout << "\n========================================\n"; std::cout << "RESULT: " << (converged ? "CONVERGED" : "MAX ITERATIONS REACHED") << std::endl; for (int i = 0; i < numVars; i++) std::cout << "x[" << i << "] = " << x[i] << std::endl; std::cout << "F(min) = " << CallTargetFunction(x) << std::endl; std::cout << "Iterations: " << iterations << std::endl; std::cout << "========================================\n"; } catch (const std::exception& e) { std::cerr << "RUNTIME ERROR: " << e.what() << std::endl; } if (hLib) FreeLibrary(hLib); return 0; }