{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Entropic Coding and Compression\n", "===============================\n", "\n", "*Important:* Please read the [installation page](http://gpeyre.github.io/numerical-tours/installation_python/) for details about how to install the toolboxes.\n", "$\\newcommand{\\dotp}[2]{\\langle #1, #2 \\rangle}$\n", "$\\newcommand{\\enscond}[2]{\\lbrace #1, #2 \\rbrace}$\n", "$\\newcommand{\\pd}[2]{ \\frac{ \\partial #1}{\\partial #2} }$\n", "$\\newcommand{\\umin}[1]{\\underset{#1}{\\min}\\;}$\n", "$\\newcommand{\\umax}[1]{\\underset{#1}{\\max}\\;}$\n", "$\\newcommand{\\umin}[1]{\\underset{#1}{\\min}\\;}$\n", "$\\newcommand{\\uargmin}[1]{\\underset{#1}{argmin}\\;}$\n", "$\\newcommand{\\norm}[1]{\\|#1\\|}$\n", "$\\newcommand{\\abs}[1]{\\left|#1\\right|}$\n", "$\\newcommand{\\choice}[1]{ \\left\\{ \\begin{array}{l} #1 \\end{array} \\right. }$\n", "$\\newcommand{\\pa}[1]{\\left(#1\\right)}$\n", "$\\newcommand{\\diag}[1]{{diag}\\left( #1 \\right)}$\n", "$\\newcommand{\\qandq}{\\quad\\text{and}\\quad}$\n", "$\\newcommand{\\qwhereq}{\\quad\\text{where}\\quad}$\n", "$\\newcommand{\\qifq}{ \\quad \\text{if} \\quad }$\n", "$\\newcommand{\\qarrq}{ \\quad \\Longrightarrow \\quad }$\n", "$\\newcommand{\\ZZ}{\\mathbb{Z}}$\n", "$\\newcommand{\\CC}{\\mathbb{C}}$\n", "$\\newcommand{\\RR}{\\mathbb{R}}$\n", "$\\newcommand{\\EE}{\\mathbb{E}}$\n", "$\\newcommand{\\Zz}{\\mathcal{Z}}$\n", "$\\newcommand{\\Ww}{\\mathcal{W}}$\n", "$\\newcommand{\\Vv}{\\mathcal{V}}$\n", "$\\newcommand{\\Nn}{\\mathcal{N}}$\n", "$\\newcommand{\\NN}{\\mathcal{N}}$\n", "$\\newcommand{\\Hh}{\\mathcal{H}}$\n", "$\\newcommand{\\Bb}{\\mathcal{B}}$\n", "$\\newcommand{\\Ee}{\\mathcal{E}}$\n", "$\\newcommand{\\Cc}{\\mathcal{C}}$\n", "$\\newcommand{\\Gg}{\\mathcal{G}}$\n", "$\\newcommand{\\Ss}{\\mathcal{S}}$\n", "$\\newcommand{\\Pp}{\\mathcal{P}}$\n", "$\\newcommand{\\Ff}{\\mathcal{F}}$\n", "$\\newcommand{\\Xx}{\\mathcal{X}}$\n", "$\\newcommand{\\Mm}{\\mathcal{M}}$\n", "$\\newcommand{\\Ii}{\\mathcal{I}}$\n", "$\\newcommand{\\Dd}{\\mathcal{D}}$\n", "$\\newcommand{\\Ll}{\\mathcal{L}}$\n", "$\\newcommand{\\Tt}{\\mathcal{T}}$\n", "$\\newcommand{\\si}{\\sigma}$\n", "$\\newcommand{\\al}{\\alpha}$\n", "$\\newcommand{\\la}{\\lambda}$\n", "$\\newcommand{\\ga}{\\gamma}$\n", "$\\newcommand{\\Ga}{\\Gamma}$\n", "$\\newcommand{\\La}{\\Lambda}$\n", "$\\newcommand{\\si}{\\sigma}$\n", "$\\newcommand{\\Si}{\\Sigma}$\n", "$\\newcommand{\\be}{\\beta}$\n", "$\\newcommand{\\de}{\\delta}$\n", "$\\newcommand{\\De}{\\Delta}$\n", "$\\newcommand{\\phi}{\\varphi}$\n", "$\\newcommand{\\th}{\\theta}$\n", "$\\newcommand{\\om}{\\omega}$\n", "$\\newcommand{\\Om}{\\Omega}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This numerical tour studies source coding using entropic coders (Huffman and arithmetic)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Method definition ndgrid(AbstractArray{T<:Any, 1}) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:3 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:3.\n", "WARNING: Method definition ndgrid(AbstractArray{#T<:Any, 1}, AbstractArray{#T<:Any, 1}) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:6 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:6.\n", "WARNING: Method definition ndgrid_fill(Any, Any, Any, Any) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:13 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:13.\n", "WARNING: Method definition ndgrid(AbstractArray{#T<:Any, 1}...) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:19 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:19.\n", "WARNING: Method definition meshgrid(AbstractArray{T<:Any, 1}) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:33 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:33.\n", "WARNING: Method definition meshgrid(AbstractArray{#T<:Any, 1}, AbstractArray{#T<:Any, 1}) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:36 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:36.\n", "WARNING: Method definition meshgrid(AbstractArray{#T<:Any, 1}, AbstractArray{#T<:Any, 1}, AbstractArray{#T<:Any, 1}) in module NtToolBox at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:44 overwritten at /Users/quentin/.julia/v0.5/NtToolBox/src/ndgrid.jl:44.\n" ] } ], "source": [ "using PyPlot\n", "using NtToolBox" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Source Coding and Entropy\n", "-------------------------\n", "Entropic coding converts a vector $x$ of integers into a binary stream\n", "$y$. Entropic coding exploits the\n", "redundancies in the statistical distribution of the entries of $x$ to\n", "reduce as much as possible the size of $y$. The lower bound for the\n", "number of bits $p$ of $y$ is the Shannon bound :\n", "\n", "$$p=-\\sum_ih(i)\\log_2(h(i))$$\n", "\n", "where $h(i)$ is the probability of apparition of symbol $i$ in $x$.\n", "\n", "Fist we generate a simple binary signal $x$ so that $0$ has a probability $p$\n", "to appear in $x$.\n", "\n", "Probability of 0." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "p = 0.1;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Size.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "n = 512;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Signal, should be with token 1,2." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "x = (rand(n) .> p) + 1;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can check the probabilities by computing the empirical histogram." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Empirical p = 0.0859375" ] } ], "source": [ "h = [sum(x .== 1); sum(x .== 2)]\n", "h = h/sum(h)\n", "\n", "print(\"Empirical p = $(h[1])\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can compute the entropy of the distribution represented as a vector $h$ of proability that should sum to 1.\n", "We take a max to avoid problems with null probabilties." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Entropy = 0.42276234377915156" ] } ], "source": [ "e = - sum(h.*log2([max(e,1e-20) for e in h]))\n", "print(\"Entropy = $e\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Huffman Coding\n", "--------------\n", "A Hufman code $C$ associates to each symbol $i$ in $\\{1,...,m\\}$ a binary code $C_i$\n", "whose length is as close as possible to the optimal bound\n", "$-\\log_2\\left(h(i)\\right)$, where $h(i)$ is the probability of apparition of the\n", "symbol $i$.\n", "\n", "We select a set of proabilities." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "h = [.1, .15, .4, .15, .2];" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The tree $T$ contains the codes and is generated by an iterative algorithm.\n", "The initial \"tree\" is a collection of empty trees, pointing to the symbols numbers." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "m = length(h)\n", "T=Array{Any,1}(zeros(m)); # create an empty tree" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We build iteratively the Huffman tree\n", "by grouping together the two erees that have the smallest probabilities.\n", "The merged tree has a probability which is the sum of the two selected\n", "probabilities.\n", "\n", "Initial probability." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "#we use the symbols i = 0,1,2,3,4 (as strings) with the associated probabilities h(i)\n", "\n", "for i in 1:m\n", " T[i] = (h[i],string(i))\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Iterative merging of the leading probabilities." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": true }, "outputs": [], "source": [ "while length(T) > 1\n", "\n", " sort!(T) #sort according to the first values of the tuples (the probabilities)\n", " t = tuple(T[1:2]...)\n", " q = T[1][1] + T[2][1]\n", " T = [T[3:end]; [(q,t)]]\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We trim the computed tree by removing the probabilities." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "function trim(T)\n", " T0 = T[2]\n", " if typeof(T0) == String\n", " return T0\n", " else\n", " return (trim(T0[1]),trim(T0[2]))\n", " end\n", "end\n", "T = trim(T[1]);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We display the computed tree." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "PyPlot.Figure(PyObject )" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_hufftree(T);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once the tree $T$ is computed, one can compute the code $C_{i}$\n", "associated to each symbol $i$. This requires to perform a deep first\n", "search in the tree and stop at each node." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "codes = Dict()\n", "\n", "function huffman_gencode(T,codes,c)\n", " if typeof(T) == String #test if T is a leaf\n", " codes[T] = c\n", " else\n", " huffman_gencode(T[1],codes, string(c, \"0\"))\n", " huffman_gencode(T[2],codes, string(c, \"1\"))\n", " end\n", "end\n", "\n", "huffman_gencode(T,codes,\"\") ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Display the code." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Code of token 4: 110\n", "Code of token 1: 100\n", "Code of token 5: 111\n", "Code of token 2: 101\n", "Code of token 3: 0\n" ] } ], "source": [ "for e in keys(codes)\n", " println(string(\"Code of token \", e, \": \", codes[e]))\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We draw a vector $x$ according to the distribution $h$.\n", "\n", "Size of the signal." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "n = 1024;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Randomization." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "function rand_discr(p; m = 1)\n", " \"\"\"\n", " rand_discr - discrete random generator \n", " \n", " y = rand_discr(p, n);\n", " \n", " y is a random vector of length n drawn from \n", " a variable X such that\n", " p(i) = Prob( X=i )\n", " \n", " Copyright (c) 2004 Gabriel Peyré\n", " \"\"\"\n", "\n", " # makes sure it sums to 1\n", " p = p/sum(p)\n", " \n", " n = length(p)\n", " coin = rand(m)\n", " cumprob = [0.]\n", " append!(cumprob, cumsum(p))\n", " sample = zeros(m)\n", " \n", " for j in 1:n\n", " ind = find((coin .> cumprob[j]) & (coin .<= cumprob[j+1]))\n", " sample[ind] = j\n", " end\n", " return sample\n", "end\n", "\n", "x = rand_discr(h, m=n);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Exercise 1__\n", "\n", "Implement the coding of the vector $x$ to obtain a binary vector $y$, which corresponds to replacing each sybmol $x(i)$ by the code $C_{x(i)}$." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "include(\"NtSolutions/coding_2_entropic/exo1.jl\")" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "## Insert your code here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compare the length of the code with the entropy bound." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Entropy bound = 2197.9538889431196\n", "Huffman code = 2250\n" ] } ], "source": [ "e = - sum(h.*log2([max(e,1e-20) for e in h]))\n", "println(\"Entropy bound = $(n*e)\")\n", "println(\"Huffman code = $(length(y))\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Decoding is more complicated, since it requires to iteratively parse the tree $T$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initial empty decoded stream." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "x1 = [];" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Perform decoding." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "T0 = T\n", "for e in y\n", " if e == '0'\n", " T0 = T0[1]\n", " else\n", " T0 = T0[2]\n", " end\n", " if typeof(T0) == String\n", " append!(x1,T0)\n", " T0 = T\n", " end\n", "end\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We test if the decoding is correct." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error (should be zero) : 0.0" ] } ], "source": [ "err = norm(x-map(x->parse(Int, x), x1))\n", "print(\"Error (should be zero) : $err\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Huffman Block Coding\n", "--------------------\n", "A Huffman coder is inefficient because it can distribute only an integer\n", "number of bit per symbol. In particular, distribution where one of the\n", "symbol has a large probability are not well coded using a Huffman code.\n", "This can be aleviated by replacing the set of $m$ symbols by $m^q$\n", "symbols obtained by packing the symbols by blocks of $q$ (here we use $m=2$ for a binary alphabet). This breaks\n", "symbols with large probability into many symbols with smaller proablity,\n", "thus approaching the Shannon entropy bound.\n", "\n", "\n", "Generate a binary vector with a high probability of having 1, so that the\n", "Huffman code is not very efficient (far from Shanon bound).\n", "\n", "Proability of having 0." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "t = .12;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Probability distriution." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "h = [t, 1-t];" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Generate signal." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "n = 4096*2\n", "x = (rand(n) .> t) + 1;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For block of length $q=3$, create a new vector by coding each block\n", "with an integer in $\\{1,...,m^q=2^3\\}$. The new length of the vector is\n", "$n_1/q$ where $n_1=\\lceil n/q\\rceil q$.\n", "\n", "Block size." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "q = 3;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Maximum token value." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "m = 2;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "New size." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "n1 = Int(ceil(n/q)*q);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "New vector." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "x1 = zeros(n1)\n", "x1[1:length(x)] = x\n", "x1[length(x)+1:end] = 1\n", "x1 = x1 - 1\n", "x2 = []\n", "\n", "mult = [m^j for j in 0:q-1]\n", "for i in 1:q:n1-1\n", " append!(x2,sum(x1[i:i+q-1].*mult)+1)\n", "end" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "H = h\n", "for i in 1:q-1\n", " Hold = H\n", " H = []\n", " for j in 1:length(h)\n", " append!(H,[e*h[j] for e in Hold])\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simpler way to compute this block-histogram is to use the Kronecker product." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "H = h\n", "for i in 1:q-1\n", " H = kron(H, h)\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Exercise 2__\n", "\n", "For various values of block size $k$, Perform the Huffman coding and compute the length of the code.\n", "Compare with the entropy lower bound." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Entropy bound = 0.5293608652873644\n", "---\n", "Huffman(block size = 1) = 1.0\n", "Huffman(block size = 2) = 0.680419921875\n", "Huffman(block size = 3) = 0.5821533203125\n", "Huffman(block size = 4) = 0.55712890625\n", "Huffman(block size = 5) = 0.551025390625\n", "Huffman(block size = 6) = 0.5479736328125\n", "Huffman(block size = 7) = 0.556396484375\n", "Huffman(block size = 8) = 0.55126953125\n", "Huffman(block size = 9) = 0.5484619140625\n" ] }, { "data": { "image/png": "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Tz5Z6bklJSUXFPrtfU+dqfzKWMXPUVFR0QX9DdvzeXLm+4r6hStpwFmMHTtWs2bN0tixY9W9e3d9/fXX1qsRrjRo0CC98847CgkJUceOHbVx40atXbtWjRo1cvhr+fn5afXq1Ro9erR69uypTz/9VB9//LEefvjhsw7bPPXUU/r888916aWX6t5775WXl5dee+01FRYW2vSeeuCBB7R8+XINHTpUd955p7p166YTJ07oo48+0vz589W1a9dK554wYYJycnL0yCOPKCQkRA8//HC1dYwaNUpvv/22kpKS9MMPP+iyyy7TqVOntHbtWt1777264YYbdP311+uKK67QI488on379qlr16767LPP9OGHH2ry5MnWOWjx8fEaMWKEXnnlFWVnZ6t3795KTk42dIXLHv/4xz/07rvv6qqrrtLEiROtLTiio6N14sQJuxrk2vN769u3r8aNG6eZM2dq8+bNuvrqq+Xt7a2dO3fqgw8+0Ny5c3XLLbec189g73vqTL1791ZYWJhGjx6tSZMmyWQy6Z133rmgoWV7Pk/OfF9RvxDSgLOYNm2aMjMztXz5ci1btkwDBw7Up59+Wu2E4Joyd+5ceXp6avHixSooKFCfPn20du1au1feGeHp6anVq1frnnvu0QMPPKAGDRpo+vTpmjZt2lmfFxcXp2+++UZTp07VzJkzZTab1bNnT7377rs2q1eDgoL0zTffaPr06frPf/6jf//732rcuLGuvPJKtWjRotrzP/zww8rOzrYGtb///e/V1v/JJ5/o6aef1pIlS7RixQo1atRIl156qTp37iypbJL9Rx99pGnTpmnp0qVauHChWrZsqWeffVZTpkyxOd+CBQsUERGhxYsXa9WqVfrLX/6ijz/+uNIk9gsRFRWldevWadKkSfrnP/+p8PBwjR8/XsHBwbrvvvvk5+d3znPY+3ubP3++unXrptdee00PP/ywvLy81LJlS40cOVJ9+vQ575/ByHvqLI0aNdL//vc/TZkyRY8++qjCwsI0cuRIXXnllef9t2LP50ly3vuK+sVkqW0zhwGgnpo8ebJee+015eXlVTvJXSrbcWD58uXKy8urweoAOBpz0gDADZXvi1nu+PHjeuedd3TppZeeNaABqDsY7gQAN9SrVy/169dPHTp0UHp6ut566y3l5OTosccec3VpAGoIIQ0A3NC1116r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", "text/plain": [ "PyPlot.Figure(PyObject )" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Huffman(block size = 10) = 0.54736328125\n" ] } ], "source": [ "include(\"NtSolutions/coding_2_entropic/exo2.jl\");" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "## Insert your code here." ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 0.5.0", "language": "julia", "name": "julia-0.5" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "0.5.0" } }, "nbformat": 4, "nbformat_minor": 1 }