Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 209 additions & 16 deletions project_1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
},
{
"cell_type": "code",
"execution_count": 55,
"execution_count": 112,
"id": "9d9c91f7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Best solution: [0 0 1 1 1 1 0 0 1 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 1 1 1 1 0 1 1\n",
" 1 0 1 0 1 1 0 1 1 1 1 0 1]\n",
"Best solution: [1 0 1 1 0 1 0 0 1 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 1 1 1 0 1 0\n",
" 1 0 1 0 1 0 1 1 1 0 1 0 1]\n",
"Total value: 309.0\n"
]
}
Expand Down Expand Up @@ -130,19 +130,27 @@
"print(\"Total value:\", best_value)\n"
]
},
{
"cell_type": "markdown",
"id": "f3e72e7b",
"metadata": {},
"source": [
"#### Knapsack CMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 113,
"id": "9be946a4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Best solution (binary vector): [1 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0\n",
"Best solution (binary vector): [0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0\n",
" 0 0 1 1 0 0 1 0 0 0 1 1 0]\n",
"Best total value: 73.0\n"
"Best total value: 70.0\n"
]
}
],
Expand Down Expand Up @@ -301,7 +309,7 @@
},
{
"cell_type": "code",
"execution_count": 57,
"execution_count": 114,
"id": "8a6129d6",
"metadata": {},
"outputs": [],
Expand All @@ -315,7 +323,7 @@
},
{
"cell_type": "code",
"execution_count": 58,
"execution_count": 115,
"id": "e75e2f25",
"metadata": {},
"outputs": [],
Expand All @@ -331,7 +339,7 @@
},
{
"cell_type": "code",
"execution_count": 59,
"execution_count": 116,
"id": "33adaa91",
"metadata": {},
"outputs": [],
Expand Down Expand Up @@ -378,15 +386,15 @@
},
{
"cell_type": "code",
"execution_count": 60,
"execution_count": 117,
"id": "8b4668c0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.0\n"
"6.684735230633176e-14\n"
]
}
],
Expand Down Expand Up @@ -419,7 +427,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 118,
"id": "b948ed30",
"metadata": {},
"outputs": [],
Expand All @@ -433,7 +441,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 119,
"id": "1aa84235",
"metadata": {},
"outputs": [],
Expand All @@ -451,7 +459,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 120,
"id": "b19497d6",
"metadata": {},
"outputs": [],
Expand Down Expand Up @@ -499,7 +507,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 121,
"id": "4a91facf",
"metadata": {},
"outputs": [
Expand Down Expand Up @@ -529,10 +537,195 @@
"print(population[sorted_ind[0]], np.average(fitness(population)))"
]
},
{
"cell_type": "markdown",
"id": "dcc99684",
"metadata": {},
"source": [
"#### CMA (for all non-binary problems)"
]
},
{
"cell_type": "code",
"execution_count": 125,
"id": "443c16e6",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"class CMAES:\n",
" def __init__(self, n_dim, problem='parabola', \n",
" pop_size=None, mu=None, sigma=None, max_iter=500):\n",
" \"\"\"\n",
" CMA for continuous minimization problems.\n",
" Supports: 'parabola', 'ellipsoid', 'rastrigin'\n",
" \"\"\"\n",
" self.n = int(n_dim)\n",
" self.problem = problem\n",
"\n",
" # CMA-ES parameters\n",
" self.lam = pop_size if pop_size else 4 + int(3 * np.log(self.n + 1))\n",
" self.mu = mu if mu else self.lam // 2\n",
" self.sigma = sigma if sigma else 0.2\n",
" self.max_iter = max_iter\n",
"\n",
" # recombination weights\n",
" w = np.log(self.mu + 0.5) - np.log(np.arange(1, self.mu + 1))\n",
" self.weights = w / np.sum(w)\n",
" self.mueff = np.sum(self.weights)**2 / np.sum(self.weights**2)\n",
"\n",
" # initialization\n",
" self.mean = np.zeros(self.n)\n",
" self.C = np.identity(self.n)\n",
" self.pc = np.zeros(self.n)\n",
" self.ps = np.zeros(self.n)\n",
"\n",
" # constants\n",
" self.cc = (4 + self.mueff/self.n) / (self.n + 4 + 2*self.mueff/self.n)\n",
" self.cs = (self.mueff + 2) / (self.n + self.mueff + 5)\n",
" self.c1 = 2 / ((self.n + 1.3)**2 + self.mueff)\n",
" self.cmu = min(1 - self.c1,\n",
" 2*(self.mueff - 2 + 1/self.mueff) /\n",
" ((self.n + 2)**2 + self.mueff))\n",
" self.damps = 1 + 2*max(0, np.sqrt((self.mueff-1)/(self.n+1)) - 1) + self.cs\n",
"\n",
" # eigen decomposition\n",
" self.B = np.identity(self.n)\n",
" self.D = np.ones(self.n)\n",
" self.inv_sqrt_C = np.identity(self.n)\n",
" self.chiN = np.sqrt(self.n) * (1 - 1/(4*self.n) + 1/(21*self.n**2))\n",
"\n",
" self.history = []\n",
"\n",
" # Objective functions\n",
" def fitness(self, x):\n",
" \"\"\"Return f(x) for the current problem (minimization).\"\"\"\n",
" if self.problem == 'parabola':\n",
" return 10 * np.sum(x**2)\n",
"\n",
" elif self.problem == 'ellipsoid':\n",
" # Rotated hyper-ellipsoid\n",
" x1, x2 = x[0], x[1]\n",
" term1 = (np.sqrt(3)/2*(x1 - 3) + 0.5*(x2 - 5))**2\n",
" term2 = 5*((np.sqrt(3)/2*(x2 - 5) - 0.5*(x1 - 3)))**2\n",
" return term1 + term2\n",
"\n",
" elif self.problem == 'rastrigin':\n",
" d = len(x)\n",
" return 10*d + np.sum((x - 2)**2 - 10*np.cos(2*np.pi*(x - 2)))\n",
"\n",
" else:\n",
" raise ValueError(f\"Unknown problem '{self.problem}'\")\n",
"\n",
" \n",
" # Core CMA logic\n",
" def ask(self):\n",
" \"\"\"Generate new candidate population.\"\"\"\n",
" arz = np.random.randn(self.n, self.lam)\n",
" ary = self.B @ (self.D.reshape(-1, 1) * arz)\n",
" arx = self.mean.reshape(-1, 1) + self.sigma * ary\n",
" return arx.T, arz.T\n",
"\n",
" def run(self):\n",
" best_val = np.inf\n",
" best_x = None\n",
"\n",
" for gen in range(self.max_iter):\n",
" arx, arz = self.ask()\n",
" fits = np.array([self.fitness(x) for x in arx])\n",
" idx = np.argsort(fits)\n",
" arx, arz, fits = arx[idx], arz[idx], fits[idx]\n",
"\n",
" if fits[0] < best_val:\n",
" best_val = fits[0]\n",
" best_x = arx[0]\n",
"\n",
" xold = self.mean\n",
" self.mean = np.dot(self.weights, arx[:self.mu])\n",
" y = np.dot(self.weights, arz[:self.mu])\n",
"\n",
" # evolution paths\n",
" self.ps = (1 - self.cs)*self.ps + np.sqrt(self.cs*(2-self.cs)*self.mueff)*(self.B @ y)\n",
" hsig = int(\n",
" (np.linalg.norm(self.ps)/np.sqrt(1-(1-self.cs)**(2*(gen+1)))/self.chiN)\n",
" < (1.4 + 2/(self.n+1))\n",
" )\n",
" self.pc = (1 - self.cc)*self.pc + hsig*np.sqrt(self.cc*(2-self.cc)*self.mueff)*(self.B @ (self.D*y))\n",
"\n",
" # covariance update\n",
" artmp = (1/self.sigma)*(arx[:self.mu] - xold)\n",
" self.C = (1 - self.c1 - self.cmu)*self.C \\\n",
" + self.c1*(np.outer(self.pc, self.pc) + (1-hsig)*self.cc*(2-self.cc)*self.C) \\\n",
" + self.cmu*np.sum([w*np.outer(ar, ar)\n",
" for w, ar in zip(self.weights, artmp)], axis=0)\n",
"\n",
" # step size\n",
" self.sigma *= np.exp((self.cs/self.damps)*(np.linalg.norm(self.ps)/self.chiN - 1))\n",
"\n",
" # decomposition update\n",
" if gen % (self.n//10 + 1) == 0:\n",
" self.D, self.B = np.linalg.eigh(self.C)\n",
" self.D = np.sqrt(np.maximum(self.D, 1e-20))\n",
" self.inv_sqrt_C = self.B @ np.diag(self.D**-1) @ self.B.T\n",
"\n",
" self.history.append(best_val)\n",
"\n",
" # stop once essentially converged\n",
" if best_val < 1e-40:\n",
" break\n",
"\n",
" return best_x, best_val, self.history\n"
]
},
{
"cell_type": "code",
"execution_count": 126,
"id": "1bdb6c52",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Best x: [-1.57456597e-21]\n",
"Best f(x)=10x²: 2.479258000512089e-41\n"
]
}
],
"source": [
"cma_para = CMAES(n_dim=1, problem='parabola', sigma=0.05, max_iter=1000)\n",
"best_x, best_val, hist = cma_para.run()\n",
"print(\"Best x:\", best_x)\n",
"print(\"Best f(x)=10x²:\", best_val)\n"
]
},
{
"cell_type": "code",
"execution_count": 127,
"id": "f0d4eba1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Best x: [3. 5.]\n",
"Best f(x): 0.0\n"
]
}
],
"source": [
"cma_ellip = CMAES(n_dim=2, problem='ellipsoid', sigma=0.3, max_iter=600)\n",
"best_x, best_val, hist = cma_ellip.run()\n",
"print(\"Best x:\", best_x)\n",
"print(\"Best f(x):\", best_val)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e954d523",
"id": "6fa924ed",
"metadata": {},
"outputs": [],
"source": []
Expand Down