{ "cells": [ { "cell_type": "markdown", "source": [ "# Matrix Completion Problem using `NExOS.jl`\n", "**Shuvomoy Das Gupta**\n", "\n", "A matrix completion problem can be formulated as the following optimization problem:\n", "\n", "$$\n", "\\begin{array}{ll}\n", "\\textrm{minimize} & \\sum_{(i,j)\\in\\Omega}(X_{ij}-Z_{ij})^{2}\\\\\n", "\\textrm{subject to} & \\mathop{{\\bf rank}}(X)\\leq r\\\\\n", " & \\|X\\|_{2}\\leq M\\\\\n", " & X\\in\\mathbf{R}^{m\\times n},\n", "\\end{array}\n", "$$\n", "\n", "where $Z\\in\\mathbf{R}^{m\\times n}$ is the matrix whose entries $Z_{ij}$ are observable for $(i,j)\\in\\Omega$. Based on these observed entries, our goal is to construct a matrix $X\\in\\mathbf{R}^{m\\times n}$ that has rank $r$. \n", "\n", "First, of course, we load our packages." ], "metadata": {} }, { "cell_type": "code", "source": [ "using Random, LinearAlgebra, NExOS\n", "\n", "Random.seed!(1234)" ], "outputs": [ { "output_type": "execute_result", "execution_count": 1, "data": { "text/plain": "MersenneTwister(UInt32[0x000004d2], Random.DSFMT.DSFMT_state(Int32[-1393240018, 1073611148, 45497681, 1072875908, 436273599, 1073674613, -2043716458, 1073445557, -254908435, 1072827086 … -599655111, 1073144102, 367655457, 1072985259, -1278750689, 1018350124, -597141475, 249849711, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)" }, "metadata": {} } ], "execution_count": 1, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:15.413Z", "iopub.execute_input": "2020-11-11T15:33:16.479Z", "iopub.status.idle": "2020-11-11T15:33:28.658Z" } } }, { "cell_type": "markdown", "source": [ "Construct a random $m\\times n$ matrix matrix of rank $k$." ], "metadata": {} }, { "cell_type": "code", "source": [ "m,n,k = 40,40,5\n", "Zfull = randn(m,k)*randn(k,n) # ground truth data\n", "Zfull = Zfull/opnorm(Zfull,2) # scale the matrix so its operator norm is 1\n", "M = opnorm(Zfull,2)" ], "outputs": [ { "output_type": "execute_result", "execution_count": 2, "data": { "text/plain": "1.0000000000000002" }, "metadata": {} } ], "execution_count": 2, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:28.675Z", "iopub.execute_input": "2020-11-11T15:33:28.987Z", "iopub.status.idle": "2020-11-11T15:33:30.602Z" } } }, { "cell_type": "markdown", "source": [ "Suppose that we only observe a fraction of entries in Zfull. Let us find the indices of all the elements that are available." ], "metadata": {} }, { "cell_type": "code", "source": [ "n_obs = 600\n", "Zobs = fill(NaN,(m,n))\n", "obs = randperm(m*n)[1:n_obs]\n", "Zobs[obs] .= Zfull[obs] # partially observed matrix" ], "outputs": [ { "output_type": "execute_result", "execution_count": 3, "data": { "text/plain": "600-element view(::Array{Float64,1}, [314, 484, 770, 1462, 495, 602, 637, 1284, 358, 1510 … 1159, 371, 157, 537, 589, 533, 221, 1025, 564, 529]) with eltype Float64:\n 0.04614085153216508\n 0.029552887430458176\n -0.0184886116014581\n -0.04597613170772224\n 0.06158831071378109\n 0.04359079928175278\n -0.014791813279264342\n 0.006936983760815719\n 0.01650141696962079\n -0.014561284205705108\n 0.0251527010880924\n 0.008374291722196085\n -0.00335913745738921\n ⋮\n -0.008553749580091464\n -0.010747230035676235\n -0.01914100968377146\n -0.055173021978315376\n -0.16168361561961594\n -0.02789400226183489\n -0.02613098308987431\n -0.010856985785824986\n 0.01568346928771265\n -0.025649452543356512\n -0.003523186151803044\n 0.022307043854383427" }, "metadata": {} } ], "execution_count": 3, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:30.617Z", "iopub.execute_input": "2020-11-11T15:33:30.629Z", "iopub.status.idle": "2020-11-11T15:33:31.849Z" } } }, { "cell_type": "markdown", "source": [ "Plot the ground-truth, full dataset and our partial observations" ], "metadata": {} }, { "cell_type": "code", "source": [ "using PyPlot" ], "outputs": [], "execution_count": 4, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:31.858Z", "iopub.execute_input": "2020-11-11T15:33:31.866Z", "iopub.status.idle": "2020-11-11T15:33:41.625Z" } } }, { "cell_type": "markdown", "source": [ "Plot the ground-truth, full dataset and our partial observations" ], "metadata": {} }, { "cell_type": "code", "source": [ "figure(figsize=(7,14))\n", "subplot(1,2,1)\n", "imshow(Zfull,cmap=ColorMap(\"Blues\"),interpolation=\"None\")\n", "xticks([]),yticks([]),title(\"True Data\",fontweight=\"bold\")\n", "\n", "subplot(1,2,2)\n", "imshow(Zobs,cmap=ColorMap(\"Blues\"),interpolation=\"None\")\n", "xticks([]),yticks([]),title(\"Observed Data\",fontweight=\"bold\")\n", "show()\n", "PyPlot.display_figs()" ], "outputs": [ { "output_type": "display_data", "data": { "text/plain": "Figure(PyObject
)", "image/png": "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" }, "metadata": {} } ], "execution_count": 5, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:41.635Z", "iopub.execute_input": "2020-11-11T15:33:41.787Z", "iopub.status.idle": "2020-11-11T15:33:45.273Z" } } }, { "cell_type": "markdown", "source": [ "Let us create our problem now:" ], "metadata": {} }, { "cell_type": "code", "source": [ "M = opnorm(Zfull,2)\n", "f = SquaredLossMatrixCompletion(Zobs, iterative = true)\n", "r = rank(Zfull)\n", "Z0 = zeros(size(Zobs))\n", "C = RankSet(M, r)\n", "settings = Settings(μ_max = 5, μ_mult_fact = 0.5, n_iter_min = 1000, n_iter_max = 1000, verbose = false, freq = 1000, tol = 1e-4, γ_updt_rule = :safe)\n", "problem = NExOS.Problem(f, C, settings.β, Z0)" ], "outputs": [ { "output_type": "execute_result", "execution_count": 6, "data": { "text/plain": "Problem{ProximalOperators.LeastSquaresIterative{1,Float64,Float64,SparseArrays.SparseMatrixCSC{Float64,Int64},Array{Float64,1},ProximalOperators.AAc},RankSet{Float64,Int64},Float64,Array{Float64,2}}(description : Least squares penalty\ndomain : n/a\nexpression : n/a\nparameters : n/a, RankSet{Float64,Int64}(1.0000000000000002, 5), 1.0e-10, [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0])" }, "metadata": {} } ], "execution_count": 6, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:45.283Z", "iopub.execute_input": "2020-11-11T15:33:45.290Z", "iopub.status.idle": "2020-11-11T15:33:46.527Z" } } }, { "cell_type": "markdown", "source": [ "Time to solve our problem..." ], "metadata": {} }, { "cell_type": "code", "source": [ "state_final = solve!(problem, settings)\n", "\n", "Z_estimated = state_final.x" ], "outputs": [ { "output_type": "execute_result", "execution_count": 7, "data": { "text/plain": "40×40 Array{Float64,2}:\n 0.00921175 -0.0038448 -0.00129091 … -0.00447769 -0.00843496\n -0.0147354 0.0011719 -0.000635124 0.00706023 0.00987895\n -0.0444565 -0.00207041 -0.0177526 0.0141985 0.00632431\n -0.0026325 0.00607353 0.0049039 -0.00903814 0.00128217\n 0.0112686 0.0109044 -0.0102908 0.00818285 -0.0127803\n 0.0291193 -0.00187681 0.000716274 … 0.013873 -0.00132453\n -0.0028306 -0.0188753 -0.0163884 0.0218045 -0.00466638\n -0.00147231 0.0134306 0.0115974 -0.00983515 0.00878667\n 0.0105054 0.00433151 0.00609612 0.00531648 0.00636103\n -0.0051754 0.0209462 0.0130169 -0.0116038 0.0111824\n -0.0119 -0.000936404 -0.0142817 … 0.00737043 -0.00860866\n -0.0144667 -0.00838286 -0.0160724 0.0259919 0.00282836\n -0.00400986 0.0017526 -0.00431504 0.019474 0.00892805\n ⋮ ⋱ \n 0.0347436 0.0353489 0.0538003 -0.0787362 0.00203755\n -0.00400174 0.0174897 0.0194419 -0.0309039 0.00560616\n -0.0107255 -0.0128399 -0.000264674 … 0.0154012 0.0140037\n 0.0289964 0.00806107 0.0227597 -0.0375122 -0.00791514\n -0.00530796 0.00876034 0.00745653 -0.00555373 0.00819782\n -0.0171454 -0.0176783 -0.0123308 0.0109885 -0.000278122\n 0.00567607 0.00238189 0.00376122 0.00607806 0.00619147\n -0.00492816 -0.0150325 -0.013713 … 0.0200635 -0.00200861\n 0.0283517 0.0228515 0.0230801 0.00278105 0.0182905\n -0.0135796 0.00143811 -0.0111562 0.0100748 -0.00156238\n -0.00264522 0.00379569 0.0072004 -0.000408534 0.00941569\n -0.0167782 -0.00217151 -0.0046546 0.00407195 0.00347602" }, "metadata": {} } ], "execution_count": 7, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:46.537Z", "iopub.execute_input": "2020-11-11T15:33:46.545Z", "iopub.status.idle": "2020-11-11T15:33:51.802Z" } } }, { "cell_type": "markdown", "source": [ "Finally, we plot a simple histogram to see how much of the matrix has been recovered." ], "metadata": {} }, { "cell_type": "code", "source": [ "figure(figsize=(8,3))\n", "PyPlot.hist(vec(Zfull - Z_estimated ),100)\n", "xlim([-0.5,0.5]),xlabel(\"Absolute Errors/Residuals\",fontweight=\"bold\"),tight_layout()\n", "show()\n", "PyPlot.display_figs()" ], "outputs": [ { "output_type": "display_data", "data": { "text/plain": "Figure(PyObject
)", "image/png": "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7YqLizVixAg98cQTatu2bXWUihquqmPpSi6XSw6HQw0bNvRGmahhCgsLlZmZqd69e7u19+7d+6rjZvPmzaX69+nTRzt27NCFCxe8VitqtqqMpSsVFxcrLy9PjRo18kaJqAWqOo4WLVqkf/zjH5o5c6a3S6yTfHqBPHhOdna2IiIiSrVHREQoOzv7qtvNmTNH/v7+mjRpkjfLQy1S1bF0uZ9++knJyckaPny4QkNDPV0iaqDTp0+rqKhIkZGRbu2RkZFXHTfZ2dll9r948aJOnz6tpk2beq1e1FxVGUtXev7553Xu3Dndf//93igRtUBVxtGhQ4eUnJysDRs2yN+fr8hVwYxFDZeamiqHw1HubceOHZIkh8NRantjTJntkpSZmakXX3xRixcvvmof1B3eHEuXu3DhgoYNG6bi4mItXLjQ468DNduVY+Tnxk1Z/ctqx7WnsmOpxNKlS5Wamqrly5eX+SMJri0VHUdFRUUaPny4Zs2apZtuuqm6yqtziGM13KOPPqphw4aV2yc2NlZfffWVvv/++1KP/fDDD6XSeokNGzYoJydHzZs3t9qKior0+9//XvPnz9eRI0ds1Y6axZtjqcSFCxd0//33KysrS1988QWzFdeQxo0by8/Pr9QvgTk5OVcdN1FRUWX29/f3V3h4uNdqRc1WlbFUYvny5RozZozeffdd3XPPPd4sEzVcZcdRXl6eduzYoV27dunRRx+VdOmQOmOM/P39tXr1av3yl7+sltprM4JFDde4cWM1btz4Z/t16dJFLpdL27Zt0+233y5J2rp1q1wul7p27VrmNiNGjCj1D2+fPn00YsQIPfLII/aLR43izbEk/StUHDp0SGvWrOGL4TUmMDBQnTp1UkZGhoYMGWK1Z2RkaNCgQWVu06VLF3388cdubatXr1bnzp0VEBDg1XpRc1VlLEmXZipGjx6tpUuXql+/ftVRKmqwyo6j0NBQff31125tCxcu1BdffKH33ntPcXFxXq+5TvDhwnF42L333mtuueUWs3nzZrN582bTrl07079/f7c+N998s/nggw+uug/OCgVjKj+WLly4YAYOHGiaNWtmdu/ebU6dOmXdCgoKfPES4APLli0zAQEB5s033zT79+83kydPNg0aNDBHjhwxxhiTnJxsRowYYfX/9ttvTXBwsHnsscfM/v37zZtvvmkCAgLMe++956uXgBqismNpyZIlxt/f37zyyitu//7885//9NVLQA1Q2XF0Jc4KVXnMWNQh77zzjiZNmmSdAWHgwIFasGCBW5+DBw/K5XL5ojzUIpUdSydOnNBHH30kSaUuJrRmzRolJSV5v2j43AMPPKAff/xRzzzzjE6dOqWEhAR98sknatGihSTp1KlTbuePj4uL0yeffKLHHntMr7zyiqKjo/XSSy/pV7/6la9eAmqIyo6l1157TRcvXtSECRM0YcIEq33kyJFavHhxdZePGqKy4wj2OYz5/yvlAAAAAKCKOCsUAAAAANsIFgAAAABsI1gAAAAAsI1gAQAAAMA2ggUAAAAA2wgWAAAAAGwjWAAAAACwjWABAAAAwDaCBQAAAADbCBYAIOnIkSNyOBxyOBxau3at159v8eLF1vOhbli7dq31mR45cuSq/VJTU7362TO2APgKwQLANWHRokXWl6169eqV+8Wvphs1apQcDoeSkpI8ts+kpCTr/bnytnLlSo89j7eNGzdOkZGRKi4utt6nkpufn58aN26s++67T7t27fL4c4eGhioxMVGJiYlyOp0e3z8A1HT+vi4AAKrD4sWLrb+NMUpPT9fMmTN9V1ANFRgYqA4dOri1NWrU6Kr9jTG6ePGiAgICSj1WVFQkSfLz86tyPYWFhQoMDKxQX2OMPv74Yw0YMED16rn/bpaYmKizZ89q3759+vTTT7Vjxw4dPXpUQUFBVa7tSh07dtSWLVs8tj8AqG2YsQBQ52VlZWnDhg2SpM6dO0uS0tPTZYwps/93332nAQMGKDg4WM2aNdMrr7xiPVZUVKSUlBS1bNlS9evXV8OGDdWxY0f96U9/svrk5+frqaee0o033qjAwECFh4dryJAh2rt3b7l1lswajBo1ymorOWwmNjZWkhQbG6v09HRJ0rp160odvnXy5EmNHj1a0dHRCgwMVMuWLfWf//mfunjxYoXeq6ZNm2rLli1utzvvvFOS+yE2n332mdq2bauAgABt3LjRrc6//OUv1ms/fvy4JOmjjz5S9+7ddd111ykoKEgdO3bUW2+95fbcJfueO3euhg4dqgYNGui3v/2tJOn5559Xq1atFBwcrJCQELVt21aPP/642/bbt2/XyZMnNXjw4FKva8uWLdq7d6+efvppSdIPP/ygAwcOWI8XFBRo5syZio+Pl9PpVEREhEaPHq3Tp09bfbKzs/XQQw+padOmCgwMVJMmTZSUlKRVq1ZJKvtQKGOMpk+frvDwcDVs2FATJ05UYWFhqfoq8tlL0nPPPaf27durUaNGCggIUEREhIYOHapvvvmm3M91y5YtuvvuuxUeHi6n06lmzZpp4MCB+sc//lHudgBQKQYA6rgZM2YYSSYqKsrs2bPHSDKSzNq1a60+WVlZVnuDBg1MXFycady4sdX24YcfGmOMefHFF40k4+fnZ2655Rbzi1/8wgQGBpqePXta+7rnnnuMJONwOEyrVq3MddddZySZ6667zhw4cMAYY8yiRYusfZfo2bWgwScAAApbSURBVLOnkWRGjhxptc2cOdNIMi1atDDGGDN48GCrrpCQEJOYmGgSExNNZmam+eGHH0xMTIz12C233GL8/f2NJPPII4+U+x6VPHfJ85Tl8poDAwNNixYtTMuWLc2aNWusOgMCAozD4TA33XSTueGGG0xWVpb561//am0XGRlpWrRoYd3/wx/+YO3/8n2X1P/b3/7WfPjhh9Zjbdq0Ma1atTJBQUGlak1JSTENGjQw+fn5xhhjRo4cWeo9nj59uvX5fffdd1b7fffd5/a5hoaGWs93/vx5Y4wxQ4YMsT7Hjh07mpiYGONwOMzMmTONMcasWbPGer6srCxjjDEvvfSS1dasWTMTERFhGjRoUKXP3hhj+vXrZxo0aGBat25tEhISjJ+fn5FkYmJirNd95dgqKioy4eHh1vvfvn1706RJEyPJrFmzptxxAQCVQbAAUKcVFxebuLg4I8lMmTLFGGNMhw4djCQzatQoq9/lweLBBx80xcXFJi8vz8THxxtJJjEx0RhjzKOPPlrqC2BeXp7Ztm2bMcaYL774wtrPCy+8YIwx5vjx41a4ePjhh40xVQ8WxvzrC/PlYcYYY1JTU60vjzk5OcYYY1auXGmFnEOHDl31fSp57rJuZ86cKVXz448/bm178eJFq05JZsGCBdZjRUVFpnnz5tZ7+NNPP5ni4mLrS3pQUJA5d+6cMeZfweKmm24yP/74o7Xv5557zkgySUlJ1n5/+ukns3HjRrfX0KZNGzN06NBS71PJc7dt29ZIMsHBweall16y+q1du9bqt27dOmOMMSdPnjRBQUFGkvmv//ovY4wxCQkJRpJZtGiRte3JkyetsFhWsGjWrJmRZLp3724uXLhgzp07Z26++eYqf/Z79+41hYWF1v2MjAxrX3/7299KfU7GGHP69OlSdZXs6/vvvzcA4CkcCgWgTlu7dq2ysrIkSSNGjHD73/fee0/nzp0rtc2wYcPkcDh03XXXqX///pJkHcbUv39/ORwOpaenKzo6WnfddZf+8Ic/WOsQtm/fbu1n+PDhkqRmzZqpR48ekqQdO3Z442VKkrZt2yZJ+v777xURESGHw2EdFmSM0datW392H4GBgdYC5JKbv3/p5XhTpkyx/r58DUVQUJD+4z/+w7p/+vRpHTt2TJI0dOhQOZ1OORwODRs2TNKlw8b27dvntu9Ro0ZZ76efn5/69OmjwMBArV27Vk2aNFH37t01depUBQcHW9scPnxY+/fvL/MwKEnaunWr9Tw33nij+vbtaz1W8r5JUs+ePeVwOBQdHa38/HxJstZNDBgwQJI0ZswY/eIXv1D//v319ttvKzo6usznzM3N1YkTJyRJAwcOlL+/v4KDg9WvX78y+1fEsWPHdNdddyk0NFT16tVTr169rMdOnjxZ5jbh4eHq0qWLJKlVq1Zq166dHnzwQe3atUuNGzeuci0AcCUWbwOo0y5ftF1yFqWSRcVnz57Ve++9p5EjR7ptU95pOvv06aOdO3fq3Xff1Z49e7Rr1y6tXbtWixcv1uHDhyu8n7KU9C+pT5JcLleFtzf/f81ISEiI2rRpU+rxy7+IX03JGoufExUVVWZ7kyZNSi2cLlHR9+PKfSckJGjfvn1asmSJdu3apT179mjjxo164403dODAAbVo0UIrV66Uv7//Vb+0FxcXKzMzU/fee6++/vpr/frXv9bOnTtVr149t7U2iYmJV63n2WefVbdu3fT5559r7969Wr9+vVatWqW1a9da6yyu5vLXfvnzXfl4eZ/9t99+q8GDB6uwsFAhISHq1KmTLl68qN27d5fa9kp///vftWTJEm3cuFH79+/Xu+++q2XLlunUqVN64oknyq0dACqKGQsAddbZs2f1/vvvW/ddLpdcLpfOnj1rtV0ePEosXbpUxhidO3fO+sKYkJAgSfrqq68UERGhZ599Vv/zP/9jfQn//vvvdfDgQd12223Wft555x1J0okTJ0otHi9LRESEJOnQoUOSLv2aX9YX1pKAcOVsy+233y5J8vf317Jly6zF1xkZGRo/fryGDBly1eeurKuFhCvbIyIi1Lx5c0nS+++/r4KCAhljtGzZMkmXZjjatm1b7j4OHTokh8OhGTNmaMWKFdq/f7+Cg4OVn59vzQB9+OGH6tGjx1XPYOVwONS5c2frTGB79uzRf//3f0v61/smSSkpKdb79uWXXyo1NVVjxoyRJG3cuFE9e/bUSy+9pC+++MJa1L9+/foynzM0NFTNmjWTdGnx+sWLF5Wfn69PP/20VN+KfPa7du2yFn5//vnn2r59u5588skyn/tyxhht2rRJo0aN0ltvvaUtW7ZYYfpqtQNAlfjwMCwA8Kq33nrLOrb8q6++cnvs5ZdfttYeZGVllbl4u2SBqySzYsUKY4wx06ZNMw6Hw8TExJiOHTtaC6mDg4OttQiXL95u3bq1CQkJqdDi7ddee81q69y5s4mNjTX16tUrdZx9yQJySSYhIcEkJiaa8+fPm5ycHHPDDTdYC6BvvfVW07JlSxMQEGB+7p/7kmP8AwMDrQXhJbdly5ZdteYSZa0HKFHZxduXr2Ewxpg33njDSDJNmzY1HTp0MNHR0dZC6/3795ucnBxTr1498+KLL7ptV9bi7fPnz1uf66233mq19+nTx+p78803mzZt2liLrEsWOHfr1s0EBgaaG2+80XTs2NFag9G1a1djTNlrLObPn++2eDsyMtI4nc4qffYHDhywFmuHhoaahIQEtxMMlLxvV35OFy5cMNKlBf1t2rQxCQkJ1r6feuqpq4wIAKg8ZiwA1Fklp2WNj49Xu3bt3B4bMmSIHA6HdU2Ly7322mtq06aNzp49q+joaL344ovWsft33nmn7r33XhUXF2vv3r0qLi7WL3/5S3366adq2LChpEu/TqekpCguLk6HDh2Sv7+/Bg8erM2bN6tVq1ZXrfeRRx7RpEmT1LhxYx0+fFi9evXS7373u1L9Ro8erV/96lcKCwvT3r17tXXrVhUVFalJkybasmWLHnnkEYWHh2vfvn3Kz89Xjx499MILL1ToPSssLNTWrVvdbqdOnarQtlfzm9/8RitXrlTXrl2Vl5en7OxstW/fXm+++aamTZv2s9t36NBBQ4YMUWBgoPbv369z587pjjvu0LvvvqvWrVvr448/VnFxsQYNGvSz+woKCtKkSZMkXZq1KJkVWLlypWbMmKH4+Hh9++23ys7OVuvWrTV9+nRrtuqBBx7QbbfdptzcXH399ddq2LChhg0bpqVLl171+SZOnKjk5GRdf/31crlc6t+/f5mfaUU++1atWumtt95SXFycCgsL1bhx43Kfu4Sfn5/GjRunuLg4fffddzp8+LBiY2P1+OOPa8aMGT+7PQBUlMOYq5zIHQCAWmDQoEE6duyYV66mDQCoOBZvAwBqtW7dumncuHG+LgMArnnMWAAAAACwjTUWAAAAAGwjWAAAAACwjWABAAAAwDaCBQAAAADbCBYAAAAAbCNYAAAAALCNYAEAAADANoIFAAAAANsIFgAAAABs+38V40mqLxAsuAAAAABJRU5ErkJggg==" }, "metadata": {} } ], "execution_count": 8, "metadata": { "execution": { "iopub.status.busy": "2020-11-11T15:33:51.811Z", "iopub.execute_input": "2020-11-11T15:33:51.819Z", "iopub.status.idle": "2020-11-11T15:33:52.615Z" } } }, { "cell_type": "markdown", "source": [ "So, `NExOS` does a good job!" ], "metadata": {} } ], "metadata": { "language_info": { "file_extension": ".jl", "name": "julia", "mimetype": "application/julia", "version": "1.5.0" }, "kernelspec": { "name": "julia-1.5", "display_name": "Julia 1.5.0", "language": "julia" }, "nteract": { "version": "0.28.0" } }, "nbformat": 4, "nbformat_minor": 2 }