Обсуждение статьи "Популяционные алгоритмы оптимизации: Алгоритм растущих деревьев (Saplings Sowing and Growing up — SSG)" - страница 12

 
Andrey Dik #:

да, очень интересный организм.))

но, слизевик использует всего лишь 2 измерения, а с двумя измерениями справляются даже простейшие АО. как он будет себя вести в 1000 измерений - большой вопрос, ведь с ростом количества измерений сложность задачи растет нелинейно.

Муравьиный же тоже, но обобщают для многомерных случаев 

Вот у чатгпт спросил, не знаю оно или нет :)

Алгоритм оптимизации "слизевик" (Slime Mould Algorithm) - это эвристический метод оптимизации, основанный на поведении слизней-слизевиков. Этот алгоритм был разработан Кьяро Д'Амброзио и имеет отношение к группе "натуральных" алгоритмов оптимизации.


Суть алгоритма заключается в размещении "слизня" в конкретной точке и наблюдении, как он распространяется вокруг этой точки, в поисках максимальной пищи. В процессе этого алгоритма, слизень оставляет за собой след, который постепенно испаряется. Чем больше след оставлен в какой-то области, тем выше вероятность того, что другой "слизень" примет этот след как путь к более высокой концентрации пищи.


В контексте оптимизации, это поведение слизня используется для поиска оптимальных решений в пространствах параметров. Например, можно использовать этот алгоритм для поиска минимального значения функции в заданных пределах параметров.


Преимуществами этого алгоритма являются его простота и способность быстро сходиться к оптимальным решениям в многомерных пространствах. Однако, он также может иметь проблемы со сходимостью к оптимальному решению в более сложных и нелинейных задачах.

 
Maxim Dmitrievsky #:
Муравьиный же тоже, но обобщают для многомерных случаев 

а что муравьиный? с ростом мерности сходимость муравьиного падает, быстро падает. так же ведут себя в общем все алгоритмы. очень зависит от стратегии поиска, а стратегию слизевика мы не знаем)))

падение сходимости медленнее чем рост сложности с увеличением мерности - рассматриваю как масштабируемость AO. способность к масштабированию зависит от типа функции, разные алго масштабируются на разных функциях по разному.

 
Maxim Dmitrievsky #:

Вот у чатгпт спросил, не знаю оно или нет :)

Алгоритм оптимизации "слизевик" (Slime Mould Algorithm) - это эвристический метод оптимизации, основанный на поведении слизней-слизевиков. Этот алгоритм был разработан Кьяро Д'Амброзио и имеет отношение к группе "натуральных" алгоритмов оптимизации.

Суть алгоритма заключается в размещении "слизня" в конкретной точке и наблюдении, как он распространяется вокруг этой точки, в поисках максимальной пищи. В процессе этого алгоритма, слизень оставляет за собой след, который постепенно испаряется. Чем больше след оставлен в какой-то области, тем выше вероятность того, что другой "слизень" примет этот след как путь к более высокой концентрации пищи.

В контексте оптимизации, это поведение слизня используется для поиска оптимальных решений в пространствах параметров. Например, можно использовать этот алгоритм для поиска минимального значения функции в заданных пределах параметров.

Преимуществами этого алгоритма являются его простота и способность быстро сходиться к оптимальным решениям в многомерных пространствах. Однако, он также может иметь проблемы со сходимостью к оптимальному решению в более сложных и нелинейных задачах.

ого, как интересно. поищу этот алго, конечно интересно его разобрать. и собрать)))

 
как руки дойдут - сделаю сравнительный график сходимости всех известных мне алго от размерности задачи, три типа задач. эта замарочка представляется мне очень трудоемкой
 
Andrey Dik #:

ого, как интересно. поищу этот алго, конечно интересно его разобрать. и собрать)))

Вот пример реализации алгоритма слизевик на языке программирования MQL:


