From be52caab8efb04fc2361b07784be9e2144ae77d0 Mon Sep 17 00:00:00 2001 From: LebedevIlyaG Date: Wed, 8 May 2024 10:29:56 +0300 Subject: [PATCH] Mco (#190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * MCO rebase to main (#183) * Benchmarks (#165) * add benchmarks * fix readme * fix readme * bolt font for arguments * Перевод комментариев в разделе iOpt на английский для документации (#164) * Перевод комментариев в разделе iOpt на английский для документации * Перевод комментариев в разделе iOpt на английский для документации (с исправлениями) * Исправление замечаний по переводу комментов iOpt * Исправление замечаний по переводу комментов iOpt (2) * Перевод комментариев из раздела problems * Update .readthedocs.yml for current requirements of Read the Docs * Update .readthedocs.yml * Update .readthedocs.yml * Update conf.py for English language * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. (#167) * Fixed a bug in the calculator destructor (#168) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Correct target score (#170) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Grid search (#169) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Added grid search * Fixed search * Corrected comments * Fix problem with pool * Removed unnecessary field * Corrected comments * Построение по сеткам известных точек + исправление багов (#172) * add graph by points * fix double axes bug * add lines layers by points --------- Co-authored-by: Marina Usova * Асинхронная параллельная схема (#166) * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * semi-fix for iter-tasks * Fixed test for asynchronous parallel circuit (#173) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Fixed test for asynchronous parallel circuit * add characteristic in save progress (#176) * add characteristic in save progress * add sol time&accuracy * Дополнение для сохранения в JSON (#177) * add characteristic in save progress * add sol time&accuracy * add Task, Parameters and creation_time for sd_item in save_progress * change save&load * Update method.py * meaningless change * add _init_ in loadProgress * The output of the optimal solution in problems with restrictions has … (#180) * The output of the optimal solution in problems with restrictions has been corrected Parallel index calculator is working properly * Update Stronginc3_example.py * Fix bug with original optimum using (#181) * fix bug with original optimum using * add var for number of constraints and fix objective function value --------- Co-authored-by: Marina Usova * Corrected documentation of examples (#182) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Append new examples. Correct documentation * Corrected documentation of examples * The calculator is used in trial calculation * Added work with the calculator * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * The calculator is used in trial calculation * Added work with the calculator * Corrected to match the updated interface * Added example with MCO Test1 * Fixed calculator factory --------- Co-authored-by: dyonichhh <36537172+RodionovDenis@users.noreply.github.com> Co-authored-by: Anton A. Shtanyuk Co-authored-by: Alexander Sysoyev Co-authored-by: Karchkov Denis Co-authored-by: UsovaMA Co-authored-by: Marina Usova Co-authored-by: oleg-w570 <73493289+oleg-w570@users.noreply.github.com> Co-authored-by: Yanina Kolt <43132462+YaniKolt@users.noreply.github.com> Co-authored-by: kozinove Co-authored-by: MADZEROPIE * Mco (#186) * Added support for parallel computing mco_process.py -> mco_method_many_lambdas.py * fix tests * Исправлена асинхронная схема * fix comments * fix comment * fix comment * Add mco breast cancer problem (#187) * Benchmarks (#165) * add benchmarks * fix readme * fix readme * bolt font for arguments * Перевод комментариев в разделе iOpt на английский для документации (#164) * Перевод комментариев в разделе iOpt на английский для документации * Перевод комментариев в разделе iOpt на английский для документации (с исправлениями) * Исправление замечаний по переводу комментов iOpt * Исправление замечаний по переводу комментов iOpt (2) * Перевод комментариев из раздела problems * Update .readthedocs.yml for current requirements of Read the Docs * Update .readthedocs.yml * Update .readthedocs.yml * Update conf.py for English language * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. (#167) * Fixed a bug in the calculator destructor (#168) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Correct target score (#170) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Grid search (#169) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Added grid search * Fixed search * Corrected comments * Fix problem with pool * Removed unnecessary field * Corrected comments * Построение по сеткам известных точек + исправление багов (#172) * add graph by points * fix double axes bug * add lines layers by points --------- Co-authored-by: Marina Usova * Асинхронная параллельная схема (#166) * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * semi-fix for iter-tasks * Fixed test for asynchronous parallel circuit (#173) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Fixed test for asynchronous parallel circuit * add characteristic in save progress (#176) * add characteristic in save progress * add sol time&accuracy * Дополнение для сохранения в JSON (#177) * add characteristic in save progress * add sol time&accuracy * add Task, Parameters and creation_time for sd_item in save_progress * change save&load * Update method.py * meaningless change * add _init_ in loadProgress * The output of the optimal solution in problems with restrictions has … (#180) * The output of the optimal solution in problems with restrictions has been corrected Parallel index calculator is working properly * Update Stronginc3_example.py * Fix bug with original optimum using (#181) * fix bug with original optimum using * add var for number of constraints and fix objective function value --------- Co-authored-by: Marina Usova * Corrected documentation of examples (#182) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Append new examples. Correct documentation * Corrected documentation of examples * The calculator is used in trial calculation * Added work with the calculator * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * The calculator is used in trial calculation * Added work with the calculator * Corrected to match the updated interface * Added example with MCO Test1 * Fixed calculator factory * Add mco breast cancer problem * line end character changed * Files moved * Corrected comments --------- Co-authored-by: dyonichhh <36537172+RodionovDenis@users.noreply.github.com> Co-authored-by: Anton A. Shtanyuk Co-authored-by: Alexander Sysoyev Co-authored-by: Karchkov Denis Co-authored-by: UsovaMA Co-authored-by: Marina Usova Co-authored-by: oleg-w570 <73493289+oleg-w570@users.noreply.github.com> Co-authored-by: Yanina Kolt <43132462+YaniKolt@users.noreply.github.com> Co-authored-by: kozinove Co-authored-by: MADZEROPIE * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * MCO rebase to main (#183) * Benchmarks (#165) * add benchmarks * fix readme * fix readme * bolt font for arguments * Перевод комментариев в разделе iOpt на английский для документации (#164) * Перевод комментариев в разделе iOpt на английский для документации * Перевод комментариев в разделе iOpt на английский для документации (с исправлениями) * Исправление замечаний по переводу комментов iOpt * Исправление замечаний по переводу комментов iOpt (2) * Перевод комментариев из раздела problems * Update .readthedocs.yml for current requirements of Read the Docs * Update .readthedocs.yml * Update .readthedocs.yml * Update conf.py for English language * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. (#167) * Fixed a bug in the calculator destructor (#168) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Correct target score (#170) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Grid search (#169) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Added grid search * Fixed search * Corrected comments * Fix problem with pool * Removed unnecessary field * Corrected comments * Построение по сеткам известных точек + исправление багов (#172) * add graph by points * fix double axes bug * add lines layers by points --------- Co-authored-by: Marina Usova * Асинхронная параллельная схема (#166) * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * semi-fix for iter-tasks * Fixed test for asynchronous parallel circuit (#173) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Fixed test for asynchronous parallel circuit * add characteristic in save progress (#176) * add characteristic in save progress * add sol time&accuracy * Дополнение для сохранения в JSON (#177) * add characteristic in save progress * add sol time&accuracy * add Task, Parameters and creation_time for sd_item in save_progress * change save&load * Update method.py * meaningless change * add _init_ in loadProgress * The output of the optimal solution in problems with restrictions has … (#180) * The output of the optimal solution in problems with restrictions has been corrected Parallel index calculator is working properly * Update Stronginc3_example.py * Fix bug with original optimum using (#181) * fix bug with original optimum using * add var for number of constraints and fix objective function value --------- Co-authored-by: Marina Usova * Corrected documentation of examples (#182) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Append new examples. Correct documentation * Corrected documentation of examples * The calculator is used in trial calculation * Added work with the calculator * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * The calculator is used in trial calculation * Added work with the calculator * Corrected to match the updated interface * Added example with MCO Test1 * Fixed calculator factory --------- Co-authored-by: dyonichhh <36537172+RodionovDenis@users.noreply.github.com> Co-authored-by: Anton A. Shtanyuk Co-authored-by: Alexander Sysoyev Co-authored-by: Karchkov Denis Co-authored-by: UsovaMA Co-authored-by: Marina Usova Co-authored-by: oleg-w570 <73493289+oleg-w570@users.noreply.github.com> Co-authored-by: Yanina Kolt <43132462+YaniKolt@users.noreply.github.com> Co-authored-by: kozinove Co-authored-by: MADZEROPIE * Mco (#186) * Added support for parallel computing mco_process.py -> mco_method_many_lambdas.py * fix tests * Исправлена асинхронная схема * fix comments * fix comment * fix comment * Add mco breast cancer problem (#187) * Benchmarks (#165) * add benchmarks * fix readme * fix readme * bolt font for arguments * Перевод комментариев в разделе iOpt на английский для документации (#164) * Перевод комментариев в разделе iOpt на английский для документации * Перевод комментариев в разделе iOpt на английский для документации (с исправлениями) * Исправление замечаний по переводу комментов iOpt * Исправление замечаний по переводу комментов iOpt (2) * Перевод комментариев из раздела problems * Update .readthedocs.yml for current requirements of Read the Docs * Update .readthedocs.yml * Update .readthedocs.yml * Update conf.py for English language * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. (#167) * Fixed a bug in the calculator destructor (#168) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Correct target score (#170) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Grid search (#169) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Added grid search * Fixed search * Corrected comments * Fix problem with pool * Removed unnecessary field * Corrected comments * Построение по сеткам известных точек + исправление багов (#172) * add graph by points * fix double axes bug * add lines layers by points --------- Co-authored-by: Marina Usova * Асинхронная параллельная схема (#166) * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * async initial * async up * async second * pep8 * pep8 * switch multiprocessing to multiprocess (part of pathos) * revert gkls example * revert requirements.txt * move async implementation from async_parallel_process to async_calculator * pep8 * redundant code removed * test for async parallel process * gkls async example add multiprocess to requirements * gkls async example * semi-fix for iter-tasks * Fixed test for asynchronous parallel circuit (#173) * Fixed a bug in the calculator destructor * Fixed problem with process pool destruction * The design of the example is brought to a single sample * Fixed test for asynchronous parallel circuit * add characteristic in save progress (#176) * add characteristic in save progress * add sol time&accuracy * Дополнение для сохранения в JSON (#177) * add characteristic in save progress * add sol time&accuracy * add Task, Parameters and creation_time for sd_item in save_progress * change save&load * Update method.py * meaningless change * add _init_ in loadProgress * The output of the optimal solution in problems with restrictions has … (#180) * The output of the optimal solution in problems with restrictions has been corrected Parallel index calculator is working properly * Update Stronginc3_example.py * Fix bug with original optimum using (#181) * fix bug with original optimum using * add var for number of constraints and fix objective function value --------- Co-authored-by: Marina Usova * Corrected documentation of examples (#182) * I supplemented the documentation with a paragraph about the work of the framework with the optimal selection of two real and one discrete parameters. Corrected the problem code for finding real and discrete parameters. * correct target score * Append new examples. Correct documentation * Corrected documentation of examples * The calculator is used in trial calculation * Added work with the calculator * Реализация решения задач MCO (#163) * 1. Добавлены интерфейсы классов для многокритериальной оптимизации * rename classes * Рабочая начальная версия mco (#179) * mco test problem & optim task * mco test problem & optim task 2 * added mco_process, fixed convolution and added to mco to solverFactory * mco test problem & optim task 3 * reverted optim task. shouldn't have touched in first place * fixed bug * mco test problem & optim task 4 * mco test problem & optim task 5 * mco test problem & optim task 6 * new problem&test, update method * working ver * mb work * delete comment, add task, evolvent for init lambdas, other refac * delete comment, add start_lambdas&is_scaling, add init_lambdas * fix with comments * fix with comments 1 --------- Co-authored-by: MADZEROPIE * The calculator is used in trial calculation * Added work with the calculator * Corrected to match the updated interface * Added example with MCO Test1 * Fixed calculator factory * Add mco breast cancer problem * line end character changed * Files moved * Corrected comments --------- Co-authored-by: dyonichhh <36537172+RodionovDenis@users.noreply.github.com> Co-authored-by: Anton A. Shtanyuk Co-authored-by: Alexander Sysoyev Co-authored-by: Karchkov Denis Co-authored-by: UsovaMA Co-authored-by: Marina Usova Co-authored-by: oleg-w570 <73493289+oleg-w570@users.noreply.github.com> Co-authored-by: Yanina Kolt <43132462+YaniKolt@users.noreply.github.com> Co-authored-by: kozinove Co-authored-by: MADZEROPIE * Corrected design * Fixed a bug in task connection * Fixed examples of optimizing the launch of a genetic algorithm * Corrected comments * Corrected design * Corrected comments --------- Co-authored-by: kozinove Co-authored-by: Yanina Kolt <43132462+YaniKolt@users.noreply.github.com> Co-authored-by: MADZEROPIE Co-authored-by: dyonichhh <36537172+RodionovDenis@users.noreply.github.com> Co-authored-by: Anton A. Shtanyuk Co-authored-by: Alexander Sysoyev Co-authored-by: Karchkov Denis Co-authored-by: UsovaMA Co-authored-by: Marina Usova Co-authored-by: oleg-w570 <73493289+oleg-w570@users.noreply.github.com> --- examples/GKLS_async_example.py | 1 - examples/GKLS_example.py | 1 - .../TSP/_1D/Problems/ga_tsp_vary_mutation.py | 4 +- .../TSP/_2D/Problems/ga_tsp_2d.py | 5 +- examples/MCO_Grishagin_example.py | 40 ++++ examples/MCO_Test1_example.py | 49 ++++ .../SVC/_2D/MCO_breast_cancer_example.py | 73 ++++++ .../SVC/_2D/Problems/mco_breast_cancer.py | 67 ++++++ examples/grid_search_example.py | 3 +- iOpt/method/async_calculator.py | 1 + iOpt/method/async_parallel_process.py | 10 +- iOpt/method/calculator.py | 44 ++-- iOpt/method/default_calculator.py | 37 +++ iOpt/method/grid_search_method.py | 8 - iOpt/method/index_method.py | 35 +-- ...calculator.py => index_method_evaluate.py} | 32 ++- iOpt/method/listener.py | 3 +- iOpt/method/mco_method.py | 223 ++++++++++++++++++ iOpt/method/mco_method_evaluate.py | 71 ++++++ iOpt/method/mco_method_many_lambdas.py | 111 +++++++++ iOpt/method/mco_optim_task.py | 103 ++++++++ iOpt/method/method.py | 31 +-- iOpt/method/mixed_integer_method.py | 14 +- iOpt/method/parallel_process.py | 12 +- iOpt/method/process.py | 26 +- iOpt/method/search_data.py | 1 + iOpt/method/solverFactory.py | 70 +++++- .../painters/animate_painters.py | 2 +- iOpt/solver.py | 32 ++- iOpt/solver_parametrs.py | 10 +- problems/grishagin_mco.py | 68 ++++++ problems/mco_test1.py | 60 +++++ problems/mco_test1_1.py | 63 +++++ problems/mco_test3.py | 60 +++++ problems/mco_test5.py | 70 ++++++ problems/mco_test6.py | 56 +++++ problems/mco_test7.py | 63 +++++ test/iOpt/method/test_mco_task.py | 80 +++++++ test/iOpt/method/test_method.py | 4 +- test/iOpt/method/test_mixed_integer_method.py | 11 +- .../method/test_multi_objective_method.py | 193 +++++++++++++++ test/iOpt/method/test_process.py | 1 + .../pointsForTest/mco_test1_points.py | 128 ++++++++++ .../pointsForTest/mco_test3_points.py | 105 +++++++++ .../pointsForTest/mco_test5_points.py | 106 +++++++++ .../pointsForTest/mco_test6_points.py | 105 +++++++++ .../pointsForTest/mco_test7_points.py | 110 +++++++++ test/problems/test_mco_problem.py | 73 ++++++ 48 files changed, 2322 insertions(+), 153 deletions(-) create mode 100644 examples/MCO_Grishagin_example.py create mode 100644 examples/MCO_Test1_example.py create mode 100644 examples/Machine_learning/SVC/_2D/MCO_breast_cancer_example.py create mode 100644 examples/Machine_learning/SVC/_2D/Problems/mco_breast_cancer.py create mode 100644 iOpt/method/default_calculator.py rename iOpt/method/{index_method_calculator.py => index_method_evaluate.py} (56%) create mode 100644 iOpt/method/mco_method.py create mode 100644 iOpt/method/mco_method_evaluate.py create mode 100644 iOpt/method/mco_method_many_lambdas.py create mode 100644 iOpt/method/mco_optim_task.py create mode 100644 problems/grishagin_mco.py create mode 100644 problems/mco_test1.py create mode 100644 problems/mco_test1_1.py create mode 100644 problems/mco_test3.py create mode 100644 problems/mco_test5.py create mode 100644 problems/mco_test6.py create mode 100644 problems/mco_test7.py create mode 100644 test/iOpt/method/test_mco_task.py create mode 100644 test/iOpt/method/test_multi_objective_method.py create mode 100644 test/problems/pointsForTest/mco_test1_points.py create mode 100644 test/problems/pointsForTest/mco_test3_points.py create mode 100644 test/problems/pointsForTest/mco_test5_points.py create mode 100644 test/problems/pointsForTest/mco_test6_points.py create mode 100644 test/problems/pointsForTest/mco_test7_points.py create mode 100644 test/problems/test_mco_problem.py diff --git a/examples/GKLS_async_example.py b/examples/GKLS_async_example.py index 529f7f60..29ef50a4 100644 --- a/examples/GKLS_async_example.py +++ b/examples/GKLS_async_example.py @@ -1,5 +1,4 @@ from iOpt.output_system.listeners.console_outputers import ConsoleOutputListener -from iOpt.output_system.listeners.static_painters import StaticPainterNDListener from iOpt.solver import Solver from iOpt.solver_parametrs import SolverParameters from problems.GKLS import GKLS diff --git a/examples/GKLS_example.py b/examples/GKLS_example.py index dce71444..0feadcd7 100644 --- a/examples/GKLS_example.py +++ b/examples/GKLS_example.py @@ -30,4 +30,3 @@ # Решение задачи solver.solve() - diff --git a/examples/Genetic_algorithm/TSP/_1D/Problems/ga_tsp_vary_mutation.py b/examples/Genetic_algorithm/TSP/_1D/Problems/ga_tsp_vary_mutation.py index 0037a3c5..4c9ddef3 100644 --- a/examples/Genetic_algorithm/TSP/_1D/Problems/ga_tsp_vary_mutation.py +++ b/examples/Genetic_algorithm/TSP/_1D/Problems/ga_tsp_vary_mutation.py @@ -58,10 +58,10 @@ def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValu :param function_value: объект хранения значения целевой функции в точке """ mutation_prob = point.float_variables[0] - ga_tsp = GA_TSP(func=self.calc_total_distance, + ga_tsp = GA_TSP(func=lambda x: self.calc_total_distance(x), n_dim=self.n_dim, size_pop=self.populationSize, max_iter=self.numberOfIterations, prob_mut=mutation_prob) best_points, best_distance = ga_tsp.run() function_value.value = best_distance[0] # print(best_distance[0]) - return function_value + return function_value \ No newline at end of file diff --git a/examples/Genetic_algorithm/TSP/_2D/Problems/ga_tsp_2d.py b/examples/Genetic_algorithm/TSP/_2D/Problems/ga_tsp_2d.py index 02c38dfe..c948f7b6 100644 --- a/examples/Genetic_algorithm/TSP/_2D/Problems/ga_tsp_2d.py +++ b/examples/Genetic_algorithm/TSP/_2D/Problems/ga_tsp_2d.py @@ -1,7 +1,6 @@ import numpy as np from iOpt.trial import Point from iOpt.trial import FunctionValue -from iOpt.trial import Trial from iOpt.problem import Problem from sko.GA import GA_TSP from typing import Dict @@ -73,10 +72,10 @@ def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValu if num_population % 2 != 0: num_population -= 1 - ga_tsp = GA_TSP(func=self.calc_total_distance, + ga_tsp = GA_TSP(func=lambda x: self.calc_total_distance(x), n_dim=self.n_dim, size_pop=num_population, max_iter=int(self.numberOfIterations), prob_mut=mutation_prob) best_points, best_distance = ga_tsp.run() function_value.value = best_distance[0] - print(best_distance[0]) + #print(best_distance[0]) return function_value diff --git a/examples/MCO_Grishagin_example.py b/examples/MCO_Grishagin_example.py new file mode 100644 index 00000000..7e4139bd --- /dev/null +++ b/examples/MCO_Grishagin_example.py @@ -0,0 +1,40 @@ +from problems.grishagin_mco import Grishagin_mco +from iOpt.solver import Solver +from iOpt.solver_parametrs import SolverParameters +from iOpt.output_system.listeners.console_outputers import ConsoleOutputListener +import matplotlib.pyplot as plt + +if __name__ == "__main__": + + problem = Grishagin_mco(2, [3, 2]) + + params = SolverParameters(r=2.5, eps=0.01, iters_limit=16000, + number_of_lambdas=50, start_lambdas=[[0, 1]], + is_scaling=False, number_of_parallel_points=2, + async_scheme=True) + + solver = Solver(problem=problem, parameters=params) + + cfol = ConsoleOutputListener(mode='full') + solver.add_listener(cfol) + + sol = solver.solve() + + # output of the Pareto set (coordinates - function values) + var = [trial.point.float_variables for trial in sol.best_trials] + val = [[trial.function_values[i].value for i in range(2)] for trial in sol.best_trials] + print("size pareto set: ", len(var)) + for fvar, fval in zip(var, val): + print(fvar, fval) + + x1 = [trial.point.float_variables[0] for trial in sol.best_trials] + x2 = [trial.point.float_variables[1] for trial in sol.best_trials] + + plt.plot(x1, x2, 'ro') + plt.show() + + fv1 = [trial.function_values[0].value for trial in sol.best_trials] + fv2 = [trial.function_values[1].value for trial in sol.best_trials] + + plt.plot(fv1, fv2, 'ro') + plt.show() diff --git a/examples/MCO_Test1_example.py b/examples/MCO_Test1_example.py new file mode 100644 index 00000000..586e821c --- /dev/null +++ b/examples/MCO_Test1_example.py @@ -0,0 +1,49 @@ +from problems.mco_test1 import mco_test1 +from iOpt.solver import Solver +from iOpt.solver_parametrs import SolverParameters + +from iOpt.output_system.listeners.console_outputers import ConsoleOutputListener +import matplotlib.pyplot as plt + +if __name__ == "__main__": + """ + Минимизация тестовой функции #1 многокритериальной оптимизации + """ + + # Создаем объект задачи + problem = mco_test1() + + # Формируем параметры решателя + params = SolverParameters(r=3.0, eps=0.01, iters_limit=16000, number_of_lambdas=50, + start_lambdas=[[0, 1]], is_scaling=False) + + # Создаем решатель + solver = Solver(problem=problem, parameters=params) + + # Добавляем вывод результатов в консоль + cfol = ConsoleOutputListener(mode='full') + solver.add_listener(cfol) + + # Решаем задачу + sol = solver.solve() + + # Выводим множество Парето + var = [trial.point.float_variables for trial in sol.best_trials] + val = [[trial.function_values[i].value for i in range(2)] for trial in sol.best_trials] + print("size pareto set: ", len(var)) + for fvar, fval in zip(var, val): + print(fvar, fval) + + # Точки для построения + # x1 = [trial.point.float_variables[0] for trial in sol.best_trials] + # x2 = [trial.point.float_variables[1] for trial in sol.best_trials] + + # plt.plot(x1, x2, 'ro') + # plt.show() + + # Точки для построения графика множества Парето y[0]-y[1] + fv1 = [trial.function_values[0].value for trial in sol.best_trials] + fv2 = [trial.function_values[1].value for trial in sol.best_trials] + + plt.plot(fv1, fv2, 'ro') + plt.show() diff --git a/examples/Machine_learning/SVC/_2D/MCO_breast_cancer_example.py b/examples/Machine_learning/SVC/_2D/MCO_breast_cancer_example.py new file mode 100644 index 00000000..8e551ca2 --- /dev/null +++ b/examples/Machine_learning/SVC/_2D/MCO_breast_cancer_example.py @@ -0,0 +1,73 @@ +from Problems.mco_breast_cancer import mco_breast_cancer + +from iOpt.solver import Solver +from iOpt.solver_parametrs import SolverParameters +from iOpt.output_system.listeners.console_outputers import ConsoleOutputListener +import matplotlib.pyplot as plt +from sklearn.datasets import load_breast_cancer +from sklearn.model_selection import train_test_split + +# Для построения HV индекса +#from pymoo.util.misc import stack +#from pymoo.indicators.hv import HV +#import numpy as np + +if __name__ == "__main__": + """ + Пробный пример многокритериальной оптимизации + """ + + # Загружаем датасет + X, y = load_breast_cancer(return_X_y=True) + + # Разбиваем датасет на тренировочную и проверочную части + X_train, X_valid, y_train, y_valid = train_test_split(X, y) + + # Создаем объект задачи + problem = mco_breast_cancer(X, y, X_train, y_train) + + # Формируем параметры решателя + params = SolverParameters(r=3.0, eps=0.01, iters_limit=200, number_of_lambdas=50, + start_lambdas=[[0, 1]], is_scaling=False) + + # Создаем решатель + solver = Solver(problem=problem, parameters=params) + + # Добавляем вывод результатов в консоль + cfol = ConsoleOutputListener(mode='full') + solver.add_listener(cfol) + + # Решаем задачу + sol = solver.solve() + + # Выводим множество Парето (координаты - значения функций) + var = [trial.point.float_variables for trial in sol.best_trials] + val = [[-trial.function_values[i].value for i in range(2)] for trial in sol.best_trials] + + print("size pareto set: ", len(var)) + for fvar, fval in zip(var, val): + print(fvar, fval) + + # Строим график множества Парето z[0]-z[1] + fv1 = [-trial.function_values[0].value for trial in sol.best_trials] + fv2 = [-trial.function_values[1].value for trial in sol.best_trials] + plt.plot(fv1, fv2, 'ro') + plt.show() + + ######################################################################## + ## Вычисляем HV индекс + ######################################################################## + + ## Вычисляем отраженное Парето множество + #data = 1-np.array(val) + #ref_point = np.array([1.0, 1.0]) + #print("reference point:") + #print(ref_point) + #print("Pareto set:") + #print(data) + + ## Создаем объект для подсчета HV индекса + #ind = HV(ref_point=ref_point) + + ## Считаем и выводим HV индекс + #print("HV", ind(data)) \ No newline at end of file diff --git a/examples/Machine_learning/SVC/_2D/Problems/mco_breast_cancer.py b/examples/Machine_learning/SVC/_2D/Problems/mco_breast_cancer.py new file mode 100644 index 00000000..37e02c07 --- /dev/null +++ b/examples/Machine_learning/SVC/_2D/Problems/mco_breast_cancer.py @@ -0,0 +1,67 @@ +import numpy as np + +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import Trial +from iOpt.problem import Problem + +from sklearn.model_selection import cross_val_score + +from sklearn.svm import SVC + + +class mco_breast_cancer(Problem): + + def __init__(self, X, y, X_train, y_train): + """ + Конструктор класса breast_cancer problem. + """ + + super(mco_breast_cancer, self).__init__() + + self.X = X + self.y = y + self.X_train = X_train + self.y_train = y_train + + self.name = "mco_test1" + self.dimension = 2 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.array([1, -7], dtype=np.double) + self.upper_bound_of_float_variables = np.array([6, -3], dtype=np.double) + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + svc_c = 10 ** x[0] + gamma = 10 ** x[1] + + classifier_obj = SVC(C=svc_c, gamma=gamma) + classifier_obj.fit(self.X_train, self.y_train) + + if function_value.functionID == 0: # OBJECTIV 1 + result = - cross_val_score(classifier_obj, self.X, self.y, n_jobs=4, scoring='precision').mean() + elif function_value.functionID == 1: # OBJECTIV 2 + result = - cross_val_score(classifier_obj, self.X, self.y, n_jobs=4, scoring='recall').mean() + + function_value.value = result + return function_value diff --git a/examples/grid_search_example.py b/examples/grid_search_example.py index 0fb80433..32f31a1d 100644 --- a/examples/grid_search_example.py +++ b/examples/grid_search_example.py @@ -40,7 +40,6 @@ cfol = ConsoleOutputListener(mode='full') solver2.add_listener(cfol) - solver2.load_progress(log) - solver2.release_all_listener() \ No newline at end of file + solver2.release_all_listener() diff --git a/iOpt/method/async_calculator.py b/iOpt/method/async_calculator.py index 12bc4890..b3ae97fe 100644 --- a/iOpt/method/async_calculator.py +++ b/iOpt/method/async_calculator.py @@ -50,6 +50,7 @@ def _take_calculated_point( self, block: bool ) -> tuple[SearchDataItem, SearchDataItem]: newpoint = self.done_queue.get(block=block) + self.evaluate_method.copy_functionals(newpoint, newpoint) oldpoint = self.waiting_oldpoints.pop(newpoint.get_x()) oldpoint.blocked = False return newpoint, oldpoint diff --git a/iOpt/method/async_parallel_process.py b/iOpt/method/async_parallel_process.py index aec72e98..2ba702d3 100644 --- a/iOpt/method/async_parallel_process.py +++ b/iOpt/method/async_parallel_process.py @@ -3,7 +3,6 @@ from iOpt.evolvent.evolvent import Evolvent from iOpt.method.async_calculator import AsyncCalculator -from iOpt.method.index_method_calculator import IndexMethodCalculator from iOpt.method.listener import Listener from iOpt.method.method import Method from iOpt.method.optim_task import OptimizationTask @@ -11,6 +10,7 @@ from iOpt.method.search_data import SearchData from iOpt.solution import Solution from iOpt.solver_parametrs import SolverParameters +from iOpt.method.calculator import Calculator class AsyncParallelProcess(Process): @@ -22,18 +22,20 @@ def __init__( search_data: SearchData, method: Method, listeners: list[Listener], + calculator: Calculator = None ): super(AsyncParallelProcess, self).__init__( - parameters, task, evolvent, search_data, method, listeners + parameters, task, evolvent, search_data, method, listeners, calculator ) - self.calculator = AsyncCalculator(IndexMethodCalculator(task), parameters) + from iOpt.method.solverFactory import SolverFactory + self.calculator = AsyncCalculator(SolverFactory.create_evaluate_method(task), parameters) def do_global_iteration(self, number: int = 1) -> None: done_trials = [] if self._first_iteration is True: for listener in self._listeners: listener.before_method_start(self.method) - done_trials = self.method.first_iteration(self.calculator) + done_trials = self.method.first_iteration() self._first_iteration = False number -= 1 diff --git a/iOpt/method/calculator.py b/iOpt/method/calculator.py index 7d339bb5..4a6a9d8a 100644 --- a/iOpt/method/calculator.py +++ b/iOpt/method/calculator.py @@ -3,6 +3,7 @@ import copy from pathos.multiprocessing import ProcessPool +from iOpt.method.default_calculator import DefaultCalculator from iOpt.method.icriterion_evaluate_method import ICriterionEvaluateMethod from iOpt.method.search_data import SearchDataItem from iOpt.solver_parametrs import SolverParameters @@ -13,7 +14,7 @@ sys.setrecursionlimit(10000) -class Calculator: +class Calculator(DefaultCalculator): evaluate_method: ICriterionEvaluateMethod = None def __init__(self, @@ -30,27 +31,25 @@ def __init__(self, self.parameters = parameters Calculator.worker_init(self.evaluate_method) self.pool = ProcessPool(parameters.number_of_parallel_points, - initializer=Calculator.worker_init, - initargs=(self.evaluate_method,)) - - r""" - Initialize the calculation method in each process from the process pool Calculator.Pool - - :param evaluate_method: a computational method that performs search trials according to specified rules. - """ + initializer=Calculator.worker_init, + initargs=(self.evaluate_method,)) @staticmethod def worker_init(evaluate_method: ICriterionEvaluateMethod): - Calculator.evaluate_method = evaluate_method - - r""" - Сalculation method in each process from the process pool Calculator.Pool + r""" + Initialize the calculation method in each process from the process pool Calculator.Pool - :param point: trial point. - """ + :param evaluate_method: a computational method that performs search trials according to specified rules. + """ + Calculator.evaluate_method = evaluate_method @staticmethod def worker(point: SearchDataItem) -> SearchDataItem: + r""" + Сalculation method in each process from the process pool Calculator.Pool + + :param point: trial point. + """ try: Calculator.evaluate_method.calculate_functionals(point) except Exception: @@ -58,18 +57,13 @@ def worker(point: SearchDataItem) -> SearchDataItem: point.set_index(-10) return point - r""" - Сalculation method for multiple points - - :param points: trial points. - """ - def calculate_functionals_for_items(self, points: list[SearchDataItem]) -> list[SearchDataItem]: - # пока оставленно на случай отладки - # for point in points: - # self.worker(point, self.method) + r""" + Сalculation method for multiple points + + :param points: trial points. + """ - # Ниже реализация цикла через пулл процессов points_copy = [] for point in points: sd = SearchDataItem(y=copy.deepcopy(point.point), x=copy.deepcopy(point.get_x()), diff --git a/iOpt/method/default_calculator.py b/iOpt/method/default_calculator.py new file mode 100644 index 00000000..9ba42051 --- /dev/null +++ b/iOpt/method/default_calculator.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from iOpt.method.icriterion_evaluate_method import ICriterionEvaluateMethod +from iOpt.method.search_data import SearchDataItem +from iOpt.solver_parametrs import SolverParameters + +import sys + + +class DefaultCalculator: + def __init__(self, + evaluate_method: ICriterionEvaluateMethod, + parameters: SolverParameters + ): + r""" + Конструктор класса Calculator + + :param evaluate_method: метод вычислений, проводящий поисковые испытания по заданным правилам. + :param parameters: параметры решения задачи оптимизации. + """ + self.evaluate_method = evaluate_method + self.parameters = parameters + + def calculate_functionals_for_items(self, points: list[SearchDataItem]) -> list[SearchDataItem]: + r""" + Метод проведения испытаний для множества точек + + :param points: точки проведения испытаний + """ + for point in points: + try: + self.evaluate_method.calculate_functionals(point) + except Exception: + point.set_z(sys.float_info.max) + point.set_index(-10) + + return points diff --git a/iOpt/method/grid_search_method.py b/iOpt/method/grid_search_method.py index 982ad963..8e2786fd 100644 --- a/iOpt/method/grid_search_method.py +++ b/iOpt/method/grid_search_method.py @@ -1,9 +1,5 @@ from __future__ import annotations -import copy -import math -import sys -from typing import Tuple import numpy as np from iOpt.evolvent.evolvent import Evolvent @@ -12,10 +8,6 @@ from iOpt.method.search_data import SearchDataItem from iOpt.solver_parametrs import SolverParameters from iOpt.method.method import Method -from iOpt.trial import FunctionValue, FunctionType -from iOpt.method.calculator import Calculator - -from iOpt.trial import Point, FunctionValue class GridSearchMethod(Method): diff --git a/iOpt/method/index_method.py b/iOpt/method/index_method.py index 34b35807..d7afd96f 100644 --- a/iOpt/method/index_method.py +++ b/iOpt/method/index_method.py @@ -1,17 +1,16 @@ from __future__ import annotations import math -import sys import numpy as np from iOpt.evolvent.evolvent import Evolvent +from iOpt.method.calculator import Calculator from iOpt.method.optim_task import OptimizationTask from iOpt.method.search_data import SearchData from iOpt.method.search_data import SearchDataItem from iOpt.solver_parametrs import SolverParameters from iOpt.method.method import Method -from iOpt.trial import FunctionValue, FunctionType class IndexMethod(Method): @@ -23,36 +22,10 @@ def __init__(self, parameters: SolverParameters, task: OptimizationTask, evolvent: Evolvent, - search_data: SearchData + search_data: SearchData, + calculator: Calculator = None ): - super(IndexMethod, self).__init__(parameters, task, evolvent, search_data) - - def calculate_functionals(self, point: SearchDataItem) -> SearchDataItem: - r""" - Perform a search trial at a given point - - :param point: the point at which the trial is to be performed. - - :return: the point at which the trial results are saved. - """ - try: - number_of_constraints = self.task.problem.number_of_constraints - for i in range(number_of_constraints): - point.function_values[i] = FunctionValue(FunctionType.CONSTRAINT, i) # ??? - point = self.task.calculate(point, i) - point.set_z(point.function_values[i].value) - point.set_index(i) - if point.get_z() > 0: - return point - point.function_values[number_of_constraints] = FunctionValue(FunctionType.OBJECTIV, number_of_constraints) - point = self.task.calculate(point, number_of_constraints) - point.set_z(point.function_values[number_of_constraints].value) - point.set_index(number_of_constraints) - except Exception: - point.set_z(sys.float_info.max) - point.set_index(-10) - - return point + super(IndexMethod, self).__init__(parameters, task, evolvent, search_data, calculator) def calculate_m(self, curr_point: SearchDataItem, left_point: SearchDataItem) -> None: r""" diff --git a/iOpt/method/index_method_calculator.py b/iOpt/method/index_method_evaluate.py similarity index 56% rename from iOpt/method/index_method_calculator.py rename to iOpt/method/index_method_evaluate.py index 0703d0c3..86a4bcb6 100644 --- a/iOpt/method/index_method_calculator.py +++ b/iOpt/method/index_method_evaluate.py @@ -1,4 +1,5 @@ import copy +import sys from iOpt.method.icriterion_evaluate_method import ICriterionEvaluateMethod from iOpt.method.optim_task import OptimizationTask @@ -6,7 +7,7 @@ from iOpt.trial import FunctionValue, FunctionType -class IndexMethodCalculator(ICriterionEvaluateMethod): +class IndexMethodEvaluate(ICriterionEvaluateMethod): """ The Method class contains an implementation of the Global Search Algorithm """ @@ -24,18 +25,23 @@ def calculate_functionals(self, point: SearchDataItem) -> SearchDataItem: :return: the point at which the trial results are saved. """ - number_of_constraints = self.task.problem.number_of_constraints - for i in range(number_of_constraints): - point.function_values[i] = FunctionValue(FunctionType.CONSTRAINT, i) - point = self.task.calculate(point, i) - point.set_z(point.function_values[i].value) - point.set_index(i) - if point.get_z() > 0: - return point - point.function_values[number_of_constraints] = FunctionValue(FunctionType.OBJECTIV, 0) - point = self.task.calculate(point, number_of_constraints) - point.set_z(point.function_values[number_of_constraints].value) - point.set_index(number_of_constraints) + try: + number_of_constraints = self.task.problem.number_of_constraints + for i in range(number_of_constraints): + point.function_values[i] = FunctionValue(FunctionType.CONSTRAINT, i) + point = self.task.calculate(point, i) + point.set_z(point.function_values[i].value) + point.set_index(i) + if point.get_z() > 0: + return point + point.function_values[number_of_constraints] = FunctionValue(FunctionType.OBJECTIV, 0) + point = self.task.calculate(point, number_of_constraints) + point.set_z(point.function_values[number_of_constraints].value) + point.set_index(number_of_constraints) + except Exception: + point.set_z(sys.float_info.max) + point.set_index(-10) + return point def copy_functionals(self, dist_point: SearchDataItem, src_point: SearchDataItem): diff --git a/iOpt/method/listener.py b/iOpt/method/listener.py index 989b9c31..2cb3e7a2 100644 --- a/iOpt/method/listener.py +++ b/iOpt/method/listener.py @@ -3,6 +3,7 @@ from iOpt.method.method import Method import numpy as np + class Listener: """ Event listener base class @@ -11,7 +12,7 @@ class Listener: def before_method_start(self, method: Method): pass - def on_end_iteration(self, curr_points : np.ndarray(shape=(1), dtype=SearchDataItem), solution: Solution): + def on_end_iteration(self, curr_points: np.ndarray(shape=(1), dtype=SearchDataItem), solution: Solution): pass def on_method_stop(self, search_data: SearchData, solution: Solution, status: bool): diff --git a/iOpt/method/mco_method.py b/iOpt/method/mco_method.py new file mode 100644 index 00000000..8ee9d0ed --- /dev/null +++ b/iOpt/method/mco_method.py @@ -0,0 +1,223 @@ +from typing import Tuple + +import numpy as np + +from enum import Enum +from iOpt.evolvent.evolvent import Evolvent +from iOpt.method.calculator import Calculator +from iOpt.method.mixed_integer_method import MixedIntegerMethod +from iOpt.method.mco_optim_task import MCOOptimizationTask +from iOpt.method.search_data import SearchDataItem, SearchData +from iOpt.solver_parametrs import SolverParameters +from iOpt.trial import FunctionValue, FunctionType, Trial +from iOpt.method.optim_task import TypeOfCalculation + + +class TypeOfParetoRelation(Enum): + DOMINANT = 1 + NONCOMPARABLE = 0 + NONDOMINATED = -1 + + +class MCOMethod(MixedIntegerMethod): + """ + The MCOMethod class contains an implementation of the Global Search Algorithm for multi-criteria problems + """ + + def __init__(self, + parameters: SolverParameters, + task: MCOOptimizationTask, + evolvent: Evolvent, + search_data: SearchData, + calculator: Calculator): + super().__init__(parameters, task, evolvent, search_data, calculator) + self.is_recalc_all_convolution = True + self.max_iter_for_convolution = 0 + + def set_max_iter_for_convolution(self, max_iter_for_convolution) -> None: + self.max_iter_for_convolution = max_iter_for_convolution + + def set_min_delta(self, min_delta) -> None: + self.min_delta = min_delta + self.is_recalc_all_convolution = True + + def recalc_all_convolution(self) -> None: + if self.is_recalc_all_convolution is not True: + return + + for item in self.search_data: + self.task.calculate(item, -1, TypeOfCalculation.CONVOLUTION) + + if self.best: + self.task.calculate(self.best, -1, TypeOfCalculation.CONVOLUTION) + for item in self.search_data: + if self.best.get_z() > item.get_z() > 0 and item.get_index() >= self.best.get_index(): + self.best = item + + self.is_recalc_all_convolution = False + + self.recalcR = True + self.recalcM = True + + if self.best: + self.Z[self.task.problem.number_of_constraints] = self.best.get_z() + + def calculate_iteration_point(self) -> Tuple[SearchDataItem, SearchDataItem]: # return (new, old) + if self.is_recalc_all_convolution is True: + self.recalc_all_convolution() + + return super(MCOMethod, self).calculate_iteration_point() + + def update_optimum(self, point: SearchDataItem) -> None: + r""" + Updates the estimate of the optimum. + + :param point: new trial point. + """ + if self.best is None or self.best.get_index() < point.get_index() or ( + self.best.get_index() == point.get_index() and point.get_z() < self.best.get_z()): + self.best = point + self.recalcR = True + self.Z[point.get_index()] = point.get_z() + + if not self.search_data.solution.best_trials[0].point: + self.search_data.solution.best_trials[0] = self.best + + if point.get_index() == self.task.problem.number_of_constraints: + self.update_min_max_value(point) + self.pareto_set_update(point) + + def pareto_set_update(self, point: SearchDataItem) -> None: + if self.search_data.get_count() == 0: + return + + pareto_set: np.ndarray(shape=(1), dtype=Trial) = [] + new_point = point.function_values + add_point = False + + for trial in self.search_data.solution.best_trials: + old_point = trial.function_values + relation = self.type_of_pareto_relation(new_point, old_point) + if relation == TypeOfParetoRelation.NONCOMPARABLE: + add_point = True + pareto_set = np.append(pareto_set, trial) + elif relation == TypeOfParetoRelation.DOMINANT: + add_point = True + elif relation == TypeOfParetoRelation.NONDOMINATED: + add_point = False + break + if add_point: + pareto_set = np.append(pareto_set, Trial(point.point, point.function_values)) + self.search_data.solution.best_trials = pareto_set + # if we don't add a point, then the pareto set doesn't change. + + def type_of_pareto_relation(self, p1: np.ndarray(shape=(1), dtype=FunctionValue), + p2: np.ndarray(shape=(1), dtype=FunctionValue)) -> TypeOfParetoRelation: + count_dom = 0 + count_equal = 0 + number_of_objectives = self.task.problem.number_of_objectives + for i in range(number_of_objectives): + if p1[i].value < p2[i].value: + count_dom += 1 + elif p1[i].value == p2[i].value: + count_equal += 1 + if count_dom == 0: + return TypeOfParetoRelation.NONDOMINATED + elif (count_dom + count_equal) == number_of_objectives: + return TypeOfParetoRelation.DOMINANT + else: + return TypeOfParetoRelation.NONCOMPARABLE + + def update_min_max_value(self, + data_item: SearchDataItem): + # If the minimum and maximum values have not yet been changed after initialization + if self.task.min_value[0] == self.task.max_value[0] and self.task.min_value[0] == 0: + # if the search information has been uploaded + if self.search_data.get_count() > 0: + self.task.min_value = [fv.value for fv in self.search_data.get_last_item().function_values] + self.task.max_value = [fv.value for fv in self.search_data.get_last_item().function_values] + for trial in self.search_data: + for i in range(0, self.task.problem.number_of_objectives): + if self.task.min_value[i] > trial.function_values[i].value: + self.task.min_value[i] = trial.function_values[i].value + self.is_recalc_all_convolution = True + if self.task.max_value[i] < trial.function_values[i].value: + self.task.max_value[i] = trial.function_values[i].value + self.is_recalc_all_convolution = True + else: + # assign the values of the first calculated item + self.task.min_value = [fv.value for fv in data_item.function_values] + self.task.max_value = [fv.value for fv in data_item.function_values] + else: + # comparing the value of the current min max with the values of the new point + for i in range(0, self.task.problem.number_of_objectives): + if self.task.min_value[i] > data_item.function_values[i].value: + self.task.min_value[i] = data_item.function_values[i].value + self.is_recalc_all_convolution = True + if self.task.max_value[i] < data_item.function_values[i].value: + self.task.max_value[i] = data_item.function_values[i].value + self.is_recalc_all_convolution = True + + def check_stop_condition(self) -> bool: + r""" + Checking the stopping condition. + The algorithm must terminate when the eps accuracy is reached or the iteration limit is exceeded. + + :return: True if the stopping criterion is met; False - otherwise. + """ + if self.min_delta < self.parameters.eps or self.iterations_count >= self.max_iter_for_convolution: + self.stop = True + else: + self.stop = False + + return self.stop + + def calculate_m(self, curr_point: SearchDataItem, left_point: SearchDataItem) -> None: + r""" + Compute the estimate of the Holder constant between curr_point and left_point. + + :param curr_point: right point of the interval + :param left_point: left point of the interval + """ + if curr_point is None: + print("CalculateM: curr_point is None") + raise RuntimeError("CalculateM: curr_point is None") + if left_point is None: + return + index = curr_point.get_index() + if index < 0: + return + m = 0.0 + if left_point.get_index() == index: + m = abs(left_point.get_z() - curr_point.get_z()) / curr_point.delta + else: + other_point = left_point + while (other_point is not None) and (other_point.get_index() < curr_point.get_index()): + if other_point.get_discrete_value_index() == curr_point.get_discrete_value_index(): + other_point = other_point.get_left() + else: + other_point = None + break + if other_point is not None and other_point.get_index() >= 0 \ + and other_point.get_discrete_value_index() == curr_point.get_discrete_value_index(): + m = abs(other_point.function_values[index].value - curr_point.get_z()) / \ + self.calculate_delta(other_point, curr_point, self.dimension) + + other_point = left_point.get_right() + if other_point is not None and other_point is curr_point: + other_point = other_point.get_right() + while (other_point is not None) and (other_point.get_index() < curr_point.get_index()): + if other_point.get_discrete_value_index() == curr_point.get_discrete_value_index(): + other_point = other_point.get_right() + else: + other_point = None + break + + if other_point is not None and other_point.get_index() >= 0 \ + and other_point.get_discrete_value_index() == curr_point.get_discrete_value_index(): + m = max(m, abs(curr_point.get_z() - other_point.get_z()) / \ + self.calculate_delta(curr_point, other_point, self.dimension)) + + if m > self.M[index] or (self.M[index] == 1.0 and m > 1e-12): + self.M[index] = m + self.recalcR = True diff --git a/iOpt/method/mco_method_evaluate.py b/iOpt/method/mco_method_evaluate.py new file mode 100644 index 00000000..d3730e3e --- /dev/null +++ b/iOpt/method/mco_method_evaluate.py @@ -0,0 +1,71 @@ +import copy +import sys + +from iOpt.method.index_method_evaluate import IndexMethodEvaluate +from iOpt.method.optim_task import OptimizationTask +from iOpt.method.search_data import SearchDataItem +from iOpt.trial import FunctionValue, FunctionType +from iOpt.method.optim_task import TypeOfCalculation + + +class MCOMethodEvaluate(IndexMethodEvaluate): + """ + The MCOMethodEvaluate class contains an implementation of the method for evaluate + the criterion value of the Global Search Algorithm + """ + + def __init__(self, task: OptimizationTask): + super().__init__(task) + + def calculate_functionals(self, point: SearchDataItem) -> SearchDataItem: + + try: + number_of_constraints = self.task.problem.number_of_constraints + for i in range(number_of_constraints): + point.function_values[i] = FunctionValue(FunctionType.CONSTRAINT, i) + point = self.task.calculate(point, i) + point.set_z(point.function_values[i].value) + point.set_index(i) + if point.get_z() > 0: + return point + + for i in range(self.task.problem.number_of_objectives): + point.function_values[number_of_constraints + i] = FunctionValue(FunctionType.OBJECTIV, i) + point = self.task.calculate(point, number_of_constraints + i) + + point = self.task.calculate(point, -1, TypeOfCalculation.CONVOLUTION) + point.set_index(number_of_constraints) + + except Exception: + point.set_z(sys.float_info.max) + point.set_index(-10) + + return point + + def copy_functionals(self, dist_point: SearchDataItem, src_point: SearchDataItem): + r""" + Copy the search trial + + :param dist_point: point to which the trial values are copied. + :param src_point: point with trial results. + """ + + dist_point.function_values = copy.deepcopy(src_point.function_values) + dist_point.set_index(src_point.get_index()) + self.update_min_max_value(src_point) + if dist_point.get_index() == self.task.problem.number_of_constraints: + dist_point = self.task.calculate(dist_point, -1, TypeOfCalculation.CONVOLUTION) + + def update_min_max_value(self, + data_item: SearchDataItem): + # If the minimum and maximum values have not yet been changed after initialization + if self.task.min_value[0] == self.task.max_value[0] and self.task.min_value[0] == 0: + self.task.min_value = [fv.value for fv in data_item.function_values] + self.task.max_value = [fv.value for fv in data_item.function_values] + else: + # comparing the value of the current min max with the values of the new point + for i in range(0, self.task.problem.number_of_objectives): + if self.task.min_value[i] > data_item.function_values[i].value: + self.task.min_value[i] = data_item.function_values[i].value + if self.task.max_value[i] < data_item.function_values[i].value: + self.task.max_value[i] = data_item.function_values[i].value diff --git a/iOpt/method/mco_method_many_lambdas.py b/iOpt/method/mco_method_many_lambdas.py new file mode 100644 index 00000000..9431035b --- /dev/null +++ b/iOpt/method/mco_method_many_lambdas.py @@ -0,0 +1,111 @@ +from iOpt.evolvent.evolvent import Evolvent +from iOpt.method.calculator import Calculator +from iOpt.method.mco_method import MCOMethod +from iOpt.method.mco_optim_task import MCOOptimizationTask +from iOpt.method.search_data import SearchData +from iOpt.solver_parametrs import SolverParameters + + +class MCOMethodManyLambdas(MCOMethod): + """ + The MCOMethodManyLambdas class contains an implementation of + the Global Search Algorithm in the case of multiple convolutions + """ + + def __init__(self, + parameters: SolverParameters, + task: MCOOptimizationTask, + evolvent: Evolvent, + search_data: SearchData, + calculator: Calculator + ): + super().__init__(parameters, task, evolvent, search_data, calculator) + self.current_lambdas = None + self.is_recalc_all_convolution = True + self.max_iter_for_convolution = 0 + self.number_of_lambdas = parameters.number_of_lambdas + + if parameters.start_lambdas: + self.start_lambdas = parameters.start_lambdas + else: + self.start_lambdas = [] + + self.current_num_lambda = 0 + self.lambdas_list = [] + self.iterations_list = [] + + self.convolution = task.convolution + + self.init_lambdas() + + def check_stop_condition(self) -> bool: + if super().check_stop_condition(): + if self.current_num_lambda < self.number_of_lambdas: + self.change_lambdas() + return super().check_stop_condition() + + def change_lambdas(self) -> None: + self.set_min_delta(1) + self.current_num_lambda += 1 + if self.current_num_lambda < self.number_of_lambdas: + self.current_lambdas = self.lambdas_list[self.current_num_lambda] + self.task.convolution.lambda_param = self.current_lambdas + + self.iterations_list.append(self.iterations_count) + max_iter_for_convolution = int((self.parameters.global_method_iteration_count / + self.number_of_lambdas) * (self.current_num_lambda + 1)) + self.set_max_iter_for_convolution(max_iter_for_convolution) + + def init_lambdas(self) -> None: + if self.task.problem.number_of_objectives == 2: + if self.number_of_lambdas > 1: + h = 1.0 / (self.number_of_lambdas - 1) + else: + h = 1 + if not self.start_lambdas: + for i in range(self.number_of_lambdas): + lambda_0 = i * h + if lambda_0 > 1: + lambda_0 = lambda_0 - 1 + lambda_1 = 1 - lambda_0 + lambdas = [lambda_0, lambda_1] + self.lambdas_list.append(lambdas) + elif len(self.start_lambdas) == self.number_of_lambdas: + for i in range(self.number_of_lambdas): + self.lambdas_list.append(self.start_lambdas[i]) + elif len(self.start_lambdas) == 1: + self.lambdas_list.append(self.start_lambdas[0]) + for i in range(1, self.number_of_lambdas): + lambda_0 = self.start_lambdas[0][0] + i * h + if lambda_0 > 1: + lambda_0 = lambda_0 - 1 + lambda_1 = 1 - lambda_0 + lambdas = [lambda_0, lambda_1] + self.lambdas_list.append(lambdas) + else: # многомерный случай + if len(self.start_lambdas) == self.number_of_lambdas: + for i in range(self.number_of_lambdas): + self.lambdas_list.append(self.start_lambdas[i]) + else: + if self.number_of_lambdas > 1: + h = 1.0 / (self.number_of_lambdas - 1) + else: + h = 1 + evolvent = Evolvent([0] * self.task.problem.number_of_objectives, + [1] * self.task.problem.number_of_objectives, + self.task.problem.number_of_objectives) + + for i in range(self.number_of_lambdas): + x = i * h + y = evolvent.get_image(x) + sum = 0 + for i in range(self.task.problem.number_of_objectives): + sum += y[i] + for i in range(self.task.problem.number_of_objectives): + y[i] = y[i] / sum + lambdas = list(y) + self.lambdas_list.append(lambdas) + + self.current_lambdas = self.lambdas_list[0] + self.max_iter_for_convolution = \ + int(self.parameters.global_method_iteration_count / self.number_of_lambdas) diff --git a/iOpt/method/mco_optim_task.py b/iOpt/method/mco_optim_task.py new file mode 100644 index 00000000..cd035051 --- /dev/null +++ b/iOpt/method/mco_optim_task.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +import numpy as np +import copy + +from iOpt.method.optim_task import OptimizationTask, TypeOfCalculation +from iOpt.method.search_data import SearchDataItem +from iOpt.problem import Problem + + +class Convolution(ABC): + """ + The Convolution class is the base class for various convolutions. + It is expected that a separate convolution object will be spawned for each set of lambdas. + It is also possible that the convolution is changed by a reference passed through the class constructor. + """ + + def __init__(self, + problem: Problem, + lambda_param: np.ndarray(shape=(1), dtype=np.double) + ): + self.problem = problem + self.lambda_param = lambda_param + + @abstractmethod + def calculate_convolution(self, + data_item: SearchDataItem, + min_value: np.ndarray(shape=(1), dtype=np.double) = [], + max_value: np.ndarray(shape=(1), dtype=np.double) = [] + ) -> SearchDataItem: + pass + + +class MinMaxConvolution(Convolution): + """ + minimax convolution + """ + + def __init__(self, + problem: Problem, + lambda_param: np.ndarray(shape=(1), dtype=np.double), + is_scaling: False + ): + self.is_scaling = is_scaling + super().__init__(problem, lambda_param) + + def calculate_convolution(self, + data_item: SearchDataItem, + min_value: np.ndarray(shape=(1), dtype=np.double) = [], + max_value: np.ndarray(shape=(1), dtype=np.double) = [] + ) -> SearchDataItem: + + value = -10 + for i in range(0, self.problem.number_of_objectives): + dx = 1 + if self.is_scaling: + dx = np.double(max_value[i] - min_value[i]) + if dx < 1e-6: + dx = 1 + + f_value = (data_item.function_values[i].value - min_value[i]) / dx + value = max(value, f_value * self.lambda_param[i]) + + data_item.set_z(value) + return data_item + + +class MCOOptimizationTask(OptimizationTask): + def __init__(self, + problem: Problem, + convolution: Convolution, + perm: np.ndarray(shape=(1), dtype=int) = None + ): + super().__init__(problem, perm) + self.convolution = convolution + self.min_value = np.ndarray(shape=(problem.number_of_objectives,), dtype=np.double) + self.min_value.fill(0) + self.max_value = np.ndarray(shape=(problem.number_of_objectives,), dtype=np.double) + self.max_value.fill(0) + if self.problem.known_optimum: + self.min_value = copy.deepcopy(self.problem.known_optimum[0].function_values) + for know_optimum in self.problem.known_optimum: + for i in range(0, self.problem.number_of_objectives): + if self.min_value[i] > know_optimum.function_values[i]: + self.min_value[i] = know_optimum.function_values[i] + + def calculate(self, + data_item: SearchDataItem, + function_index: int, + calculation_type: TypeOfCalculation = TypeOfCalculation.FUNCTION + ) -> SearchDataItem: + """Compute selected function by number.""" + if calculation_type == TypeOfCalculation.FUNCTION: + data_item.function_values[self.perm[function_index]] = \ + self.problem.calculate(data_item.point, data_item.function_values[self.perm[function_index]]) + if not np.isfinite(data_item.function_values[self.perm[function_index]].value): + raise Exception("Infinity values") + + elif calculation_type == TypeOfCalculation.CONVOLUTION: + data_item = self.convolution.calculate_convolution(data_item, self.min_value, self.max_value) + + return data_item diff --git a/iOpt/method/method.py b/iOpt/method/method.py index d977fb42..1aad5ca0 100644 --- a/iOpt/method/method.py +++ b/iOpt/method/method.py @@ -10,6 +10,8 @@ from iOpt.evolvent.evolvent import Evolvent from iOpt.method.calculator import Calculator +from iOpt.method.default_calculator import DefaultCalculator +from iOpt.method.index_method_evaluate import IndexMethodEvaluate from iOpt.method.optim_task import OptimizationTask from iOpt.method.search_data import SearchData from iOpt.method.search_data import SearchDataItem @@ -26,7 +28,8 @@ def __init__(self, parameters: SolverParameters, task: OptimizationTask, evolvent: Evolvent, - search_data: SearchData + search_data: SearchData, + calculator: Calculator = None ): r""" Method class constructor @@ -35,7 +38,9 @@ def __init__(self, :param task: problem wrapper. :param evolvent: Peano-Hilbert evolvent mapping the segment [0,1] to the multidimensional region D. :param search_data: data structure for storing accumulated search information. + :param calculator: class containing trial methods (parallel and/or inductive circuit) """ + self.stop: bool = False self.recalcR: bool = True self.recalcM: bool = True @@ -47,12 +52,17 @@ def __init__(self, self.evolvent = evolvent self.search_data = search_data - self.M = [1.0 for _ in range(task.problem.number_of_objectives + task.problem.number_of_constraints)] - self.Z = [np.infty for _ in range(task.problem.number_of_objectives + task.problem.number_of_constraints)] + self.M = [1.0 for _ in range(1 + task.problem.number_of_constraints)] + self.Z = [np.infty for _ in range(1 + task.problem.number_of_constraints)] self.dimension = task.problem.number_of_float_variables self.search_data.solution.solution_accuracy = np.infty self.numberOfAllFunctions = task.problem.number_of_objectives + task.problem.number_of_constraints + if calculator is None: + self.calculator = DefaultCalculator(IndexMethodEvaluate(self.task), parameters=self.parameters) + else: + self.calculator = calculator + @property def min_delta(self): return self.search_data.solution.solution_accuracy @@ -74,7 +84,7 @@ def calculate_delta(self, l_point: SearchDataItem, r_point: SearchDataItem, dime """ return pow(r_point.get_x() - l_point.get_x(), 1.0 / dimension) - def first_iteration(self, calculator: Calculator = None) -> list[SearchDataItem]: + def first_iteration(self) -> list[SearchDataItem]: r""" Perform the first iteration of the Global Search Algorithm """ @@ -126,12 +136,7 @@ def first_iteration(self, calculator: Calculator = None) -> list[SearchDataItem] function_values=[FunctionValue()] * self.numberOfAllFunctions) items.append(item) - if calculator is None: - for item in items: - self.calculate_functionals(item) - self.update_optimum(item) - else: - calculator.calculate_functionals_for_items(items) + self.calculator.calculate_functionals_for_items(items) for item in items: self.update_optimum(item) @@ -267,9 +272,7 @@ def calculate_functionals(self, point: SearchDataItem) -> SearchDataItem: :return: the point at which the trial results are saved. """ try: - point = self.task.calculate(point, 0) - point.set_z(point.function_values[0].value) - point.set_index(0) + self.calculator.calculate_functionals_for_items([point]) except Exception: point.set_z(sys.float_info.max) point.set_index(-10) @@ -368,7 +371,7 @@ def finalize_iteration(self) -> None: End the iteration, updates the iteration counter """ self.search_data.get_last_item().creation_time = time() - self.search_data.get_last_item().iterationNumber = self.iterations_count #будет ли работать в параллельном случае? + self.search_data.get_last_item().iterationNumber = self.iterations_count # будет ли работать в параллельном случае? self.iterations_count += 1 def get_iterations_count(self) -> int: diff --git a/iOpt/method/mixed_integer_method.py b/iOpt/method/mixed_integer_method.py index 2307955c..7b2d1f2a 100644 --- a/iOpt/method/mixed_integer_method.py +++ b/iOpt/method/mixed_integer_method.py @@ -29,9 +29,10 @@ def __init__(self, parameters: SolverParameters, task: OptimizationTask, evolvent: Evolvent, - search_data: SearchData + search_data: SearchData, + calculator: Calculator = None ): - super(MixedIntegerMethod, self).__init__(parameters, task, evolvent, search_data) + super(MixedIntegerMethod, self).__init__(parameters, task, evolvent, search_data, calculator) # u = {i, j, k}, i = {0, 1, 2}, j = {0, 1}, k = {0, 1, 2, 3, 4} -> 3*2*4=24 @@ -41,7 +42,7 @@ def __init__(self, self.numberOfParameterCombinations = len(self.discreteParameters) # 0 0.5 1 1.5 2 2.5 3 3.5 4 - def first_iteration(self, calculator: Calculator = None) -> list[SearchDataItem]: + def first_iteration(self) -> list[SearchDataItem]: r""" The method performs the first iteration of the Global Search Algorithm """ @@ -135,12 +136,7 @@ def first_iteration(self, calculator: Calculator = None) -> list[SearchDataItem] if not is_init_image_x: is_init_image_x = True - if calculator is None: - for item in items: - self.calculate_functionals(item) - self.update_optimum(item) - else: - calculator.calculate_functionals_for_items(items) + self.calculator.calculate_functionals_for_items(items) for item in items: self.update_optimum(item) diff --git a/iOpt/method/parallel_process.py b/iOpt/method/parallel_process.py index 28b9f762..14ec0433 100644 --- a/iOpt/method/parallel_process.py +++ b/iOpt/method/parallel_process.py @@ -4,7 +4,7 @@ from iOpt.method.calculator import Calculator from iOpt.method.listener import Listener from iOpt.method.method import Method -from iOpt.method.index_method_calculator import IndexMethodCalculator + from iOpt.method.optim_task import OptimizationTask from iOpt.method.process import Process from iOpt.method.search_data import SearchData, SearchDataItem @@ -22,7 +22,8 @@ def __init__(self, evolvent: Evolvent, search_data: SearchData, method: Method, - listeners: List[Listener] + listeners: List[Listener], + calculator: Calculator = None ): """ Constructor of the ParallelProcess class @@ -34,10 +35,7 @@ def __init__(self, :param method: An optimization method that performs search trials according to given rules. :param listeners: List of "observers" (used to display current information). """ - super(ParallelProcess, self).__init__(parameters, task, evolvent, search_data, method, listeners) - - self.index_method_calculator = IndexMethodCalculator(task) - self.calculator = Calculator(self.index_method_calculator, parameters) + super(ParallelProcess, self).__init__(parameters, task, evolvent, search_data, method, listeners, calculator) def do_global_iteration(self, number: int = 1): """ @@ -50,7 +48,7 @@ def do_global_iteration(self, number: int = 1): if self._first_iteration is True: for listener in self._listeners: listener.before_method_start(self.method) - done_trials = self.method.first_iteration(self.calculator) + done_trials = self.method.first_iteration() self._first_iteration = False number -= 1 diff --git a/iOpt/method/process.py b/iOpt/method/process.py index a7492022..be8ffec5 100644 --- a/iOpt/method/process.py +++ b/iOpt/method/process.py @@ -1,4 +1,3 @@ -import sys from datetime import datetime from typing import List @@ -6,6 +5,7 @@ import json from iOpt.evolvent.evolvent import Evolvent +from iOpt.method.calculator import Calculator from iOpt.method.listener import Listener from iOpt.method.local_optimizer import local_optimize from iOpt.method.method import Method @@ -14,7 +14,6 @@ from iOpt.solution import Solution from iOpt.solver_parametrs import SolverParameters from iOpt.trial import FunctionValue, FunctionType -from iOpt.trial import Point class Process: @@ -28,7 +27,8 @@ def __init__(self, evolvent: Evolvent, search_data: SearchData, method: Method, - listeners: List[Listener] + listeners: List[Listener], + calculator: Calculator = None ): """ Constructor of the Process class @@ -39,6 +39,7 @@ def __init__(self, :param search_data: A data structure for storing accumulated search information. :param method: An optimization method that performs search trials according to given rules. :param listeners: List of "observers" (used to display current information). + :param calculator: class containing trial methods (parallel and/or inductive circuit) """ self.parameters = parameters self.task = task @@ -47,6 +48,10 @@ def __init__(self, self.method = method self._listeners = listeners self._first_iteration = True + if calculator is None: + self.calculator = method.calculator + else: + self.calculator = calculator def solve(self) -> Solution: """ @@ -170,26 +175,27 @@ def get_results(self) -> Solution: """ return self.search_data.solution - def save_progress(self, file_name: str, mode = 'full') -> None: + def save_progress(self, file_name: str, mode='full') -> None: """ Save the optimization process from a file + :param mode: 'full' - save all optimization information :param file_name: file name. """ data = self.search_data.searchdata_to_json(mode=mode) data['Parameters'] = [] data['Parameters'].append({ - 'eps': self.parameters.eps, - 'r': self.parameters.r, - 'iters_limit': self.parameters.iters_limit, - 'start_point': self.parameters.start_point, - 'number_of_parallel_points': self.parameters.number_of_parallel_points + 'eps': self.parameters.eps, + 'r': self.parameters.r, + 'iters_limit': self.parameters.iters_limit, + 'start_point': self.parameters.start_point, + 'number_of_parallel_points': self.parameters.number_of_parallel_points }) with open(file_name, 'w') as f: json.dump(data, f, indent='\t', separators=(',', ':')) f.write('\n') - def load_progress(self, file_name: str, mode = 'full') -> None: + def load_progress(self, file_name: str, mode='full') -> None: """ Load the optimization process from a file diff --git a/iOpt/method/search_data.py b/iOpt/method/search_data.py index a689d884..f9b2e2c1 100644 --- a/iOpt/method/search_data.py +++ b/iOpt/method/search_data.py @@ -361,6 +361,7 @@ def searchdata_to_json(self, mode ='full') -> json: #что именно воз """ Save the optimization process to a file + :param mode: 'full' - save all optimization information :param file_name: file name. """ data = {} diff --git a/iOpt/method/solverFactory.py b/iOpt/method/solverFactory.py index 1b86d02c..5167e00d 100644 --- a/iOpt/method/solverFactory.py +++ b/iOpt/method/solverFactory.py @@ -2,11 +2,19 @@ from iOpt.evolvent.evolvent import Evolvent from iOpt.method.async_parallel_process import AsyncParallelProcess + +from iOpt.method.calculator import Calculator +from iOpt.method.default_calculator import DefaultCalculator from iOpt.method.index_method import IndexMethod +from iOpt.method.index_method_evaluate import IndexMethodEvaluate from iOpt.method.listener import Listener +from iOpt.method.mco_method_many_lambdas import MCOMethodManyLambdas from iOpt.method.method import Method from iOpt.method.mixed_integer_method import MixedIntegerMethod +from iOpt.method.mco_method_evaluate import MCOMethodEvaluate from iOpt.method.optim_task import OptimizationTask +from iOpt.method.mco_optim_task import MCOOptimizationTask, MinMaxConvolution +from iOpt.problem import Problem from iOpt.method.parallel_process import ParallelProcess from iOpt.method.process import Process from iOpt.method.search_data import SearchData @@ -21,11 +29,51 @@ class SolverFactory: def __init__(self): pass + @staticmethod + def create_task(problem: Problem, + parameters: SolverParameters) -> OptimizationTask: + """ + Создает подходящий класс метода решения по заданным параметрам + + :param parameters: параметры решения задачи оптимизации. + :param task: обёртка решаемой задачи. + :param evolvent: развертка Пеано-Гильберта, отображающая отрезок [0,1] на многомерную область D. + :param search_data: структура данных для хранения накопленной поисковой информации. + + :return: созданный метод + """ + if problem.number_of_objectives > 1: + if parameters.start_lambdas: + convolution = MinMaxConvolution(problem, parameters.start_lambdas[0], parameters.is_scaling) + else: + convolution = MinMaxConvolution(problem, [1.0 / problem.number_of_objectives] * problem.number_of_objectives, parameters.is_scaling) + return MCOOptimizationTask(problem, convolution) + else: + return OptimizationTask(problem) + + + @staticmethod + def create_evaluate_method(task: OptimizationTask): + if task.problem.number_of_objectives > 1: + return MCOMethodEvaluate(task) + else: + return IndexMethodEvaluate(task) + + @staticmethod + def create_calculator(task: OptimizationTask, + parameters: SolverParameters): + index_method_evaluate = SolverFactory.create_evaluate_method(task) + if parameters.number_of_parallel_points > 1: + return Calculator(index_method_evaluate, parameters) + else: + return DefaultCalculator(index_method_evaluate, parameters) + @staticmethod def create_method(parameters: SolverParameters, task: OptimizationTask, evolvent: Evolvent, - search_data: SearchData) -> Method: + search_data: SearchData, + calculator: Calculator) -> Method: """ Create a suitable solution method class based on the given parameters @@ -33,16 +81,18 @@ def create_method(parameters: SolverParameters, :param task: the wrapper of the problem to be solved. :param evolvent: Peano-Hilbert evolvent mapping the segment [0,1] to the multidimensional region D. :param search_data: data structure for storing accumulated search information. + :param calculator: класс, содержащий методы проведения испытаний (параллельные и/или индексную схему) :return: created method """ - - if task.problem.number_of_discrete_variables > 0: - return MixedIntegerMethod(parameters, task, evolvent, search_data) + if task.problem.number_of_objectives > 1: + return MCOMethodManyLambdas(parameters, task, evolvent, search_data, calculator) + elif task.problem.number_of_discrete_variables > 0: + return MixedIntegerMethod(parameters, task, evolvent, search_data, calculator) elif task.problem.number_of_constraints > 0: - return IndexMethod(parameters, task, evolvent, search_data) + return IndexMethod(parameters, task, evolvent, search_data, calculator) else: - return Method(parameters, task, evolvent, search_data) + return Method(parameters, task, evolvent, search_data, calculator) @staticmethod def create_process(parameters: SolverParameters, @@ -50,7 +100,8 @@ def create_process(parameters: SolverParameters, evolvent: Evolvent, search_data: SearchData, method: Method, - listeners: List[Listener]) -> Process: + listeners: List[Listener], + calculator: Calculator) -> Process: """ Create a suitable process class based on the specified parameters @@ -65,11 +116,10 @@ def create_process(parameters: SolverParameters, """ if parameters.number_of_parallel_points == 1: return Process(parameters=parameters, task=task, evolvent=evolvent, - search_data=search_data, method=method, listeners=listeners) + search_data=search_data, method=method, listeners=listeners, calculator=calculator) elif parameters.async_scheme: return AsyncParallelProcess(parameters=parameters, task=task, evolvent=evolvent, search_data=search_data, method=method, listeners=listeners) else: return ParallelProcess(parameters=parameters, task=task, evolvent=evolvent, - search_data=search_data, method=method, listeners=listeners) - + search_data=search_data, method=method, listeners=listeners, calculator=calculator) diff --git a/iOpt/output_system/painters/animate_painters.py b/iOpt/output_system/painters/animate_painters.py index 31ee190c..21e4b3bf 100644 --- a/iOpt/output_system/painters/animate_painters.py +++ b/iOpt/output_system/painters/animate_painters.py @@ -23,7 +23,7 @@ def __init__(self, is_points_at_bottom, parameter_in_nd_problem, path_for_saves, def set_problem(self, problem: Problem): self.objFunc = problem.calculate - self.number_of_constraints = self.problem.number_of_constraints + self.number_of_constraints = problem.number_of_constraints for i in range(problem.number_of_float_variables): self.section.append(float(problem.upper_bound_of_float_variables[i]) - float(problem.lower_bound_of_float_variables[i])) diff --git a/iOpt/solver.py b/iOpt/solver.py index b331aa8d..b004211c 100644 --- a/iOpt/solver.py +++ b/iOpt/solver.py @@ -1,8 +1,11 @@ from time import time from typing import List +import numpy as np from iOpt.evolvent.evolvent import Evolvent from iOpt.method.grid_search_method import GridSearchMethod +from iOpt.method.calculator import Calculator +from iOpt.method.index_method_evaluate import IndexMethodEvaluate from iOpt.method.listener import Listener from iOpt.method.optim_task import OptimizationTask from iOpt.method.search_data import SearchData @@ -41,11 +44,15 @@ def __init__(self, self.search_data = SearchData(problem) self.evolvent = Evolvent(problem.lower_bound_of_float_variables, problem.upper_bound_of_float_variables, problem.number_of_float_variables) - self.task = OptimizationTask(problem) - self.method = SolverFactory.create_method(parameters, self.task, self.evolvent, self.search_data) + self.task = SolverFactory.create_task(problem, parameters) + + self.calculator = SolverFactory.create_calculator(self.task, self.parameters) + + self.method = SolverFactory.create_method(parameters, self.task, self.evolvent, + self.search_data, self.calculator) self.process = SolverFactory.create_process(parameters=parameters, task=self.task, evolvent=self.evolvent, search_data=self.search_data, method=self.method, - listeners=self.__listeners) + listeners=self.__listeners, calculator=self.calculator) def solve(self) -> Solution: """ @@ -213,6 +220,23 @@ def check_parameters(problem: Problem, parameters.start_point.float_variables): if y < lower_bound or y > upper_bound: raise Exception("Incorrect start point coordinate") + if parameters.number_of_lambdas: + if parameters.number_of_lambdas < 0: + raise Exception("Number of lambda sets is incorrect, parameters.number_of_lambdas <= 0") + if parameters.start_lambdas: + if len(parameters.start_lambdas)>1 and len(parameters.start_lambdas)= 0 for lamb in lambdas) for lambdas in parameters.start_lambdas): + raise Exception("The lambda parameters must be non-negative") + + + # неортицательные и корличество или 1 или совпадет с кол-вом л + + + def grid_search(self) -> Solution: """ @@ -227,7 +251,7 @@ def grid_search(self) -> Solution: self.method = GridSearchMethod(self.parameters, self.task, self.evolvent, self.search_data) self.process = SolverFactory.create_process(parameters=self.parameters, task=self.task, evolvent=self.evolvent, search_data=self.search_data, method=self.method, - listeners=self.__listeners) + listeners=self.__listeners, calculator=self.calculator) sol = self.solve() diff --git a/iOpt/solver_parametrs.py b/iOpt/solver_parametrs.py index bb36f035..4a5947d1 100644 --- a/iOpt/solver_parametrs.py +++ b/iOpt/solver_parametrs.py @@ -18,7 +18,10 @@ def __init__(self, number_of_parallel_points: int = 1, async_scheme: bool = False, timeout: int = -1, - proportion_of_global_iterations: float = 0.95 + proportion_of_global_iterations: float = 0.95, + start_lambdas: list = [], + number_of_lambdas: int = 10, + is_scaling: bool = False ): r""" Constructor of SolverParameters class @@ -58,6 +61,11 @@ def __init__(self, self.async_scheme = async_scheme self.timeout = timeout + + self.start_lambdas = start_lambdas + self.number_of_lambdas = number_of_lambdas + self.is_scaling = is_scaling + def to_string(self) -> str: """ Creates a string containing the values of the main parameters diff --git a/problems/grishagin_mco.py b/problems/grishagin_mco.py new file mode 100644 index 00000000..d247ba9f --- /dev/null +++ b/problems/grishagin_mco.py @@ -0,0 +1,68 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import Trial +from iOpt.problem import Problem +from problems.grishagin_function.grishagin_function import GrishaginFunction + + +class Grishagin_mco(Problem): + """ + Функция Гришагина задана формулой: + :math:`f(y) = \{ (\sum_{i=1}^{7}\sum_{i=1}^{7} A_{ij}a_{ij}(x)+B_{ij}b_{ij}(x))^{2}+` + :math:`+(\sum_{i=1}^{7}\sum_{i=1}^{7} C_{ij}a_{ij}(x)+D_{ij}b_{ij}(x))^{2}\}`, + где :math:`a_{ij}(x) = sin(i\pi x_{1})sin(j\pi x_{2}),` + :math:`b_{ij}(x) = cos(i\pi x_{1})cos(j\pi x_{2}),` + коэффициенты :math:`A_{ij}, B_{ij}, C_{ij}, D_{ij}` - равномерно распределеные величины + на отрезке :math:`[-1, 1].` + """ + + def __init__(self, count_functions: int, + function_numbers: np.ndarray(shape=(1), dtype=int) = None + ): + """ + Конструктор класса Grishagin_mco problem. + + :param functionNumber: номер задачи в наборе, :math:`1 <= functionNumber <= 100` + :param countFunction: количество функций - критериев + """ + super(Grishagin_mco, self).__init__() + self.name = "Grishagin_mco" + self.dimension = 2 + self.number_of_float_variables = self.dimension + self.number_of_discrete_variables = 0 + self.number_of_objectives = count_functions + self.number_of_constraints = 0 + self.float_variable_names = np.ndarray(shape=(self.dimension,), dtype=str) + for i in range(self.dimension): + self.float_variable_names[i] = i + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.dimension,), dtype=np.double) + self.lower_bound_of_float_variables.fill(0) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.dimension,), dtype=np.double) + self.upper_bound_of_float_variables.fill(1) + + self.count_functions = count_functions + self.function_numbers = np.ndarray(shape=(self.count_functions, ), dtype=int) + if function_numbers: + self.function_numbers = function_numbers #сюда бы проверки всякие запихнуть + else: + for i in range(count_functions): + self.function_numbers[i]=i+1 # мб добавить рандомное заполнение? + + self.functions = np.ndarray(shape=(self.count_functions,), dtype=GrishaginFunction) + for i in range(count_functions): + self.functions[i] = GrishaginFunction(self.function_numbers[i]) + self.functions[i].SetFunctionNumber() + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + function_value.value = self.functions[function_value.functionID].Calculate(point.float_variables) + + return function_value diff --git a/problems/mco_test1.py b/problems/mco_test1.py new file mode 100644 index 00000000..d21d34c1 --- /dev/null +++ b/problems/mco_test1.py @@ -0,0 +1,60 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + + +class mco_test1(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test1, self).__init__() + self.name = "mco_test1" + self.dimension = 2 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(0) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(1) + + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + result = np.double((x[0]-1)*x[1]*x[1]+1) + elif function_value.functionID == 1: # OBJECTIV 2 + result = np.double(x[1]) + + function_value.value = result + return function_value + + diff --git a/problems/mco_test1_1.py b/problems/mco_test1_1.py new file mode 100644 index 00000000..73456bf4 --- /dev/null +++ b/problems/mco_test1_1.py @@ -0,0 +1,63 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + +test_points = np.array([ + +]) + +class mco_test1(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test1, self).__init__() + self.name = "mco_test1" + self.dimension = 2 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(0) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(1) + + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + result = np.double((x[0]-1)*x[1]*x[1]+1) + elif function_value.functionID == 1: # OBJECTIV 2 + result = np.double(x[1]) + + function_value.value = result + return function_value + + diff --git a/problems/mco_test3.py b/problems/mco_test3.py new file mode 100644 index 00000000..e0c18b7c --- /dev/null +++ b/problems/mco_test3.py @@ -0,0 +1,60 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + + +class mco_test3(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test3, self).__init__() + self.name = "mco_test3" + self.dimension = 2 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(0) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(2) + + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + result = np.double(x[0]) + elif function_value.functionID == 1: # OBJECTIV 2 + result = np.double(min(abs(x[0]-1), 1.5-x[0])+x[1]+1) + + function_value.value = result + return function_value + + diff --git a/problems/mco_test5.py b/problems/mco_test5.py new file mode 100644 index 00000000..fa63c367 --- /dev/null +++ b/problems/mco_test5.py @@ -0,0 +1,70 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + + +class mco_test5(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test5, self).__init__() + self.name = "mco_test5" + self.dimension = 3 + self.number_of_float_variables = 3 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(-5) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(5) + + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + result = np.double(-10 * (math.exp(-0.2 * math.sqrt(x[0] * x[0] + x[1] * x[1])) + \ + math.exp(-0.2 * math.sqrt(x[2] * x[2] + x[1] * x[1])))) + # print(x[0], x[1], x[2]) + # print((x[0] * x[0] + x[1] * x[1])) + # print(math.sqrt(x[0] * x[0] + x[1] * x[1])) + # print((-0.2 * math.sqrt(x[0] * x[0] + x[1] * x[1]))) + # print(math.exp(-0.2 * math.sqrt(x[0] * x[0] + x[1] * x[1]))) + # print(math.exp(-0.2 * math.sqrt(x[2] * x[2] + x[1] * x[1]))) + # print((math.exp(-0.2 * math.sqrt(x[0] * x[0] + x[1] * x[1])) + math.exp(-0.2 * math.sqrt(x[2] * x[2] + x[1] * x[1])))) + elif function_value.functionID == 1: # OBJECTIV 2 + result = 0 + for i in range(3): + result += pow(abs(x[i]), 0.8) + 5.0 * math.sin(x[i] * x[i] * x[i]) + + function_value.value = result + return function_value + + diff --git a/problems/mco_test6.py b/problems/mco_test6.py new file mode 100644 index 00000000..dea96303 --- /dev/null +++ b/problems/mco_test6.py @@ -0,0 +1,56 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + + +class mco_test6(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test6, self).__init__() + self.name = "mco_test6" + self.dimension = 2 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(0) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(1) + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + result = np.double(x[0]) + elif function_value.functionID == 1: # OBJECTIV 2 + result = np.double((1 - (x[0] / (1 + 10 * x[1])) * (x[0] / (1 + 10 * x[1])) - + (x[0] / (1 + 10 * x[1])) * math.sin(8 * x[0] * math.pi)) * (1 + 10 * x[1])) + + function_value.value = result + return function_value diff --git a/problems/mco_test7.py b/problems/mco_test7.py new file mode 100644 index 00000000..7d648da2 --- /dev/null +++ b/problems/mco_test7.py @@ -0,0 +1,63 @@ +import numpy as np +from iOpt.trial import Point +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Trial +from iOpt.problem import Problem +import math + + +class mco_test7(Problem): + """ + + """ + + def __init__(self): + """ + Конструктор класса mco_test1 problem. + """ + super(mco_test7, self).__init__() + self.name = "mco_test7" + self.dimension = 3 + self.number_of_float_variables = 2 + self.number_of_discrete_variables = 0 + self.number_of_objectives = 2 + self.number_of_constraints = 0 + + self.float_variable_names = np.ndarray(shape=(self.number_of_float_variables,), dtype=object) + for i in range(self.number_of_float_variables): + self.float_variable_names[i] = str(i) + + self.lower_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.lower_bound_of_float_variables.fill(-4) + self.upper_bound_of_float_variables = np.ndarray(shape=(self.number_of_float_variables,), dtype=np.double) + self.upper_bound_of_float_variables.fill(4) + + self.known_optimum = np.ndarray(shape=(1,), dtype=Trial) + + def calculate(self, point: Point, function_value: FunctionValue) -> FunctionValue: + """ + Вычисление значения выбранной функции в заданной точке. + + :param point: координаты точки испытания, в которой будет вычислено значение функции + :param function_value: объект, определяющий номер функции в задаче и хранящий значение функции + :return: Вычисленное значение функции в точке point + """ + result: np.double = 0 + x = point.float_variables + + if function_value.functionID == 0: # OBJECTIV 1 + val = 0 + for i in range(3): + val += (x[i] - 1 / math.sqrt(3)) * (x[i] - 1 / math.sqrt(3)) + result = np.double(1 - math.exp(-val)) + + + elif function_value.functionID == 1: # OBJECTIV 2 + val = 0 + for i in range(3): + val += (x[i] + 1 / math.sqrt(3)) * (x[i] + 1 / math.sqrt(3)) + result = np.double(1 - math.exp(-val)) + + function_value.value = result + return function_value diff --git a/test/iOpt/method/test_mco_task.py b/test/iOpt/method/test_mco_task.py new file mode 100644 index 00000000..0bb6a2b5 --- /dev/null +++ b/test/iOpt/method/test_mco_task.py @@ -0,0 +1,80 @@ +from iOpt.method.search_data import SearchDataItem +from problems.grishagin_mco import Grishagin_mco +from iOpt.trial import Point +from iOpt.trial import FunctionValue +import numpy as np +from iOpt.method.mco_optim_task import MCOOptimizationTask +from iOpt.method.mco_optim_task import MinMaxConvolution +from iOpt.method.optim_task import TypeOfCalculation + +if __name__ == "__main__": + + problem = Grishagin_mco(2, [1, 2]) + conv = MinMaxConvolution(problem, [0.5, 0.5], False) + task = MCOOptimizationTask(problem, conv) + + task.min_value = [np.double(-13.51436), np.double(-11.28447)] + + min_z = 100 + min_point = Point([], []) + min_fun = np.ndarray(shape=(2,), dtype=FunctionValue) + + for i in range(0, 100): + for j in range(0, 100): + pointfv = [np.double(i/100), np.double(j/100)] + point = Point(pointfv, []) + + funV = np.ndarray(shape=(2,), dtype=FunctionValue) + for k in range(0, 2): + funV[k] = FunctionValue(functionID=k) + funV[k] = problem.calculate(point, funV[k]) + + sditem = SearchDataItem(point, point.float_variables[1], funV, []) + task.calculate(sditem, -1, TypeOfCalculation.CONVOLUTION) + + if (min_z > sditem.get_z()): + min_z = sditem.get_z() + min_point = sditem.point + min_fun = funV + + print(min_z, min_point.float_variables, [fv.value for fv in min_fun]) + # 1.3206019466549357 [0.63, 0.37] [-10.906885767640356, -8.64326610669013] + + #is_scaling + # 0.11702826509839945 [0.63, 0.37] [-10.906885767640356, -8.64326610669013] + + "" + # Pareto set after 5000 iterations + # [-10.20071994533217, -9.048618851776029][0.62353516 0.36083984] + # [-8.301130179104787, -10.40551296979958][0.65185547 0.35107422] + # [-13.144906394676253, -6.072324595007004][0.61181641 0.39404297] + # [-11.938589250054529, -7.441058563760394][0.62939453 0.38427734] + # [-10.190288362639677, -9.221841563370118][0.63330078 0.36376953] + # [-7.204550076392398, -11.000241595429669][0.66455078 0.33349609] + # [-5.7913570098004525, -11.24874919452789][0.64697266 0.32080078] + # [-9.302230472348885, -9.553057450921768][0.64892578 0.36376953] + # [-9.15234020775477, -9.781148328755988][0.62939453 0.35302734] + # [-12.848034559388259, -6.54532948000002][0.61669922 0.39013672] + # [-10.3094368604201, -8.62635751498344][0.64404297 0.37451172] + # [-11.27774822721674, -8.30936389536164][0.62841797 0.37353516] + # [-9.121203314934272, -9.96846279713267][0.64111328 0.35595703] + # [-11.910727880612416, -7.706230147786212][0.62060547 0.37744141] + # [-8.294820285320384, -10.41957178118964][0.63916016 0.34716797] + # [-12.200336647760743, -7.069230751600034][0.60791016 0.37841797] + # [-7.637515158932618, -10.77240652397774][0.65869141 0.34326172] + # [-7.207698192143824, -10.855790821057813][0.67333984 0.32470703] + # [-12.96704615527787, -6.2097075149626155][0.60595703 0.38916016] + # [-6.764254636468001, -11.2176851692763][0.65869141 0.32666016] + # [-13.397922583064096, -5.481333524951266][0.60693359 0.39990234] + # [-6.8004941888681, -11.203703457526622][0.65478516 0.32958984] + # [-13.432857223048867, -4.758964996890917][0.60888672 0.41162109] + "" + + #0.603052, 0.408337, # f(min1)=-13.51436 + #0.652988, 0.320592, # f(min2)=-11.28447 + #1.000000, 0.000000, # f(min3)=-13.20907 + #0.066182, 0.582587, # f(min4)=-11.54117 + #0.904308, 0.872639, # f(min5)=-9.969261 + + + diff --git a/test/iOpt/method/test_method.py b/test/iOpt/method/test_method.py index 69731960..d2d10bb7 100644 --- a/test/iOpt/method/test_method.py +++ b/test/iOpt/method/test_method.py @@ -4,9 +4,7 @@ import numpy as np -from iOpt.evolvent.evolvent import Evolvent - -from iOpt.method.search_data import SearchData, SearchDataItem +from iOpt.method.search_data import SearchDataItem from iOpt.solver import SolverParameters from iOpt.method.method import Method from iOpt.trial import Point diff --git a/test/iOpt/method/test_mixed_integer_method.py b/test/iOpt/method/test_mixed_integer_method.py index 3feed079..3c58e7ba 100644 --- a/test/iOpt/method/test_mixed_integer_method.py +++ b/test/iOpt/method/test_mixed_integer_method.py @@ -7,6 +7,7 @@ from iOpt.method.optim_task import OptimizationTask from iOpt.method.calculator import Calculator +from iOpt.method.solverFactory import SolverFactory from iOpt.trial import Point from iOpt.method.search_data import SearchDataItem from iOpt.solver_parametrs import SolverParameters @@ -31,6 +32,7 @@ def setUp(self, mock_evolvent, mock_problem): mock_problem.number_of_constraints = 0 task = OptimizationTask(mock_problem) + self.mixedIntegerMethod = MixedIntegerMethod(SolverParameters(), task, mock_evolvent, SearchData(mock_problem)) self.globalTrials_RI_d_3 = 132 @@ -59,11 +61,13 @@ def test_GetDiscreteParameters(self): self.assertEqual(dp, [("A", "A"), ("A", "B"), ("B", "A"), ("B", "B")]) def test_FirstIteration(self): - self.mixedIntegerMethod.calculate_functionals = Mock(side_effect=self.mock_CalculateFunctionals) + calculator = Calculator(None, self.mixedIntegerMethod.parameters) + calculator.calculate_functionals_for_items = Mock(side_effect=self.mock_CalculateFunctionalsForItems) + self.mixedIntegerMethod.calculator = calculator self.mixedIntegerMethod.evolvent.get_image = Mock(side_effect=self.mock_GetImage) self.mixedIntegerMethod.first_iteration() self.assertEqual(self.mixedIntegerMethod.search_data.get_count(), 9) - self.mixedIntegerMethod.calculate_functionals.assert_called() + calculator.calculate_functionals_for_items.assert_called() self.mixedIntegerMethod.evolvent.get_image.assert_called() def test_FirstIterationParallel(self): @@ -71,7 +75,8 @@ def test_FirstIterationParallel(self): self.mixedIntegerMethod.evolvent.get_image = Mock(side_effect=self.mock_GetImage) calculator = Calculator(None, self.mixedIntegerMethod.parameters) calculator.calculate_functionals_for_items = Mock(side_effect=self.mock_CalculateFunctionalsForItems) - self.mixedIntegerMethod.first_iteration(calculator) + self.mixedIntegerMethod.calculator = calculator + self.mixedIntegerMethod.first_iteration() self.assertEqual(self.mixedIntegerMethod.search_data.get_count(), 13) calculator.calculate_functionals_for_items.assert_called() self.mixedIntegerMethod.evolvent.get_image.assert_called() diff --git a/test/iOpt/method/test_multi_objective_method.py b/test/iOpt/method/test_multi_objective_method.py new file mode 100644 index 00000000..a162b25d --- /dev/null +++ b/test/iOpt/method/test_multi_objective_method.py @@ -0,0 +1,193 @@ +import unittest +from unittest import mock +from unittest.mock import Mock + +import numpy as np + +from iOpt.method.search_data import SearchData, SearchDataItem +from iOpt.solver import SolverParameters +from iOpt.method.method import Method +from iOpt.trial import Point + + +class TestMethod(unittest.TestCase): + @staticmethod + def GetImage(x: np.double) -> np.double: + return x + + @mock.patch('iOpt.evolvent.evolvent') + @mock.patch('iOpt.method.mco_optim_task.OptimizationTask') + @mock.patch('iOpt.method.search_data.SearchData') + def setUp(self, mock_evolvent, mock_task, mock_searchData): + mock_evolvent.get_image.return_value = Mock(side_effect=self.GetImage) + + self.method = Method(evolvent=mock_evolvent, parameters=SolverParameters(), + task=mock_task, search_data=mock_searchData) + + def test_mockev(self): + self.method.evolvent.get_image = Mock(side_effect=self.GetImage) + self.assertEqual(self.method.evolvent.get_image(0.0), 0.0) + self.assertEqual(self.method.evolvent.get_image(0.5), 0.5) + self.assertEqual(self.method.evolvent.get_image(1.0), 1.0) + + def test_CalculateM_easy(self): + left = SearchDataItem(x=0.0, y=Point(float_variables=[5.0], discrete_variables=[])) + curr = SearchDataItem(x=1.0, y=Point(float_variables=[10.0], discrete_variables=[])) + curr.set_left(left) + self.method.M[0] = 1.0 + assert (self.method.M[0] == 1.0) + curr.delta = 1.0 + left.set_z(0.0) + curr.set_z(10.0) + left.set_index(0) + curr.set_index(0) + # test 1. NOT AAA, BUT INITIALIZATION IS TOO BIG, AND DIFFERENT FOR easy and hard + self.method.recalcR = False + self.method.calculate_m(curr, left) + assert (self.method.M[0] == 10.0) + self.assertTrue(self.method.recalcR) + # test 2 + self.method.recalcR = False + curr.set_z(-20.0) + self.method.calculate_m(curr, left) + assert (self.method.M[0] == 20.0) + self.assertTrue(self.method.recalcR) + # test 3 + self.method.recalcR = False + curr.set_z(-5.0) + self.method.calculate_m(curr, left) + assert (self.method.M[0] == 20.0) + self.assertFalse(self.method.recalcR) + + def test_CalculateM_hard(self): + left = SearchDataItem(x=0.1, y=Point(float_variables=[6.0], discrete_variables=[])) + curr = SearchDataItem(x=0.5, y=Point(float_variables=[10.0], discrete_variables=[])) + right = SearchDataItem(x=1.0, y=Point(float_variables=[15.0], discrete_variables=[])) + curr.set_left(left) + assert (self.method.M[0] == 1.0) + curr.delta = 0.4 + right.delta = 0.5 + left.set_z(6.0) + curr.set_z(16.0) + right.set_z(2000.0) + left.set_index(0) + curr.set_index(0) + right.set_index(1) + # test 1 + self.method.recalcR = False + self.method.calculate_m(curr, left) + self.assertEqual(self.method.M[0], 25.0) + self.assertTrue(self.method.recalcR) + # test 2 + self.method.recalcR = False + self.method.calculate_m(right, curr) + self.assertEqual(self.method.M[0], 25.0) + self.assertFalse(self.method.recalcR) + # test 3 + self.method.recalcR = False + self.method.calculate_m(curr, right) + self.assertEqual(self.method.M[0], 25.0) + self.assertFalse(self.method.recalcR) + + def test_CalculateM_dont_throws(self): + curr = SearchDataItem(x=0.5, y=Point(float_variables=[10.0], discrete_variables=[])) + + try: + self.method.calculate_m(curr, None) + except RuntimeError: + self.fail("exception was raised!") + + def test_CalculateM_throws(self): + curr = SearchDataItem(x=0.5, y=Point(float_variables=[10.0], discrete_variables=[])) + with self.assertRaises(Exception): + self.method.calculate_m(None, curr) + + def test_Iteration_count(self): + itcount = self.method.get_iterations_count() + self.method.finalize_iteration() + self.assertEqual(self.method.get_iterations_count(), itcount + 1) + + def test_calculate_global_r(self): + left = SearchDataItem(x=0.0, y=Point(float_variables=[5.0], discrete_variables=[])) + curr = SearchDataItem(x=1.0, y=Point(float_variables=[10.0], discrete_variables=[])) + curr.set_left(left) + curr.delta = 1.0 + left.set_z(5.0) + curr.set_z(15.0) + self.method.M[0] = 10.0 + left.set_index(0) + curr.set_index(0) + self.method.parameters.r = 2.0 + self.method.Z[0] = 5.0 + + # test 1 + self.method.calculate_global_r(curr, left) + self.assertEqual(curr.globalR, 0.25) + # test 2 + curr.set_index(-2) + self.method.calculate_global_r(curr, left) + self.assertEqual(curr.globalR, 2.0) + # test 3 + curr.set_index(0) + left.set_index(-2) + self.method.calculate_global_r(curr, left) + self.assertEqual(curr.globalR, 0) + # test 4 + self.method.parameters.r = 4.0 + self.method.Z = [-7, -25.0] + self.method.M = [17.54, 40.0] + left.set_index(1) + curr.set_index(0) + self.method.calculate_global_r(curr, left) + self.assertEqual(curr.globalR, 1.25) + + def test_calculate_global_r_throws(self): + left = SearchDataItem(x=0.5, y=Point(float_variables=[10.0], discrete_variables=[])) + + left.set_z(15.0) + self.method.M[0] = 10.0 + with self.assertRaises(Exception): + self.method.calculate_global_r(None, left) + + def test_CalculateNextPointCoordinate(self): + self.method.task.problem.number_of_float_variables = 1 + left = SearchDataItem(x=0.0, y=Point(float_variables=[5.0], discrete_variables=[])) + curr = SearchDataItem(x=1.0, y=Point(float_variables=[10.0], discrete_variables=[])) + + curr.delta = 1.0 + left.set_z(5.0) + curr.set_z(15.0) + self.method.M[0] = 10.0 + left.set_index(0) + curr.set_index(0) + self.method.parameters.r = 2.0 + + # test 1 + curr.set_left(left) + self.assertEqual(0.25, self.method.calculate_next_point_coordinate(curr)) + + # test 2 + left.set_index(-2) + self.assertEqual(0.5, self.method.calculate_next_point_coordinate(curr)) + + def test_CalculateNextPointCoordinate_throws(self): + self.method.task.problem.number_of_float_variables = 1 + curr = SearchDataItem(x=0.5, y=Point(float_variables=[10.0], discrete_variables=[])) + + curr.set_z(15.0) + self.method.M[0] = 10.0 + # test 1 + with self.assertRaises(Exception): + self.method.calculate_next_point_coordinate(curr) + # test 2 + curr.set_left(curr) + with self.assertRaises(Exception): + self.method.calculate_next_point_coordinate(curr) + + +# def test_RecalcAll_mock(self): + + +# Executing the tests in the above test case class +if __name__ == "__main__": + unittest.main() diff --git a/test/iOpt/method/test_process.py b/test/iOpt/method/test_process.py index 74f9415d..f9a01a5f 100644 --- a/test/iOpt/method/test_process.py +++ b/test/iOpt/method/test_process.py @@ -112,6 +112,7 @@ def mock_CalculateTask(self, dataItem: SearchDataItem, functionIndex: int = 0, def test_DoGlobalIterationAndListener(self, mock_OnEndIteration, mock_BeforeMethodStart): self.process.method.evolvent.get_image = Mock(side_effect=self.mock_GetImage) self.process.task.calculate = Mock(side_effect=self.mock_CalculateTask) + try: self.process.do_global_iteration(1) mock_BeforeMethodStart.assert_called_once() diff --git a/test/problems/pointsForTest/mco_test1_points.py b/test/problems/pointsForTest/mco_test1_points.py new file mode 100644 index 00000000..a5a2a5f7 --- /dev/null +++ b/test/problems/pointsForTest/mco_test1_points.py @@ -0,0 +1,128 @@ +import numpy as np + +test_points = np.array([[1.00000, 0.00000, 0.00000, 0.00000], + [1.00000, 0.00200, 0.00000, 0.00200], + [0.99998, 0.00400, 0.00000, 0.00400], + [0.99996, 0.00600, 0.00000, 0.00600], + [0.99994, 0.00800, 0.00000, 0.00800], + [0.99990, 0.01000, 0.00000, 0.01000], + [0.99986, 0.01200, 0.00000, 0.01200], + [0.99980, 0.01400, 0.00000, 0.01400], + [0.99974, 0.01600, 0.00000, 0.01600], + [0.99968, 0.01800, 0.00000, 0.01800], + [0.99960, 0.02000, 0.00000, 0.02000], + [0.99952, 0.02200, 0.00000, 0.02200], + [0.99942, 0.02400, 0.00000, 0.02400], + [0.99932, 0.02600, 0.00000, 0.02600], + [0.99922, 0.02800, 0.00000, 0.02800], + [0.99910, 0.03000, 0.00000, 0.03000], + [0.99898, 0.03200, 0.00000, 0.03200], + [0.99884, 0.03400, 0.00000, 0.03400], + [0.99870, 0.03600, 0.00000, 0.03600], + [0.99856, 0.03800, 0.00000, 0.03800], + [0.99840, 0.04000, 0.00000, 0.04000], + [0.99824, 0.04200, 0.00000, 0.04200], + [0.99806, 0.04400, 0.00000, 0.04400], + [0.99788, 0.04600, 0.00000, 0.04600], + [0.99770, 0.04800, 0.00000, 0.04800], + [0.99750, 0.05000, 0.00000, 0.05000], + [0.99730, 0.05200, 0.00000, 0.05200], + [0.99708, 0.05400, 0.00000, 0.05400], + [0.99686, 0.05600, 0.00000, 0.05600], + [0.99664, 0.05800, 0.00000, 0.05800], + [0.99640, 0.06000, 0.00000, 0.06000], + [0.99616, 0.06200, 0.00000, 0.06200], + [0.99590, 0.06400, 0.00000, 0.06400], + [0.99564, 0.06600, 0.00000, 0.06600], + [0.99538, 0.06800, 0.00000, 0.06800], + [0.99510, 0.07000, 0.00000, 0.07000], + [0.99482, 0.07200, 0.00000, 0.07200], + [0.99452, 0.07400, 0.00000, 0.07400], + [0.99422, 0.07600, 0.00000, 0.07600], + [0.99392, 0.07800, 0.00000, 0.07800], + [0.99360, 0.08000, 0.00000, 0.08000], + [0.99328, 0.08200, 0.00000, 0.08200], + [0.99294, 0.08400, 0.00000, 0.08400], + [0.99260, 0.08600, 0.00000, 0.08600], + [0.99226, 0.08800, 0.00000, 0.08800], + [0.99190, 0.09000, 0.00000, 0.09000], + [0.99154, 0.09200, 0.00000, 0.09200], + [0.99116, 0.09400, 0.00000, 0.09400], + [0.99078, 0.09600, 0.00000, 0.09600], + [0.99040, 0.09800, 0.00000, 0.09800], + [0.99000, 0.10000, 0.00000, 0.10000], + [0.98960, 0.10200, 0.00000, 0.10200], + [0.98918, 0.10400, 0.00000, 0.10400], + [0.98876, 0.10600, 0.00000, 0.10600], + [0.98834, 0.10800, 0.00000, 0.10800], + [0.98790, 0.11000, 0.00000, 0.11000], + [0.98746, 0.11200, 0.00000, 0.11200], + [0.98700, 0.11400, 0.00000, 0.11400], + [0.98654, 0.11600, 0.00000, 0.11600], + [0.98608, 0.11800, 0.00000, 0.11800], + [0.98560, 0.12000, 0.00000, 0.12000], + [0.98512, 0.12200, 0.00000, 0.12200], + [0.98462, 0.12400, 0.00000, 0.12400], + [0.98412, 0.12600, 0.00000, 0.12600], + [0.98362, 0.12800, 0.00000, 0.12800], + [0.98310, 0.13000, 0.00000, 0.13000], + [0.98258, 0.13200, 0.00000, 0.13200], + [0.98204, 0.13400, 0.00000, 0.13400], + [0.98150, 0.13600, 0.00000, 0.13600], + [0.98096, 0.13800, 0.00000, 0.13800], + [0.98040, 0.14000, 0.00000, 0.14000], + [0.97984, 0.14200, 0.00000, 0.14200], + [0.97926, 0.14400, 0.00000, 0.14400], + [0.97868, 0.14600, 0.00000, 0.14600], + [0.97810, 0.14800, 0.00000, 0.14800], + [0.97750, 0.15000, 0.00000, 0.15000], + [0.97690, 0.15200, 0.00000, 0.15200], + [0.97628, 0.15400, 0.00000, 0.15400], + [0.97566, 0.15600, 0.00000, 0.15600], + [0.97504, 0.15800, 0.00000, 0.15800], + [0.97440, 0.16000, 0.00000, 0.16000], + [0.97376, 0.16200, 0.00000, 0.16200], + [0.97310, 0.16400, 0.00000, 0.16400], + [0.97244, 0.16600, 0.00000, 0.16600], + [0.97178, 0.16800, 0.00000, 0.16800], + [0.97110, 0.17000, 0.00000, 0.17000], + [0.97042, 0.17200, 0.00000, 0.17200], + [0.96972, 0.17400, 0.00000, 0.17400], + [0.96902, 0.17600, 0.00000, 0.17600], + [0.96832, 0.17800, 0.00000, 0.17800], + [0.96760, 0.18000, 0.00000, 0.18000], + [0.96688, 0.18200, 0.00000, 0.18200], + [0.96614, 0.18400, 0.00000, 0.18400], + [0.96540, 0.18600, 0.00000, 0.18600], + [0.96466, 0.18800, 0.00000, 0.18800], + [0.96390, 0.19000, 0.00000, 0.19000], + [0.96314, 0.19200, 0.00000, 0.19200], + [0.96236, 0.19400, 0.00000, 0.19400], + [0.96158, 0.19600, 0.00000, 0.19600], + [0.96080, 0.19800, 0.00000, 0.19800], + [0.96000, 0.20000, 0.00000, 0.20000], + [0.95920, 0.20200, 0.00000, 0.20200], + [0.95838, 0.20400, 0.00000, 0.20400], + [0.95756, 0.20600, 0.00000, 0.20600], + [0.95674, 0.20800, 0.00000, 0.20800], + [0.95590, 0.21000, 0.00000, 0.21000], + [0.95506, 0.21200, 0.00000, 0.21200], + [0.95420, 0.21400, 0.00000, 0.21400], + [0.95334, 0.21600, 0.00000, 0.21600], + [0.95248, 0.21800, 0.00000, 0.21800], + [0.95160, 0.22000, 0.00000, 0.22000], + [0.95072, 0.22200, 0.00000, 0.22200], + [0.94982, 0.22400, 0.00000, 0.22400], + [0.94892, 0.22600, 0.00000, 0.22600], + [0.94802, 0.22800, 0.00000, 0.22800], + [0.94710, 0.23000, 0.00000, 0.23000], + [0.94618, 0.23200, 0.00000, 0.23200], + [0.94524, 0.23400, 0.00000, 0.23400], + [0.94430, 0.23600, 0.00000, 0.23600], + [0.94336, 0.23800, 0.00000, 0.23800], + [0.94240, 0.24000, 0.00000, 0.24000], + [0.94144, 0.24200, 0.00000, 0.24200], + [0.94046, 0.24400, 0.00000, 0.24400], + [0.93948, 0.24600, 0.00000, 0.24600], + [0.93850, 0.24800, 0.00000, 0.24800] + ], dtype=np.double) diff --git a/test/problems/pointsForTest/mco_test3_points.py b/test/problems/pointsForTest/mco_test3_points.py new file mode 100644 index 00000000..568fbb24 --- /dev/null +++ b/test/problems/pointsForTest/mco_test3_points.py @@ -0,0 +1,105 @@ +import numpy as np + +test_points = np.array([ + [0.60400, 1.39600, 0.60400, 0.00000], + [0.60400, 1.39800, 0.60400, 0.00200], + [0.60600, 1.39400, 0.60600, 0.00000], + [0.60600, 1.39600, 0.60600, 0.00200], + [0.60800, 1.39200, 0.60800, 0.00000], + [0.60800, 1.39400, 0.60800, 0.00200], + [0.61000, 1.39000, 0.61000, 0.00000], + [0.61000, 1.39200, 0.61000, 0.00200], + [0.61200, 1.38800, 0.61200, 0.00000], + [0.61200, 1.39000, 0.61200, 0.00200], + [0.61400, 1.38600, 0.61400, 0.00000], + [0.61400, 1.38800, 0.61400, 0.00200], + [0.61600, 1.38400, 0.61600, 0.00000], + [0.61600, 1.38600, 0.61600, 0.00200], + [0.61800, 1.38200, 0.61800, 0.00000], + [0.61800, 1.38400, 0.61800, 0.00200], + [0.62000, 1.38000, 0.62000, 0.00000], + [0.62000, 1.38200, 0.62000, 0.00200], + [0.62200, 1.37800, 0.62200, 0.00000], + [0.62200, 1.38000, 0.62200, 0.00200], + [0.62400, 1.37600, 0.62400, 0.00000], + [0.62400, 1.37800, 0.62400, 0.00200], + [0.62600, 1.37400, 0.62600, 0.00000], + [0.62600, 1.37600, 0.62600, 0.00200], + [0.62800, 1.37200, 0.62800, 0.00000], + [0.62800, 1.37400, 0.62800, 0.00200], + [0.63000, 1.37000, 0.63000, 0.00000], + [0.63000, 1.37200, 0.63000, 0.00200], + [0.63200, 1.36800, 0.63200, 0.00000], + [0.63200, 1.37000, 0.63200, 0.00200], + [0.63400, 1.36600, 0.63400, 0.00000], + [0.63400, 1.36800, 0.63400, 0.00200], + [0.63600, 1.36400, 0.63600, 0.00000], + [0.63600, 1.36600, 0.63600, 0.00200], + [0.63800, 1.36200, 0.63800, 0.00000], + [0.63800, 1.36400, 0.63800, 0.00200], + [0.64000, 1.36000, 0.64000, 0.00000], + [0.64000, 1.36200, 0.64000, 0.00200], + [0.64200, 1.35800, 0.64200, 0.00000], + [0.64200, 1.36000, 0.64200, 0.00200], + [0.64400, 1.35600, 0.64400, 0.00000], + [0.64400, 1.35800, 0.64400, 0.00200], + [0.64600, 1.35400, 0.64600, 0.00000], + [0.64600, 1.35600, 0.64600, 0.00200], + [0.64800, 1.35200, 0.64800, 0.00000], + [0.64800, 1.35400, 0.64800, 0.00200], + [0.65000, 1.35000, 0.65000, 0.00000], + [0.65000, 1.35200, 0.65000, 0.00200], + [0.65200, 1.34800, 0.65200, 0.00000], + [0.65200, 1.35000, 0.65200, 0.00200], + [0.65400, 1.34600, 0.65400, 0.00000], + [0.65400, 1.34800, 0.65400, 0.00200], + [0.65600, 1.34400, 0.65600, 0.00000], + [0.65600, 1.34600, 0.65600, 0.00200], + [0.65800, 1.34200, 0.65800, 0.00000], + [0.65800, 1.34400, 0.65800, 0.00200], + [0.66000, 1.34000, 0.66000, 0.00000], + [0.66000, 1.34200, 0.66000, 0.00200], + [0.66200, 1.33800, 0.66200, 0.00000], + [0.66200, 1.34000, 0.66200, 0.00200], + [0.66400, 1.33600, 0.66400, 0.00000], + [0.66400, 1.33800, 0.66400, 0.00200], + [0.66600, 1.33400, 0.66600, 0.00000], + [0.66600, 1.33600, 0.66600, 0.00200], + [0.66800, 1.33200, 0.66800, 0.00000], + [0.66800, 1.33400, 0.66800, 0.00200], + [0.67000, 1.33000, 0.67000, 0.00000], + [0.67000, 1.33200, 0.67000, 0.00200], + [0.67200, 1.32800, 0.67200, 0.00000], + [0.67200, 1.33000, 0.67200, 0.00200], + [0.67400, 1.32600, 0.67400, 0.00000], + [0.67400, 1.32800, 0.67400, 0.00200], + [0.67600, 1.32400, 0.67600, 0.00000], + [0.67600, 1.32600, 0.67600, 0.00200], + [0.67800, 1.32200, 0.67800, 0.00000], + [0.67800, 1.32400, 0.67800, 0.00200], + [0.68000, 1.32000, 0.68000, 0.00000], + [0.68000, 1.32200, 0.68000, 0.00200], + [0.68200, 1.31800, 0.68200, 0.00000], + [0.68200, 1.32000, 0.68200, 0.00200], + [0.68400, 1.31600, 0.68400, 0.00000], + [0.68400, 1.31800, 0.68400, 0.00200], + [0.68600, 1.31400, 0.68600, 0.00000], + [0.68600, 1.31600, 0.68600, 0.00200], + [0.68800, 1.31200, 0.68800, 0.00000], + [0.68800, 1.31400, 0.68800, 0.00200], + [0.69000, 1.31000, 0.69000, 0.00000], + [0.69000, 1.31200, 0.69000, 0.00200], + [0.69200, 1.30800, 0.69200, 0.00000], + [0.69200, 1.31000, 0.69200, 0.00200], + [0.69400, 1.30600, 0.69400, 0.00000], + [0.69400, 1.30800, 0.69400, 0.00200], + [0.69600, 1.30400, 0.69600, 0.00000], + [0.69600, 1.30600, 0.69600, 0.00200], + [0.69800, 1.30200, 0.69800, 0.00000], + [0.69800, 1.30400, 0.69800, 0.00200], + [0.70000, 1.30000, 0.70000, 0.00000], + [0.70000, 1.30200, 0.70000, 0.00200], + [0.70200, 1.29800, 0.70200, 0.00000], + [0.70200, 1.30000, 0.70200, 0.00200], + [0.70400, 1.29600, 0.70400, 0.00000] +], dtype=np.double) diff --git a/test/problems/pointsForTest/mco_test5_points.py b/test/problems/pointsForTest/mco_test5_points.py new file mode 100644 index 00000000..2e60d4c9 --- /dev/null +++ b/test/problems/pointsForTest/mco_test5_points.py @@ -0,0 +1,106 @@ +import numpy as np + +test_points = np.array([ + [-14.40586, -11.62105, -1.16000, -1.16000, 0.00000], + [-14.44648, -11.61695, -1.16000, -1.16000, 0.00000], + [-14.46703, -11.61285, -1.16000, -1.14000, 0.00000], + [-14.50765, -11.57974, -1.16000, -1.14000, 0.00000], + [-15.85892, -7.74736, -1.16000, -1.16000, 0.00000], + [-15.89070, -7.74327, -1.16000, -1.14000, 0.00000], + [-15.92261, -7.71016, -1.16000, -1.12000, 0.00000], + [-17.92946, -3.87368, -1.16000, 0.00000, 0.00000], + [-14.42617, -11.61695, -1.14000, -1.16000, 0.00000], + [-14.44648, -11.61285, -1.14000, -1.14000, 0.00000], + [-14.46703, -11.61285, -1.14000, -1.16000, 0.00000], + [-14.48758, -11.60875, -1.14000, -1.14000, 0.00000], + [-14.50800, -11.57565, -1.14000, -1.12000, 0.00000], + [-14.50765, -11.57974, -1.14000, -1.16000, 0.00000], + [-14.52843, -11.57565, -1.14000, -1.14000, 0.00000], + [-14.54910, -11.54254, -1.14000, -1.12000, 0.00000], + [-14.56903, -11.51687, -1.14000, -1.14000, 0.00000], + [-14.58994, -11.48376, -1.14000, -1.12000, 0.00000], + [-14.63051, -11.40257, -1.14000, -1.12000, 0.00000], + [-15.89070, -7.74327, -1.14000, -1.16000, 0.00000], + [-15.92249, -7.73917, -1.14000, -1.14000, 0.00000], + [-15.95439, -7.70606, -1.14000, -1.12000, 0.00000], + [-15.98643, -7.64729, -1.14000, -1.10000, 0.00000], + [-16.01860, -7.56609, -1.14000, -1.08000, 0.00000], + [-16.90169, -4.11430, -1.14000, -0.56000, 0.00000], + [-16.93752, -4.04283, -1.14000, -0.54000, 0.00000], + [-16.97350, -3.97765, -1.14000, -0.52000, 0.00000], + [-17.00962, -3.91861, -1.14000, -0.50000, 0.00000], + [-17.96124, -3.86958, -1.14000, 0.00000, 0.00000], + [-14.50800, -11.57565, -1.12000, -1.14000, 0.00000], + [-14.52843, -11.54254, -1.12000, -1.12000, 0.00000], + [-14.54910, -11.54254, -1.12000, -1.14000, 0.00000], + [-14.56976, -11.50943, -1.12000, -1.12000, 0.00000], + [-14.59031, -11.45066, -1.12000, -1.10000, 0.00000], + [-14.58994, -11.48376, -1.12000, -1.14000, 0.00000], + [-14.61085, -11.45066, -1.12000, -1.12000, 0.00000], + [-14.63163, -11.39188, -1.12000, -1.10000, 0.00000], + [-14.63051, -11.40257, -1.12000, -1.14000, 0.00000], + [-14.65166, -11.36946, -1.12000, -1.12000, 0.00000], + [-14.67270, -11.31069, -1.12000, -1.10000, 0.00000], + [-14.69220, -11.26897, -1.12000, -1.12000, 0.00000], + [-14.71348, -11.21019, -1.12000, -1.10000, 0.00000], + [-14.73245, -11.15212, -1.12000, -1.12000, 0.00000], + [-14.75399, -11.09335, -1.12000, -1.10000, 0.00000], + [-14.79418, -10.96294, -1.12000, -1.10000, 0.00000], + [-15.53934, -8.02126, -1.12000, -1.10000, 0.00000], + [-15.56855, -7.93680, -1.12000, -1.10000, 0.00000], + [-15.56917, -7.91767, -1.12000, -1.12000, 0.00000], + [-15.59702, -7.85890, -1.12000, -1.10000, 0.00000], + [-15.92261, -7.71016, -1.12000, -1.16000, 0.00000], + [-15.95439, -7.70606, -1.12000, -1.14000, 0.00000], + [-15.98630, -7.67295, -1.12000, -1.12000, 0.00000], + [-16.01834, -7.61418, -1.12000, -1.10000, 0.00000], + [-16.05050, -7.53298, -1.12000, -1.08000, 0.00000], + [-16.08280, -7.43249, -1.12000, -1.06000, 0.00000], + [-16.11522, -7.31565, -1.12000, -1.04000, 0.00000], + [-16.75656, -4.53704, -1.12000, -0.66000, 0.00000], + [-16.79169, -4.43248, -1.12000, -0.64000, 0.00000], + [-16.82695, -4.33467, -1.12000, -0.62000, 0.00000], + [-16.86236, -4.24356, -1.12000, -0.60000, 0.00000], + [-16.89790, -4.15910, -1.12000, -0.58000, 0.00000], + [-16.93359, -4.08120, -1.12000, -0.56000, 0.00000], + [-16.96943, -4.00972, -1.12000, -0.54000, 0.00000], + [-17.00540, -3.94455, -1.12000, -0.52000, 0.00000], + [-17.04153, -3.88550, -1.12000, -0.50000, 0.00000], + [-17.99315, -3.83648, -1.12000, 0.00000, 0.00000], + [-14.59031, -11.45066, -1.10000, -1.12000, 0.00000], + [-14.63163, -11.39188, -1.10000, -1.12000, 0.00000], + [-14.65242, -11.33310, -1.10000, -1.10000, 0.00000], + [-14.67270, -11.31069, -1.10000, -1.12000, 0.00000], + [-14.69373, -11.25191, -1.10000, -1.10000, 0.00000], + [-14.71463, -11.17072, -1.10000, -1.08000, 0.00000], + [-14.71348, -11.21019, -1.10000, -1.12000, 0.00000], + [-14.73477, -11.15141, -1.10000, -1.10000, 0.00000], + [-14.75592, -11.07022, -1.10000, -1.08000, 0.00000], + [-14.75399, -11.09335, -1.10000, -1.12000, 0.00000], + [-14.77552, -11.03457, -1.10000, -1.10000, 0.00000], + [-14.79693, -10.95338, -1.10000, -1.08000, 0.00000], + [-14.79418, -10.96294, -1.10000, -1.12000, 0.00000], + [-14.81597, -10.90416, -1.10000, -1.10000, 0.00000], + [-14.83764, -10.82297, -1.10000, -1.08000, 0.00000], + [-14.85611, -10.76276, -1.10000, -1.10000, 0.00000], + [-14.87803, -10.68156, -1.10000, -1.08000, 0.00000], + [-14.89591, -10.61274, -1.10000, -1.10000, 0.00000], + [-14.91810, -10.53154, -1.10000, -1.08000, 0.00000], + [-14.93537, -10.45627, -1.10000, -1.10000, 0.00000], + [-14.95782, -10.37508, -1.10000, -1.08000, 0.00000], + [-14.97447, -10.29533, -1.10000, -1.10000, 0.00000], + [-14.99718, -10.21413, -1.10000, -1.08000, 0.00000], + [-15.03617, -10.05047, -1.10000, -1.08000, 0.00000], + [-15.07477, -9.88566, -1.10000, -1.08000, 0.00000], + [-15.11295, -9.72110, -1.10000, -1.08000, 0.00000], + [-15.15071, -9.55801, -1.10000, -1.08000, 0.00000], + [-15.18802, -9.39743, -1.10000, -1.08000, 0.00000], + [-15.22488, -9.24027, -1.10000, -1.08000, 0.00000], + [-15.23664, -9.16850, -1.10000, -1.10000, 0.00000], + [-15.26124, -9.08731, -1.10000, -1.08000, 0.00000], + [-15.36726, -8.65940, -1.10000, -1.08000, 0.00000], + [-15.40150, -8.52852, -1.10000, -1.08000, 0.00000], + [-15.40919, -8.48521, -1.10000, -1.10000, 0.00000], + [-15.43517, -8.40402, -1.10000, -1.08000, 0.00000] + +], dtype=np.double) diff --git a/test/problems/pointsForTest/mco_test6_points.py b/test/problems/pointsForTest/mco_test6_points.py new file mode 100644 index 00000000..4457d007 --- /dev/null +++ b/test/problems/pointsForTest/mco_test6_points.py @@ -0,0 +1,105 @@ +import numpy as np + +test_points = np.array([ + [0.00000, 1.00000, 0.00000, 0.00000], + [0.00100, 0.99997, 0.00100, 0.00000], + [0.00200, 0.99990, 0.00200, 0.00000], + [0.00300, 0.99977, 0.00300, 0.00000], + [0.00400, 0.99958, 0.00400, 0.00000], + [0.00500, 0.99935, 0.00500, 0.00000], + [0.00600, 0.99906, 0.00600, 0.00000], + [0.00700, 0.99873, 0.00700, 0.00000], + [0.00800, 0.99834, 0.00800, 0.00000], + [0.00900, 0.99790, 0.00900, 0.00000], + [0.01000, 0.99741, 0.01000, 0.00000], + [0.01100, 0.99688, 0.01100, 0.00000], + [0.01200, 0.99629, 0.01200, 0.00000], + [0.01300, 0.99566, 0.01300, 0.00000], + [0.01400, 0.99498, 0.01400, 0.00000], + [0.01500, 0.99425, 0.01500, 0.00000], + [0.01600, 0.99348, 0.01600, 0.00000], + [0.01700, 0.99267, 0.01700, 0.00000], + [0.01800, 0.99181, 0.01800, 0.00000], + [0.01900, 0.99091, 0.01900, 0.00000], + [0.02000, 0.98996, 0.02000, 0.00000], + [0.02100, 0.98898, 0.02100, 0.00000], + [0.02200, 0.98796, 0.02200, 0.00000], + [0.02300, 0.98690, 0.02300, 0.00000], + [0.02400, 0.98581, 0.02400, 0.00000], + [0.02500, 0.98468, 0.02500, 0.00000], + [0.02600, 0.98352, 0.02600, 0.00000], + [0.02700, 0.98232, 0.02700, 0.00000], + [0.02800, 0.98110, 0.02800, 0.00000], + [0.02900, 0.97984, 0.02900, 0.00000], + [0.03000, 0.97856, 0.03000, 0.00000], + [0.03100, 0.97726, 0.03100, 0.00000], + [0.03200, 0.97593, 0.03200, 0.00000], + [0.03300, 0.97457, 0.03300, 0.00000], + [0.03400, 0.97320, 0.03400, 0.00000], + [0.03500, 0.97181, 0.03500, 0.00000], + [0.03600, 0.97040, 0.03600, 0.00000], + [0.03700, 0.96897, 0.03700, 0.00000], + [0.03800, 0.96754, 0.03800, 0.00000], + [0.03900, 0.96609, 0.03900, 0.00000], + [0.04000, 0.96463, 0.04000, 0.00000], + [0.04100, 0.96316, 0.04100, 0.00000], + [0.04200, 0.96169, 0.04200, 0.00000], + [0.04300, 0.96021, 0.04300, 0.00000], + [0.04400, 0.95873, 0.04400, 0.00000], + [0.04500, 0.95726, 0.04500, 0.00000], + [0.04600, 0.95578, 0.04600, 0.00000], + [0.04700, 0.95431, 0.04700, 0.00000], + [0.04800, 0.95285, 0.04800, 0.00000], + [0.04900, 0.95139, 0.04900, 0.00000], + [0.05000, 0.94995, 0.05000, 0.00000], + [0.05100, 0.94851, 0.05100, 0.00000], + [0.05200, 0.94710, 0.05200, 0.00000], + [0.05300, 0.94569, 0.05300, 0.00000], + [0.05400, 0.94431, 0.05400, 0.00000], + [0.05500, 0.94295, 0.05500, 0.00000], + [0.05600, 0.94161, 0.05600, 0.00000], + [0.05700, 0.94029, 0.05700, 0.00000], + [0.05800, 0.93901, 0.05800, 0.00000], + [0.05900, 0.93775, 0.05900, 0.00000], + [0.06000, 0.93652, 0.06000, 0.00000], + [0.06100, 0.93532, 0.06100, 0.00000], + [0.06200, 0.93416, 0.06200, 0.00000], + [0.06300, 0.93304, 0.06300, 0.00000], + [0.06400, 0.93195, 0.06400, 0.00000], + [0.06500, 0.93090, 0.06500, 0.00000], + [0.06600, 0.92990, 0.06600, 0.00000], + [0.06700, 0.92894, 0.06700, 0.00000], + [0.06800, 0.92802, 0.06800, 0.00000], + [0.06900, 0.92716, 0.06900, 0.00000], + [0.07000, 0.92634, 0.07000, 0.00000], + [0.07100, 0.92557, 0.07100, 0.00000], + [0.07200, 0.92486, 0.07200, 0.00000], + [0.07300, 0.92420, 0.07300, 0.00000], + [0.07400, 0.92359, 0.07400, 0.00000], + [0.07500, 0.92305, 0.07500, 0.00000], + [0.07600, 0.92256, 0.07600, 0.00000], + [0.07700, 0.92213, 0.07700, 0.00000], + [0.07800, 0.92176, 0.07800, 0.00000], + [0.07900, 0.92145, 0.07900, 0.00000], + [0.08000, 0.92121, 0.08000, 0.00000], + [0.08100, 0.92104, 0.08100, 0.00000], + [0.08200, 0.92093, 0.08200, 0.00000], + [0.08300, 0.92089, 0.08300, 0.00000], + [0.25300, 0.91693, 0.25300, 0.00000], + [0.25400, 0.90999, 0.25400, 0.00000], + [0.25500, 0.90302, 0.25500, 0.00000], + [0.25600, 0.89601, 0.25600, 0.00000], + [0.25700, 0.88897, 0.25700, 0.00000], + [0.25800, 0.88191, 0.25800, 0.00000], + [0.25900, 0.87483, 0.25900, 0.00000], + [0.26000, 0.86774, 0.26000, 0.00000], + [0.26100, 0.86064, 0.26100, 0.00000], + [0.26200, 0.85353, 0.26200, 0.00000], + [0.26300, 0.84642, 0.26300, 0.00000], + [0.26400, 0.83932, 0.26400, 0.00000], + [0.26500, 0.83222, 0.26500, 0.00000], + [0.26600, 0.82514, 0.26600, 0.00000], + [0.26700, 0.81807, 0.26700, 0.00000], + [0.26800, 0.81103, 0.26800, 0.00000], + [0.26900, 0.80401, 0.26900, 0.00000] +], dtype=np.double) diff --git a/test/problems/pointsForTest/mco_test7_points.py b/test/problems/pointsForTest/mco_test7_points.py new file mode 100644 index 00000000..e30ae51b --- /dev/null +++ b/test/problems/pointsForTest/mco_test7_points.py @@ -0,0 +1,110 @@ +import numpy as np + +test_points = np.array([ + [0.98151, 0.00001, -0.57600, -0.57600, 0.00000], + [0.98082, 0.00030, -0.56000, -0.57600, 0.00000], + [0.98011, 0.00060, -0.56000, -0.57600, 0.00000], + [0.97936, 0.00090, -0.56000, -0.56000, 0.00000], + [0.97860, 0.00171, -0.54400, -0.56000, 0.00000], + [0.97782, 0.00252, -0.54400, -0.56000, 0.00000], + [0.97700, 0.00333, -0.54400, -0.54400, 0.00000], + [0.97617, 0.00465, -0.52800, -0.54400, 0.00000], + [0.97530, 0.00597, -0.52800, -0.54400, 0.00000], + [0.97441, 0.00728, -0.52800, -0.52800, 0.00000], + [0.97349, 0.00910, -0.51200, -0.52800, 0.00000], + [0.97254, 0.01092, -0.51200, -0.52800, 0.00000], + [0.97156, 0.01273, -0.51200, -0.51200, 0.00000], + [0.97056, 0.01504, -0.49600, -0.51200, 0.00000], + [0.96952, 0.01735, -0.49600, -0.51200, 0.00000], + [0.96845, 0.01966, -0.49600, -0.49600, 0.00000], + [0.96736, 0.02246, -0.48000, -0.49600, 0.00000], + [0.96623, 0.02525, -0.48000, -0.49600, 0.00000], + [0.96505, 0.02803, -0.48000, -0.48000, 0.00000], + [0.96386, 0.03130, -0.46400, -0.48000, 0.00000], + [0.96263, 0.03456, -0.46400, -0.48000, 0.00000], + [0.96135, 0.03781, -0.46400, -0.46400, 0.00000], + [0.96007, 0.04203, -0.44800, -0.48000, 0.00000], + [0.95871, 0.04526, -0.44800, -0.46400, 0.00000], + [0.95732, 0.04896, -0.44800, -0.44800, 0.00000], + [0.95591, 0.05313, -0.43200, -0.44800, 0.00000], + [0.95445, 0.05728, -0.43200, -0.44800, 0.00000], + [0.95294, 0.06141, -0.43200, -0.43200, 0.00000], + [0.95141, 0.06601, -0.41600, -0.43200, 0.00000], + [0.94983, 0.07058, -0.41600, -0.43200, 0.00000], + [0.94819, 0.07513, -0.41600, -0.41600, 0.00000], + [0.94653, 0.08013, -0.40000, -0.41600, 0.00000], + [0.94482, 0.08510, -0.40000, -0.41600, 0.00000], + [0.94305, 0.09004, -0.40000, -0.40000, 0.00000], + [0.94126, 0.09543, -0.38400, -0.40000, 0.00000], + [0.93941, 0.10077, -0.38400, -0.40000, 0.00000], + [0.93750, 0.10609, -0.38400, -0.38400, 0.00000], + [0.93556, 0.11183, -0.36800, -0.38400, 0.00000], + [0.93357, 0.11754, -0.36800, -0.38400, 0.00000], + [0.93151, 0.12321, -0.36800, -0.36800, 0.00000], + [0.92942, 0.12928, -0.35200, -0.36800, 0.00000], + [0.92728, 0.13532, -0.35200, -0.36800, 0.00000], + [0.92506, 0.14131, -0.35200, -0.35200, 0.00000], + [0.92282, 0.14770, -0.33600, -0.35200, 0.00000], + [0.92051, 0.15404, -0.33600, -0.35200, 0.00000], + [0.91813, 0.16033, -0.33600, -0.33600, 0.00000], + [0.91572, 0.16701, -0.32000, -0.33600, 0.00000], + [0.91325, 0.17363, -0.32000, -0.33600, 0.00000], + [0.91070, 0.18019, -0.32000, -0.32000, 0.00000], + [0.90812, 0.18713, -0.30400, -0.32000, 0.00000], + [0.90547, 0.19400, -0.30400, -0.32000, 0.00000], + [0.90274, 0.20081, -0.30400, -0.30400, 0.00000], + [0.89998, 0.20798, -0.28800, -0.30400, 0.00000], + [0.89715, 0.21508, -0.28800, -0.30400, 0.00000], + [0.89423, 0.22211, -0.28800, -0.28800, 0.00000], + [0.89129, 0.22948, -0.27200, -0.28800, 0.00000], + [0.88826, 0.23677, -0.27200, -0.28800, 0.00000], + [0.88516, 0.24400, -0.27200, -0.27200, 0.00000], + [0.88202, 0.25154, -0.25600, -0.27200, 0.00000], + [0.87880, 0.25901, -0.25600, -0.27200, 0.00000], + [0.87550, 0.26640, -0.25600, -0.25600, 0.00000], + [0.87216, 0.27410, -0.24000, -0.25600, 0.00000], + [0.86874, 0.28171, -0.24000, -0.25600, 0.00000], + [0.86523, 0.28924, -0.24000, -0.24000, 0.00000], + [0.86169, 0.29705, -0.22400, -0.24000, 0.00000], + [0.85806, 0.30477, -0.22400, -0.24000, 0.00000], + [0.85434, 0.31241, -0.22400, -0.22400, 0.00000], + [0.85060, 0.32032, -0.20800, -0.22400, 0.00000], + [0.84675, 0.32813, -0.20800, -0.22400, 0.00000], + [0.84281, 0.33586, -0.20800, -0.20800, 0.00000], + [0.83885, 0.34383, -0.19200, -0.20800, 0.00000], + [0.83480, 0.35170, -0.19200, -0.20800, 0.00000], + [0.83064, 0.35949, -0.19200, -0.19200, 0.00000], + [0.82646, 0.36750, -0.19200, -0.17600, 0.00000], + [0.82218, 0.37541, -0.17600, -0.19200, 0.00000], + [0.81779, 0.38322, -0.17600, -0.17600, 0.00000], + [0.81339, 0.39125, -0.16000, -0.17600, 0.00000], + [0.80889, 0.39917, -0.16000, -0.17600, 0.00000], + [0.80428, 0.40699, -0.16000, -0.16000, 0.00000], + [0.79976, 0.41531, -0.14400, -0.17600, 0.00000], + [0.79492, 0.42292, -0.14400, -0.16000, 0.00000], + [0.79008, 0.43072, -0.14400, -0.14400, 0.00000], + [0.78524, 0.43870, -0.14400, -0.12800, 0.00000], + [0.78028, 0.44657, -0.12800, -0.14400, 0.00000], + [0.77520, 0.45433, -0.12800, -0.12800, 0.00000], + [0.77013, 0.46226, -0.11200, -0.12800, 0.00000], + [0.76494, 0.47007, -0.11200, -0.12800, 0.00000], + [0.75964, 0.47777, -0.11200, -0.11200, 0.00000], + [0.75434, 0.48562, -0.09600, -0.11200, 0.00000], + [0.74893, 0.49336, -0.09600, -0.11200, 0.00000], + [0.74339, 0.50097, -0.09600, -0.09600, 0.00000], + [0.73800, 0.50898, -0.08000, -0.11200, 0.00000], + [0.73223, 0.51636, -0.08000, -0.09600, 0.00000], + [0.72647, 0.52387, -0.08000, -0.08000, 0.00000], + [0.72072, 0.53151, -0.06400, -0.08000, 0.00000], + [0.71486, 0.53903, -0.06400, -0.08000, 0.00000], + [0.70887, 0.54642, -0.06400, -0.06400, 0.00000], + [0.70291, 0.55393, -0.04800, -0.06400, 0.00000], + [0.69683, 0.56131, -0.04800, -0.06400, 0.00000], + [0.69062, 0.56856, -0.04800, -0.04800, 0.00000], + [0.68445, 0.57592, -0.03200, -0.04800, 0.00000], + [0.67815, 0.58315, -0.03200, -0.04800, 0.00000], + [0.67173, 0.59026, -0.03200, -0.03200, 0.00000], + [0.66535, 0.59745, -0.01600, -0.03200, 0.00000], + [0.65885, 0.60451, -0.01600, -0.03200, 0.00000], + [0.65222, 0.61145, -0.01600, -0.01600, 0.00000] +], dtype=np.double) diff --git a/test/problems/test_mco_problem.py b/test/problems/test_mco_problem.py new file mode 100644 index 00000000..7fdb48ba --- /dev/null +++ b/test/problems/test_mco_problem.py @@ -0,0 +1,73 @@ +import math +import unittest +import numpy as np +from iOpt.trial import FunctionValue +from iOpt.trial import FunctionType +from iOpt.trial import Point +from problems.mco_test1 import mco_test1 +from problems.mco_test3 import mco_test3 +from problems.mco_test5 import mco_test5 +from problems.mco_test6 import mco_test6 +from problems.mco_test7 import mco_test7 + +from test.problems.pointsForTest import mco_test1_points, mco_test3_points, mco_test5_points, mco_test6_points,\ + mco_test7_points + + + +class TestMco(unittest.TestCase): + """setUp method is overridden from the parent class TestHill""" + + # def test_Mco1(self): + # problem = mco_test1() + # sample = mco_test1_points + # self.Calculate(problem, sample) + # + # def test_Mco3(self): + # problem = mco_test3() + # sample = mco_test3_points + # self.Calculate(problem, sample) + + # def test_Mco5(self): # в задачке явно что-то не так (в списке одинаковые точки у которых разные значения) + # problem = mco_test5() + # sample = mco_test5_points + # self.Calculate(problem, sample) + + # def test_Mco6(self): + # problem = mco_test6() + # sample = mco_test6_points + # self.Calculate(problem, sample) + + # def test_Mco7(self): # тут тоже что-то не так + # problem = mco_test7() + # sample = mco_test7_points + # self.Calculate(problem, sample) + + def Calculate(self, problem, Sample): + for i in range(0, len(Sample.test_points)): + fv_point = [] + for j in range(problem.number_of_objectives, problem.number_of_objectives+problem.dimension): + fv_point.append(np.double(Sample.test_points[i][j])) + + point = Point(fv_point, []) + for j in range(0, problem.number_of_objectives): + function_value = FunctionValue() + function_value.type = FunctionType.OBJECTIV + function_value.functionID = j + + function_value = problem.calculate(point, function_value) + + # if j==1: + # print(function_value.value, np.double(Sample.test_points[i][j])) + + self.assertAlmostEqual(function_value.value, + np.double(Sample.test_points[i][j]), 5) + + print(problem.name, "is OK") + + + + +"""Executing the tests in the above test case class""" +if __name__ == "__main__": + unittest.main()