#include "opt_alg.h"
#if LAB_NO > 1
double *expansion(double x0, double d, double alpha, int Nmax, matrix *ud, matrix *ad)
{
double *p = new double[2];
solution X0(x0), X1(x0 + d);
X0.fit_fun(ud, ad);
X1.fit_fun(ud, ad);
if (X0.y == X1.y)
{
p[0] = X0.x();
p[1] = X1.x();
if (ud != nullptr)
{
double **Array = new double *[1];
//Array[0] = new double[] { x0, p[0], p[1], (double)solution::f_calls };
ud->add_row(matrix(1, 4, Array));
}
return p;
}
if (X0.y < X1.y)
{
d *= -1;
X1.x = X0.x + d;
X1.fit_fun(ud, ad);
if (X0.y <= X1.y)
{
p[0] = X1.x();
p[1] = X0.x() - d;
//if (ud != nullptr)
//{
// double** Array = new double* [1];
// //Array[0] = new double[] { x0, p[0], p[1], (double)solution::f_calls };
// ud->add_row(matrix(1, 4, Array));
//}
return p;
}
}
solution X2;
int i = 1;
while (true)
{
X2.x = x0 + pow(alpha, i) * d; //x0 - double(faktyczny punkt startowy)
X2.fit_fun(ud, ad);
//if (ud != nullptr)
//{
// double** Array = new double* [1];
// //Array[0] = new double[] { x0, X0.x(), X2.x(), (double)solution::f_calls };
// ud->add_row(matrix(1, 4, Array));
//}
if (X2.y >= X1.y || solution::f_calls > Nmax)
break;
X0 = X1;
X1 = X2;
++i;
}
d > 0 ? p[0] = X0.x(), p[1] = X2.x() : (p[0] = X2.x(), p[1] = X0.x());
return p;
}
solution fib(double a, double b, double epsilon, matrix *ud, matrix *ad)
{
int n = static_cast(ceil(log2(sqrt(5) * (b - a) / epsilon) / log2((1 + sqrt(5)) / 2)));
int *F = new int[n]{1, 1};
for (int i = 2; i < n; ++i)
F[i] = F[i - 2] + F[i - 1];
solution A(a), B(b), C, D;
C.x = B.x - 1.0 * F[n - 2] / F[n - 1] * (B.x - A.x);
D.x = A.x + B.x - C.x;
C.fit_fun(ud, ad);
D.fit_fun(ud, ad);
for (int i = 0; i <= n - 3; ++i)
{
if (C.y < D.y)
B = D;
else
A = C;
C.x = B.x - 1.0 * F[n - i - 2] / F[n - i - 1] * (B.x - A.x);
D.x = A.x + B.x - C.x;
C.fit_fun(ud, ad);
D.fit_fun(ud, ad);
#if LAB_NO == 2 && LAB_PART == 2
if (ud != nullptr)
{
(*ud).add_row((B.x - A.x)());
}
#endif
}
return C;
}
solution lag(double a, double b, double epsilon, double gamma, int Nmax, matrix *ud, matrix *ad)
{
solution A(a), B(b), C, D, D_old(a);
C.x = (a + b) / 2;
A.fit_fun(ud, ad);
B.fit_fun(ud, ad);
C.fit_fun(ud, ad);
double l, m;
while (true)
{
l = A.y(0) * (pow(B.x(0), 2) - pow(C.x(0), 2)) + B.y(0) * (pow(C.x(0), 2) - pow(A.x(0), 2)) + C.y(0) * (pow(A.x(0), 2) - pow(B.x(0), 2));
m = A.y(0) * (B.x(0) - C.x(0)) + B.y(0) * (C.x(0) - A.x(0)) + C.y(0) * (A.x(0) - B.x(0));
if (m <= 0) //check this: Ok, not positive
{
C.x = NAN;
C.y = NAN;
return C;
}
D.x = 0.5 * l / m;
D.fit_fun(ud, ad);
if (A.x <= D.x && D.x <= C.x) // a --- d ---- c ---- b
{
if (D.y < C.y)
{
B = C; // a --- c --- b
C = D;
}
else
{
A = D; //a -- c --- b
}
}
else if (C.x <= D.x && D.x <= B.x)
{
if (D.y < C.y)
{
A = C;
C = D;
}
else
{
B = D;
}
}
else
{
// punkt poza przedzialem ab
C.x = NAN;
C.y = NAN;
return C;
}
#if LAB_NO == 2 && LAB_PART == 2
if (ud != nullptr)
{
(*ud).add_row((B.x - A.x)()); // jakie� dane usera
}
#endif
if (B.x - A.x < epsilon || abs(D.x() - D_old.x()) < gamma || solution::f_calls > Nmax)
{
return C;
}
D_old = D;
}
}
#endif
#if LAB_NO > 2
solution HJ(matrix x0, double s, double alpha, double epsilon, int Nmax, matrix *ud, matrix *ad) //jesli etap probny konczy sie porazka to zmniejszamy s i zaczynamy szukac blizej srodka - zmiejszyc krok
{ // kryterium stopu - osiagniecie dlugosci kroku mniejszej niz episilon - jesli jest to na odlegosc mniejszej niz epsilon nie ma mniejszej wartosci | alfa < episolon ===> koniec
solution XB(x0), XB_old, X; //XB - baza, XB_old - stara baza - odbicie symetryczne starej bazy wzgledem nowej bazy
XB.fit_fun(ud, ad);
if (alpha >= 1)
{
// alpha ma zmniejszaÄ krok
throw "Alpha shouldn't be more than 1";
}
while (true)
{
X = HJ_trial(XB, s, ud, ad); //etap próbny
if (X.y < XB.y) //jesli konzcy sie sukcesem to kolejna petla, gdy etap probny zakonczyl sie sukcesem
{
while (true) // petla sukcesywnie wykonuje etapy robocze
{
XB_old = XB; //stara baza to XB, X_old na wykÅÄ
dzie jest z podkreÅleniem
XB = X; //XB to jest X
#if LAB_NO == 3 && LAB_PART == 2
if (ud != nullptr)
{
(*ud).add_row(trans(XB.x));
}
#endif
X.x = 2 * XB.x - XB_old.x; //Odbicie symetryczne xold przez xb
X.fit_fun(ud, ad);
X = HJ_trial(X, s, ud, ad); //etap probny w etpapie roboczym, z punktu x uruchamiam etap probny
if (X.y >= XB.y)
{
break; //przerwe wykonywanie etapow roboczych gdy X bedzie gorszy niz Xb
}
if (solution::f_calls > Nmax)
{
return XB; //konczy caly algorytm, gdy liczba wywowal funkcji celu za duza
}
}
}
else
{
s *= alpha; //redukujemy dlugosc kroku, alfa zawsze <1
}
if (s < epsilon || solution::f_calls > Nmax) //sprawdzamy kryteria stopu
{
return XB;
}
}
}
// Póbkowanie - etap próbnya
solution HJ_trial(solution XB, double s, matrix *ud, matrix *ad) //moze zwrocic ten sam punkt albo lepszy
{
int n = get_dim(XB); //sprawdzamy rozmiar problemu
matrix D = ident_mat(n); //macierz zawierajÄ
ca kierunki (macierz jednostkowa)
solution X; //rozwiÄ
zanie X
for (int i = 0; i < n; ++i) //petla po kazdym kierunku
{
X.x = XB.x + s * D[i]; //XB + s w kierunku D
X.fit_fun(ud, ad); //wartoÅÄ funkcji celu w tym punkcie
if (X.y < XB.y) //jezeli ten punkt jest lepszy
{
XB = X; //to w tym momencie siÄ przesuwamy
}
else
{
X.x = XB.x - s * D[i]; //jesli nie jest lepszy - jest gorszy to stawiamy punkt trzeci z innej strony
X.fit_fun(ud, ad); //krok w tym samym kierunku a przeciwnym zwrocie ^ ^ ^
if (X.y < XB.y) //jesli pomaga to sie przesuwamy
{
// Ważne silne nierównoÅci
XB = X;
}
} // jesli nie to zostajemy w tym samym punkcie
}
return XB;
}
//s0 matrix - dla kadzego kroku oddzielna dlugosc kroku, //alhpa, beta - zwiekszanie/zmniejszanie dlugosci kroku
solution Rosen(matrix x0, matrix s0, double alpha, double beta, double epsilon, int Nmax, matrix *ud, matrix *ad) //w tej metodzie tylko wylacznie etap probny, wystepuje sytuacje w ktorej zmienamy kierunki, moze byc sytuacja ze wykonujemy obwod
{ // zwiekszamy i zmniejszamy dlugosc kroku, w HJ tylko zmniejszamy, | RS dlugosc korku zawsze inna
solution X(x0), Xt; //xt - punkt tymczasowy
int n = get_dim(X); //ilosc kierunkow - wymiar probleu
matrix l(n, 1), p(n, 1), s(s0), D = ident_mat(n); //macierz kierunkow, lambda - sumaryczne przesuniecie(l) - dla kazdego kroku oddzielnie, p - wektor wartosci 0,1,2,3... - liczy ile bylo porazek w danym kierunku, s - macierz dlugosci krokow kierunkow, D - kierunki
X.fit_fun(ud, ad);
while (true)
{
for (int i = 0; i < n; ++i) //proba w kazdym kierunku
{
Xt.x = X.x + s(i) * D[i];
Xt.fit_fun(ud, ad);
if (Xt.y < X.y) //jesli punkt lepszy
{
X = Xt; //dodaje do lambdy dlugosc kroku
l(i) += s(i); //zwiekszam lambde o s
s(i) *= alpha; //zwiekszam s, wazna kolejnosc, aplha powinna byc wieksza od 1
}
else
{
++p(i);
s(i) *= -beta; //zmniejszam dlugosc kroku
}
}
#if LAB_NO == 3 && LAB_PART == 2
if (ud != nullptr)
{
(*ud).add_row(trans(X.x));
}
#endif
bool change = true;
for (int i = 0; i < n; ++i) //zmiana bazy kierunkow, obracamy wektory
if (l(i) == 0 || p(i) == 0) //obrot wykonujemy jezeli w kazdym kierunku jest przesuniecie i w kazdym kierunku jest porazka, wszystkie p musza byc mniejsze niz 0 i wwszystkie presuniecia(l) mniejsze od 0
{
change = false;
break;
}
if (change) // nowe kierunki zaleza od starych kierunkow i l, musza byc prostopadle, wektory tych kierunkow musza byc znormlanizowane(dlugosc 1), uzywamy ortonoralizacji G-S,
{
matrix Q(n, n), v(n, 1); // wyzerowane, v wektor pionowy, macierz trójkÄ
tna dolna zawierajÄ
ca wartoÅci lambd
for (int i = 0; i < n; ++i)
{
for (int j = 0; j <= i; ++j) // wypelnianie macierzy Q lambdami
{
Q(i, j) = l(i);
}
}
Q = D * Q;
v = Q[0] / norm(Q[0]); //pierwsza kolumna podzielona przez norme
D.set_col(v, 0); //wsatawiamy do macierzy D jako kierunek piewrszy - kolumne zerowa
for (int i = 1; i < n; ++i) // nastepne kierunki liczmy w petli
{
matrix temp(n, 1);
for (int j = 0; j < i; ++j)
{
temp = temp + trans(Q[i]) * D[j] * D[j]; //transponowana kolumna j razy D(kierunki) ktore sa juz policzone
}
v = (Q[i] - temp) / norm(Q[i] - temp);
D.set_col(v, i);
} //koniec obrotu, wszystkie nowe kierunki
s = s0; //zerujemy s
l = matrix(n, 1); //zerujemy lambdy
p = matrix(n, 1); //zerujemy porazki
}
double max_s = abs(s(0));
for (int i = 1; i < n; ++i) //kryterkium kroku gdy jedno z s za male/duze abs
{
if (max_s < abs(s(i)))
{
max_s = abs(s(i));
}
}
if (max_s < epsilon || solution::f_calls > Nmax)
{
return X;
}
}
}
#endif
#if LAB_NO > 3
solution pen(matrix x0, double c0, double dc, double epsilon, int Nmax, matrix *ud, matrix *ad) //funkcja kary
{
double alpha = 1, beta = 0.5, gamma = 2, delta = 0.5, s = 0.5;
solution X(x0), X1;
matrix c(2, new double[2]{c0, dc}); // c0 - waga przy karze dc - odpowiada za wybor funkcji kary; zew, wew ; wysyÅana jak ad
while (true)
{
X1 = sym_NM(X.x, s, alpha, beta, gamma, delta, epsilon, Nmax, ud, &c); //metoda symplex, odpal metode optymalizacji bez ograniczeÅ
if ((norm(X.x - X1.x) < epsilon) || solution::f_calls > Nmax) //gdy przestanie sie zmieniac lub max liczba iteracji
return X1;
c(0) *= dc;
X = X1; //rozpoczynamy symulacje dla zmienionej wartosci- punktu ktory znalezlismy
}
}
///
/// sympleks
///
/// pkt poczatkowe
///
/// Przy odbiciu
/// zawezenie
/// ekspansja
/// dedukcja
///
///
///
///
///
solution sym_NM(matrix x0, double s, double alpha, double beta, double gamma, double delta, double epsilon, int Nmax, matrix *ud, matrix *ad)
{
int n = get_len(x0);
matrix D = ident_mat(n); //wektory w macierzy D
int N = n + 1; // liczba wierzcholkow symleksu; sympleks iloÅc zmiennych + 1
solution *S = new solution[N]; //symplex
S[0].x = x0;
S[0].fit_fun(ud, ad);
for (int i = 1; i < N; ++i)
{
S[i].x = S[0].x + s * D[i - 1];
S[i].fit_fun(ud, ad);
}
solution PR, PE, PN; //reflected, ecspansed, narrowed
matrix pc; //srodek ciezkosci sympleksu
int i_min, i_max;
while (true)
{
i_min = i_max = 0;
for (int i = 1; i < N; ++i)
{
if (S[i_min].y > S[i].y)
i_min = i;
if (S[i_max].y < S[i].y)
i_max = i;
}
pc = matrix(n, 1);
for (int i = 0; i < N; ++i)
if (i != i_max)
pc = pc + S[i].x;
pc = pc / (N - 1); //liczenie srodka c; albo n
PR.x = pc + alpha * (pc - S[i_max].x); //odbicie
PR.fit_fun(ud, ad);
if (S[i_min].y < PR.y && PR.y < S[i_max].y)
S[i_max] = PR;
else if (PR.y < S[i_min].y)
{
PE.x = pc + gamma * (PR.x - pc);
PE.fit_fun(ud, ad);
if (PE.y < PR.y) //aceptujemy odbicie, ackeptujemy ten ktory sprawia ze symplex bd mniejsz
S[i_max] = PE;
else
S[i_max] = PR;
}
else
{
PN.x = pc + beta * (S[i_max].x - pc);
PN.fit_fun(ud, ad);
if (PN.y < S[i_max].y)
S[i_max] = PN;
else
{
for (int i = 0; i < N; ++i)
if (i != i_min)
{
S[i].x = delta * (S[i].x + S[i_min].x);
S[i].fit_fun(ud, ad);
}
}
}
double max_s = norm(S[i_min].x - S[0].x); //odleglosc pomiedzy wierzcholkiem 0 i minimalnym
for (int i = 1; i < N; ++i) //liczymy najdluzsza krawedz symplexu
if (max_s < norm(S[i_min].x - S[i].x))
max_s = norm(S[i_min].x - S[i].x);
if (max_s < epsilon || solution::f_calls > Nmax) //kryteria stopu
return S[i_min];
}
}
#endif
#if LAB_NO > 4
solution SD(matrix x0, double h0, double epsilon, int Nmax, matrix *ud, matrix *ad) // punkt startowy, dlugosc kroku(jesli zmiennokrokowa <0)
{
int n = get_len(x0); // rozmiar problemu
solution X, X1; // rozwiazania
X.x = x0; // punkt startowy
matrix d(n, 1), *P = new matrix[2]; // okreslenie kierunku
solution h; // dlugosc kroku ktora wyznaczamy
double *ab; // przedzial ab - aby podzielic ekspansje
while (true)
{
X.grad(); // liczymy gradient
d = -X.g; // kierunek najszybszego spadku
if (h0 < 0) //jestli to metoda zmiennokrokowa - znajdujemy dlugosc kroku
{
P[0] = X.x; // P zawiera X ora d - kierunek
P[1] = d;
ab = expansion(0, 1, 1.2, Nmax, ud, P); // wywolujemy metode ekspansji, P jako ad(wsk)
h = golden(ab[0], ab[1], epsilon, Nmax, ud, P);
X1.x = X.x + h.x * d; // przesuwamy sie
}
else // stalokrokowa
X1.x = X.x + h0 * d;
#if LAB_NO == 5 && LAB_PART == 2
(*ud).add_row(trans(X1.x));
#endif
if (norm(X.x - X1.x) < epsilon || solution::f_calls > Nmax || solution::g_calls > Nmax) // kryterium stopu
{
X1.fit_fun(ud, ad);
return X1;
}
X = X1; // przesuwamy sie jesli nie ma konca
}
}
solution CG(matrix x0, double h0, double epsilon, int Nmax, matrix *ud, matrix *ad)
{
int n = get_len(x0);
solution X, X1;
X.x = x0;
matrix d(n, 1), *P = new matrix[2];
solution h;
double *ab, beta;
X.grad(); // liczymy gradient
d = -X.g; // pierwszy gradient liczymy inaczej niż resztÄ, stÄ
d przed pÄtlÄ
while (true)
{
if (h0 < 0)
{
P[0] = X.x; //wysylamy P do fit_fun jako ad, potrzebne do g(alfa); wysylamy P do fit_fun jako ad, potrzebne do g(alfa)
P[1] = d;
ab = expansion(0, 1, 1.2, Nmax, ud, P); //przedziaÅ poczÄ
tkowy - metoda ekspansji
h = golden(ab[0], ab[1], epsilon, Nmax, ud, P); //liczymy za pomocÄ
zÅotego podziaÅu
X1.x = X.x + h.x * d;
}
else // stalokrokowa
{
X1.x = X.x + h0 * d;
}
#if LAB_NO == 5 && LAB_PART == 2
(*ud).add_row(trans(X1.x));
#endif
if (solution::f_calls > Nmax || solution::g_calls > Nmax || norm(X1.x - X.x) < epsilon) //kiedy siÄ zatrzymaÄ
{
X1.fit_fun(ud, ad);
return X1;
}
X1.grad();
beta = pow(norm(X1.g), 2) / pow(norm(X.g), 2);
d = -X1.g + beta * d; // nowy kierunek
X = X1; // zaczynamy z nowego punktu
}
}
solution Newton(matrix x0, double h0, double epsilon, int Nmax, matrix *ud, matrix *ad)
{
int n = get_len(x0);
solution X, X1;
X.x = x0;
matrix d(n, 1), *P = new matrix[2];
solution h;
double *ab;
while (true)
{
X.grad(); // liczymy gradient
X.hess(); // liczymy hesian
d = -inv(X.H) * X.g; // kierunek d
if (h0 < 0) //jestli to metoda zmiennokrokowa - znajdujemy dlugosc kroku
{
P[0] = X.x; // P zawiera X ora d - kierunek
P[1] = d;
ab = expansion(0, 1, 1.2, Nmax, ud, P); // wywolujemy metode ekspansji, P jako ad(wsk)
h = golden(ab[0], ab[1], epsilon, Nmax, ud, P);
X1.x = X.x + h.x * d; // przesuwamy sie
}
else // stalokrokowa
X1.x = X.x + h0 * d;
#if LAB_NO == 5 && LAB_PART == 2
(*ud).add_row(trans(X1.x));
#endif
if (norm(X.x - X1.x) < epsilon || solution::f_calls > Nmax || solution::g_calls > Nmax) // kryterium stopu
{
X1.fit_fun(ud, ad);
return X1;
}
X = X1; // przesuwamy sie jesli nie ma konca
}
}
solution golden(double a, double b, double epsilon, int Nmax, matrix *ud, matrix *ad) // metoda zlotego podzialu
{
double alfa = (sqrt(5) - 1) / 2;
solution A, B, C, D;
A.x = a; // poczatek
B.x = b; // koniec przedzialu
C.x = B.x - alfa * (B.x - A.x);
C.fit_fun(ud, ad);
D.x = A.x + alfa * (B.x - A.x);
D.fit_fun(ud, ad);
while (true)
{
if (C.y < D.y)
{
B = D;
D = C;
C.x = B.x - alfa * (B.x - A.x); // PW WHY ? Checkout: d6d1e5c74ab642797df877050f7274ca9d8fdfe6
C.fit_fun(ud, ad);
}
else
{
A = C;
C = D;
D.x = A.x + alfa * (B.x - A.x);
D.fit_fun(ud, ad);
}
if (B.x - A.x < epsilon || solution::f_calls > Nmax) //kryterium stopu
{
A.x = (A.x + B.x) / 2; //jeÅli stop to zwracamy Årodek pomiÄdzy a i b
A.fit_fun(ud, ad);
return A;
}
}
}
#endif
#if LAB_NO > 5
solution Powell(matrix x0, double epsilon, int Nmax, matrix *ud, matrix *ad)
{
// a[0] = x
// a[1] = d
int n = get_len(x0);
matrix D = ident_mat(n), *A = new matrix[2];
solution X, P, h;
X.x = x0;
double *ab; // z ekspansji
while (true)
{
P = X;
for (int i = 0; i < n; ++i)
{
A[0] = P.x;
A[1] = D[i];
ab = expansion(0, 1, 1.2, Nmax, ud, A);
h = golden(ab[0], ab[1], epsilon, Nmax, ud, A);
P.x = P.x + h.x * D[i];
}
if (norm(X.x - P.x) < epsilon || solution::f_calls > Nmax)
{
P.fit_fun(ud);
return P;
}
for (int i = 0; i < n - 1; ++i)
{
D.set_col(D[i + 1], i);
}
//ostatni kierunek daje sie inaczej
D.set_col(P.x - X.x, n - 1);
A[0] = P.x;
A[1] = D[n - 1];
ab = expansion(0, 1, 1.2, Nmax, ud, A);
h = golden(ab[0], ab[1], epsilon, Nmax, ud, A);
X.x = P.x + h.x * D[n - 1];
}
}
#endif
#if LAB_NO > 6
solution EA(int N, matrix limits, int mi, int lambda, matrix sigma0, double epsilon, int Nmax, matrix *ud, matrix *ad)
{
solution *P = new solution[mi + lambda];
solution *Pm = new solution[mi];
random_device rd;
default_random_engine gen;
gen.seed(static_cast(chrono::system_clock::now().time_since_epoch().count()));
normal_distribution distr(0.0, 1.0);
matrix IFF(mi, 1), temp(N, 2);
double r, s, s_IFF;
double tau = pow(2 * N, -0.5), tau1 = pow(2 * pow(N, 0.5), -0.5);
int j_min;
for (int i = 0; i < mi; ++i)
{
P[i].x = matrix(N, 2);
for (int j = 0; j < N; ++j)
{
P[i].x(j, 0) = (limits(j, 1) - limits(j, 0)) * rand_mat(1, 1)() + limits(j, 0);
P[i].x(j, 1) = sigma0(j);
}
P[i].fit_fun(ud, ad);
cout << P[i].y << endl;
if (P[i].y < epsilon)
{
return P[i];
}
}
int WhileLoopCount = 0;
while (true)
{
if (ud != nullptr)
{
for (size_t i = 0; i < mi; i++)
{
matrix data(1, 3, 10);
data(0, 0) = WhileLoopCount;
data(0, 1) = P[i].x(0, 0);
data(0, 2) = P[i].x(1, 0);
ud->add_row(data);
}
}
WhileLoopCount++;
cout << WhileLoopCount << endl;
s_IFF = 0;
for (int i = 0; i < mi; ++i)
{
IFF(i) = 1 / P[i].y();
s_IFF += IFF(i);
}
for (int i = 0; i < lambda; ++i)
{
r = s_IFF * rand_mat(1, 1)();
s = 0;
for (int j = 0; j < mi; ++j)
{
s += IFF(j);
if (r <= s)
{
P[mi + i] = P[j];
break;
}
}
}
for (int i = 0; i < lambda; ++i)
{
r = distr(gen);
for (int j = 0; j < N; ++j)
{
P[mi + i].x(j, 1) *= exp(tau1 * r + tau * distr(gen));
P[mi + i].x(j, 0) += P[mi + i].x(j, 1) * distr(gen);
}
}
for (int i = 0; i < lambda; i += 2)
{
r = rand_mat(1, 1)();
temp = P[mi + i].x;
P[mi + i].x = r * P[mi + i].x + (1 - r) * P[mi + i + 1].x;
P[mi + i + 1].x = r * P[mi + i + 1].x + (1 - r) * temp;
}
for (int i = 0; i < lambda; ++i)
{
P[mi + i].fit_fun(ud, ad);
if (P[mi + i].y < epsilon)
return P[mi + i];
}
for (int i = 0; i < mi; ++i)
{
j_min = 0;
for (int j = 1; j < mi + lambda; ++j)
if (P[j_min].y > P[j].y)
j_min = j;
Pm[i] = P[j_min];
P[j_min].y = 1e10;
}
for (int i = 0; i < mi; ++i)
P[i] = Pm[i];
if (solution::f_calls > Nmax)
return P[0];
}
}
#endif