```

double slimeMouldAlgorithm(double(*f)(double[]), double x[], int n, double LB[], double UB[], int maxIter, int N)

{

    const double k = 0.1; // коэффициент испарения следа

    const double stepSize = 0.001; // размер шага движения "слизня"

    double trail[N]; // массив следов каждой частицы

    double bestTrail[N]; // массив лучшего следа

    double bestFitness = DBL_MAX; // начальное значение лучшей фитнес-функции

    double bestX[N]; // массив значений параметров соответствующих лучшему следу

    for (int i = 0; i < N; i++) {

        for (int j = 0; j < n; j++) {

            x[j] = LB[j] + (UB[j] - LB[j]) * (double)rand() / RAND_MAX; // расставляем "слизней" случайно в заданном диапазоне параметров

        }

        trail[i] = f(x); // вычисляем значение фитнес-функции для этих параметров

        if (trail[i] < bestFitness) { // если значение фитнес-функции лучше текущего лучшего значения, сохраняем его как новый лучший

            bestFitness = trail[i];

            memcpy(bestX, x, sizeof(bestX)); // копируем значения найденных параметров в массив лучших значений

            memcpy(bestTrail, trail, sizeof(bestTrail)); // копируем значение функций для найденных параметров в массив лучших значений функций

        }

    }

    for (int iter = 0; iter < maxIter; iter++) { // цикл по числу итераций

        for (int i = 0; i < N; i++) {

            double r[n], d[n];

            for (int j = 0; j < n; j++) {

                r[j] = (double)rand() / RAND_MAX - 0.5; // случайный вектор приращения

                d[j] = r[j] * stepSize * (UB[j] - LB[j]); // вычисляем ширину шага

                x[j] += d[j]; // прибавляем шаг к параметру

                if (x[j] < LB[j]) { // если параметр выходит за пределы диапазона, оставляем его на границе

                    x[j] = LB[j];

                } else if (x[j] > UB[j]) {

                    x[j] = UB[j];

                }

            }

            double newTrail = f(x); // вычисляем значение функции для новых параметров

            if (newTrail <= trail[i]) { // если значения функции улучшилось или не изменилось, сохраняем новые параметры и значение функции

                memcpy(bestX, x, sizeof(bestX)); // копируем новые параметры в массив лучших значений параметров

                memcpy(bestTrail, &newTrail, sizeof(newTrail)); // копируем новое значение функции в массив лучших значений функций

                trail[i] = newTrail; // сохраняем значение функции для новых параметров в массиве значений функций для всех "слизней"

                if (bestTrail[i] < bestFitness) { // проверяем, является ли лучшее решение на данный момент лучше текущего лучшего

                    bestFitness = bestTrail[i];

                }

            } else { // если значения функции ухудшилось, возвращаемся к старым параметрам

                memcpy(x, bestX, sizeof(bestX));

                trail[i] = bestTrail[i];

            }

        }

        for (int i = 0; i < N; i++) {

            trail[i] *= (1.0 - k); // испаряем след слизня, чтобы избежать застревания в локальном максимуме

        }

    }

    return bestFitness;

}

```


Этот код использует случайные значения выбранных параметров как начальную точку, затем последовательно обрабатывает каждую частицу. Для каждой частицы он генерирует случайный вектор приращения, вычисляет размер шага и прибавляет его к каждому параметру. Затем он вычисляет значение функции для новых параметров и сохраняет его, если значение уменьшается или остается таким же. По завершении каждого цикла он испаряет следы слизня, чтобы избежать застревания в локальном максимуме.


Там наверное подкорректировать придется 😀 гпт выдал

 
Корректировка:

Вы правы, в MQL нет функции `memcpy`. Для копирования значений из одной переменной в другую можно воспользоваться оператором присваивания `=`. Вот пример измененного кода без использования функции `memcpy`:


