diff --git a/PowellProcess.cpp b/PowellProcess.cpp new file mode 100644 index 0000000..675d713 --- /dev/null +++ b/PowellProcess.cpp @@ -0,0 +1,172 @@ +#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; +}