```

double slimeMouldAlgorithm(double(*f)(double[]), double x[], int n, double LB[], double UB[], int maxIter, int N)

{

    const double k = 0.1; // коэффициент испарения следа

    const double stepSize = 0.001; // размер шага движения "слизня"

    double trail[N]; // массив следов каждой частицы

    double bestTrail[N]; // массив лучшего следа

    double bestFitness = DBL_MAX; // начальное значение лучшей фитнес-функции

    double bestX[N]; // массив значений параметров соответствующих лучшему следу

    for (int i = 0; i < N; i++) {

        for (int j = 0; j < n; j++) {

            x[j] = LB[j] + (UB[j] - LB[j]) * (double)rand() / RAND_MAX; // расставляем "слизней" случайно в заданном диапазоне параметров

        }

        trail[i] = f(x); // вычисляем значение фитнес-функции для этих параметров

        if (trail[i] < bestFitness) { // если значение фитнес-функции лучше текущего лучшего значения, сохраняем его как новый лучший

            bestFitness = trail[i];

            for (int j = 0; j < n; j++) {

                bestX[j] = x[j]; // копируем значения найденных параметров в массив лучших значений

            }

            bestTrail[i] = trail[i]; // копируем значение функции для найденных параметров в массив лучших значений функций

        }

    }

    for (int iter = 0; iter < maxIter; iter++) { // цикл по числу итераций

        for (int i = 0; i < N; i++) {

            double r[n], d[n];

            for (int j = 0; j < n; j++) {

                r[j] = (double)rand() / RAND_MAX - 0.5; // случайный вектор приращения

                d[j] = r[j] * stepSize * (UB[j] - LB[j]); // вычисляем ширину шага

                x[j] += d[j]; // прибавляем шаг к параметру

                if (x[j] < LB[j]) { // если параметр выходит за пределы диапазона, оставляем его на границе

                    x[j] = LB[j];

                } else if (x[j] > UB[j]) {

                    x[j] = UB[j];

                }

            }

            double newTrail = f(x); // вычисляем значение функции для новых параметров

            if (newTrail <= trail[i]) { // если значения функции улучшилось или не изменилось, сохраняем новые параметры и значение функции

                for (int j = 0; j < n; j++) {

                    bestX[j] = x[j]; // копируем новые параметры в массив лучших значений параметров

                }

                bestTrail[i] = newTrail; // копируем новое значение функции в массив лучших значений функций

                trail[i] = newTrail; // сохраняем значение функции для новых параметров в массиве значений функций для всех "слизней"

                if (bestTrail[i] < bestFitness) { // проверяем, является ли лучшее решение на данный момент лучше текущего лучшего

                    bestFitness = bestTrail[i];

                }

            } else { // если значения функции ухудшилось, возвращаемся к старым параметрам

                for (int j = 0; j < n; j++) {

                    x[j] = bestX[j];

                }

                trail[i] = bestTrail[i];

            }

        }

        for (int i = 0; i < N; i++) {

            trail[i] *= (1.0 - k); // испаряем след слизня, чтобы избежать застревания в локальном максимуме

        }

    }

    return bestFitness;

}

``` 


Как видите, мы просто используем циклы для копирования значений массивов поэлементно.

 


всё то знает эта железяка...))

в общем случае, наверное, можно доверится железяке по выбору алго под задачу, но я бы лучше заглянул в свою рейтинговую таблицу))

 
Maxim Dmitrievsky #:

```

double slimeMouldAlgorithm(double(*f)(double[]), double x[], int n, double LB[], double UB[], int maxIter, int N)

нужно будет его ещё разбить по схеме, как сделаны все алго в статьях. в таком виде он неюзабелен.

 
Andrey Dik #:

нужно будет его ещё разбить по схеме, как сделаны все алго в статьях. в таком виде он неюзабелен.

Попробуй через чат, интересно вывезет ли такую задачу :) у меня токены кончились, так балуюсь иногда. Скормить ему пример статьи и чтобы стиль соблюдал. Кстати, отличный копеечный стартап - такой бот в телеге.
 
Maxim Dmitrievsky #:
Попробуй через чат, интересно вывезет ли такую задачу :) у меня токены кончились, так балуюсь иногда. Скормить ему пример статьи и чтобы стиль соблюдал. Кстати, отличный копеечный стартап - такой бот в телеге.

уже попробовал. к сожалению, а может быть и к счастью, бот не генерирует новой информации, а ту, что общедоступна, часто искажает. думаю это связано с механизмами интерполяции информации. привирает, придумывает несуществующие аббревиатуры алгоритмов, даже имена авторов придумывает на ходу и даты появления алгоритма)). очень осторожно нужно относится к такой информации.

как помощник в редактировании текста, стилистических правок и получения справки при написании статей - да, незаменимый помощник.

Причина обращения: