├── Enclosed_circle.png ├── JuliaCon2019_Huda ├── python_sum.py ├── hello_world.o ├── Fibo_externC.o ├── Fibo_externC.dylib ├── hello_world.dylib ├── hello_world_lib.dylib ├── Fibo_externC.cpp ├── hello_world.c ├── Makefile ├── Julia Wrappers.ipynb └── Performance Tips for Julia.ipynb ├── README.md ├── 00.Jupyter_notebooks.ipynb ├── 07.Packages.ipynb ├── 11.Basic_linear_algebra.ipynb ├── 02.Strings.ipynb ├── 01.Getting_started.ipynb ├── 05.Conditionals.ipynb ├── 06.Loops.ipynb ├── Monte_Carlo_calculation_of_pi.ipynb ├── 10.Multiple_dispatch.ipynb ├── 08.Plotting.ipynb ├── 12.Factorizations_and_other_fun.ipynb ├── 04.Functions.ipynb ├── 03.Data_structures.ipynb └── SOLUTIONS_Monte_Carlo_calculation_of_pi.ipynb /Enclosed_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/Enclosed_circle.png -------------------------------------------------------------------------------- /JuliaCon2019_Huda/python_sum.py: -------------------------------------------------------------------------------- 1 | def py_sum(A): 2 | s = 0.0 3 | for a in A: 4 | s += a 5 | return s -------------------------------------------------------------------------------- /JuliaCon2019_Huda/hello_world.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/JuliaCon2019_Huda/hello_world.o -------------------------------------------------------------------------------- /JuliaCon2019_Huda/Fibo_externC.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/JuliaCon2019_Huda/Fibo_externC.o -------------------------------------------------------------------------------- /JuliaCon2019_Huda/Fibo_externC.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/JuliaCon2019_Huda/Fibo_externC.dylib -------------------------------------------------------------------------------- /JuliaCon2019_Huda/hello_world.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/JuliaCon2019_Huda/hello_world.dylib -------------------------------------------------------------------------------- /JuliaCon2019_Huda/hello_world_lib.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xorJane/Excelling-at-Julia-Basics-and-Beyond/HEAD/JuliaCon2019_Huda/hello_world_lib.dylib -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Excelling-at-Julia-Basics-and-Beyond 2 | 3 | Aspirational schedule for July 22: 4 | 5 | 8:30 to 10:00 -- Intro to Julia 6 | 7 | 10:00 to 10:30 -- break/troubleshooting Julia installations 8 | 9 | 10:30 to 12:00 -- Code optimization 10 | -------------------------------------------------------------------------------- /JuliaCon2019_Huda/Fibo_externC.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" 4 | { 5 | int64_t Fibonacci_I(int64_t n) 6 | { 7 | int x = 0; 8 | int y = 1; 9 | int t; 10 | for(int i=1; i 2 | 3 | int hello_world() 4 | { 5 | printf("Hello, World!\n"); 6 | return 0; 7 | } 8 | 9 | int hello_world_repeated(int n) 10 | { 11 | for (int i = 0; i\n", 49 | "One difference is that, in the latter case, you can use quotation marks within your string." 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "\"Here, we get an \"error\" because it's ambiguous where this string ends \"" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "\"\"\"Look, Mom, no \"errors\"!!! \"\"\"" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "Note that ' ' define a character, but NOT a string!" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "typeof('a')" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "'We will get an error here'" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "## String interpolation\n", 100 | "\n", 101 | "We can use the $ sign to insert existing variables into a string and to evaluate expressions within a string.
\n", 102 | "Below is an example that contains some highly sensitive personal information." 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "name = \"Jane\"\n", 112 | "num_fingers = 10\n", 113 | "num_toes = 10" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": null, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "println(\"Hello, my name is $name.\")\n", 123 | "println(\"I have $num_fingers fingers and $num_toes toes.\")" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | " println(\"That is $(num_fingers + num_toes) digits in all!!\")" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "## String concatenation\n", 140 | "\n", 141 | "Below are three ways we can concatenate strings!

\n", 142 | "The first way is to use the `string()` function.
\n", 143 | "`string()` converts non-string inputs to strings." 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": null, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [ 152 | "s3 = \"How many cats \";\n", 153 | "s4 = \"is too many cats?\";\n", 154 | "😺 = 10" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "string(s3, s4)" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [ 172 | "string(\"I don't know, but \", 😺, \" is too few.\")" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "We can also use `*` for concatenation!" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "s3*s4" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "### Exercises\n", 196 | "\n", 197 | "#### 2.1 \n", 198 | "Create a string that says \"hi\" 1000 times, first with `repeat` and then with the exponentiation operator, which can call `*` under the hood." 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "#### 2.2 \n", 213 | "Declare two variables\n", 214 | "\n", 215 | "```julia\n", 216 | "a = 3\n", 217 | "b = 4\n", 218 | "```\n", 219 | "and use them to create two strings:\n", 220 | "```julia\n", 221 | "\"3 + 4\"\n", 222 | "\"7\"\n", 223 | "```" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "#### Bonus\n", 231 | "\n", 232 | "**2.3**\n", 233 | "\n", 234 | "Print a string that says, \"The value of pi is [insert value of pi up to at least 10 digits here]\" using Julia's built in variable, `pi`." 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": null, 240 | "metadata": {}, 241 | "outputs": [], 242 | "source": [] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": null, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [] 250 | } 251 | ], 252 | "metadata": { 253 | "kernelspec": { 254 | "display_name": "Julia 1.0.1", 255 | "language": "julia", 256 | "name": "julia-1.0" 257 | }, 258 | "language_info": { 259 | "file_extension": ".jl", 260 | "mimetype": "application/julia", 261 | "name": "julia", 262 | "version": "1.0.1" 263 | } 264 | }, 265 | "nbformat": 4, 266 | "nbformat_minor": 2 267 | } 268 | -------------------------------------------------------------------------------- /01.Getting_started.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Getting started\n", 8 | "\n", 9 | "Topics:\n", 10 | "1. How to print\n", 11 | "2. How to assign variables\n", 12 | "3. How to comment\n", 13 | "4. Syntax for basic math" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "## How to print\n", 21 | "\n", 22 | "In Julia we usually use `println()` to print" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "println(\"I'm excited to learn Julia!\")" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## How to assign variables\n", 39 | "\n", 40 | "All we need is a variable name, value, and an equal's sign!
\n", 41 | "Julia will figure out types for us." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "my_answer = 42\n", 51 | "typeof(my_answer)" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "my_pi = 3.14159\n", 61 | "typeof(my_pi)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "😺 = \"smiley cat!\"\n", 71 | "typeof(😺)" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "To type a smiley cat, use tab completion to select the emoji name and then tab again" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "# \\:smi + --> select with down arrow + ---> + to complete" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "After assigning a value to a variable, we can reassign a value of a different type to that variable without any issue." 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "😺 = 1" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "typeof(😺)" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "Note: Julia allows us to write super generic code, and 😺 is an example of this. \n", 120 | "\n", 121 | "This allows us to write code like" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "😀 = 0\n", 131 | "😞 = -1" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [ 140 | "😺 + 😞 == 😀" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "## How to comment" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "# You can leave comments on a single line using the pound/hash key" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "#=\n", 166 | "\n", 167 | "For multi-line comments, \n", 168 | "use the '#= =#' sequence.\n", 169 | "\n", 170 | "=#" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Syntax for basic math" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "sum = 3 + 7" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "difference = 10 - 3" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [ 204 | "product = 20 * 5" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": null, 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "quotient = 100 / 10" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": null, 219 | "metadata": {}, 220 | "outputs": [], 221 | "source": [ 222 | "power = 10 ^ 2" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "modulus = 101 % 2" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "### Exercises\n", 239 | "\n", 240 | "#### 1.1 \n", 241 | "Look up docs for the `convert` function." 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": null, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": {}, 254 | "source": [ 255 | "#### 1.2 \n", 256 | "Assign `365` to a variable named `days`. Convert `days` to a float." 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": null, 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "#### 1.3 \n", 271 | "See what happens when you execute\n", 272 | "\n", 273 | "```julia\n", 274 | "convert(Int64, \"1\")\n", 275 | "```\n", 276 | "and\n", 277 | "\n", 278 | "```julia\n", 279 | "parse(Int64, \"1\")\n", 280 | "```" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "#### Bonus\n", 288 | "\n", 289 | "**1.4**\n", 290 | "\n", 291 | "Use `rand` to generate an Array of 100 Integers with values between 1 and 10." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [] 300 | } 301 | ], 302 | "metadata": { 303 | "kernelspec": { 304 | "display_name": "Julia 1.0.1", 305 | "language": "julia", 306 | "name": "julia-1.0" 307 | }, 308 | "language_info": { 309 | "file_extension": ".jl", 310 | "mimetype": "application/julia", 311 | "name": "julia", 312 | "version": "1.0.1" 313 | } 314 | }, 315 | "nbformat": 4, 316 | "nbformat_minor": 2 317 | } 318 | -------------------------------------------------------------------------------- /05.Conditionals.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true 7 | }, 8 | "source": [ 9 | "# Conditionals\n", 10 | "\n", 11 | "#### with the `if` keyword\n", 12 | "In Julia, the syntax\n", 13 | "\n", 14 | "```julia\n", 15 | "if *condition 1*\n", 16 | " *option 1*\n", 17 | "elseif *condition 2*\n", 18 | " *option 2*\n", 19 | "else\n", 20 | " *option 3*\n", 21 | "end\n", 22 | "```\n", 23 | "\n", 24 | "allows us to conditionally evaluate one of our options.\n", 25 | "

\n", 26 | "For example, we might want to implement the FizzBuzz test: given a number, N, print \"Fizz\" if N is divisible by 3, \"Buzz\" if N is divisible by 5, and \"FizzBuzz\" if N is divisible by 3 and 5. Otherwise just print the number itself! Enter your choice for `N` here:" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "N = " 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "if (N % 3 == 0) && (N % 5 == 0) # `&&` means \"AND\"; % computes the remainder after division\n", 45 | " println(\"FizzBuzz\")\n", 46 | "elseif N % 3 == 0\n", 47 | " println(\"Fizz\")\n", 48 | "elseif N % 5 == 0\n", 49 | " println(\"Buzz\")\n", 50 | "else\n", 51 | " println(N)\n", 52 | "end" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "#### with ternary operators\n", 60 | "\n", 61 | "For this last block, we could instead use the ternary operator with the syntax\n", 62 | "\n", 63 | "```julia\n", 64 | "a ? b : c\n", 65 | "```\n", 66 | "\n", 67 | "which equates to \n", 68 | "\n", 69 | "```julia\n", 70 | "if a\n", 71 | " b\n", 72 | "else\n", 73 | " c\n", 74 | "end\n", 75 | "```" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "Now let's say we want to return the larger of two numbers. Give `x` and `y` values here:" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "x =\n", 92 | "y =" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "Using the `if` and `else` keywords, we might write:" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "if x > y\n", 109 | " x\n", 110 | "else\n", 111 | " y\n", 112 | "end" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "and as a ternary operator, the conditional looks like this:" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "(x > y) ? x : y" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "#### with short-circuit evaluation\n", 136 | "\n", 137 | "We've already seen expressions with the syntax\n", 138 | "```julia\n", 139 | "a && b\n", 140 | "```\n", 141 | "to return true if both `a` and `b` are true. Of course, if `a` is false, Julia doesn't even need to know the value of `b` in order to determine that the overall result will be false. So Julia doesn't even need to check what `b` is; it can just \"short-circuit\" and immediately return `false`. The second argument `b` might be a more complicated expression like a function call with a side-effect, in which case it won't even be called:" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "false && (println(\"hi\"); true)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [ 159 | "true && (println(\"hi\"); true)" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "On the other hand, if `a` is true, Julia knows it can just return the value of `b` as the overall expression. This means that `b` doesn't necessarily need evaluate to `true` or `false`! `b` could even be an error:" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [ 175 | "(x > 0) && error(\"x cannot be greater than 0\")" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "Similarly, check out the `||` operator, which also uses short-circuit evaluation to perform the \"or\" operation." 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "true || println(\"hi\")" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "and" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "false || println(\"hi\")" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": { 213 | "collapsed": true 214 | }, 215 | "source": [ 216 | "### Exercises\n", 217 | "\n", 218 | "#### 5.1 \n", 219 | "Write a conditional statement that prints a number if the number is even and the string \"odd\" if the number is odd." 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "#### 5.2 \n", 234 | "Rewrite the code from 5.1 using a ternary operator." 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": null, 240 | "metadata": {}, 241 | "outputs": [], 242 | "source": [] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": {}, 247 | "source": [ 248 | "#### Bonus\n", 249 | "\n", 250 | "**5.3**\n", 251 | "\n", 252 | "Given variables `x` and `y` defining a point $(x, y)$, write a conditional statement that prints \"Less than 1!\" if the distance of $(x, y)$ from $(0, 0)$ is less than 1." 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "metadata": {}, 259 | "outputs": [], 260 | "source": [ 261 | "x, y = rand(2)" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": null, 267 | "metadata": {}, 268 | "outputs": [], 269 | "source": [] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "#### 5.4 -- combine conditional and function practice!\n", 276 | "\n", 277 | "Write a function `inside_circle(x, y)` that takes coordinates/variables `x` and `y` and determines whether the point $(x, y)$ falls inside a circle of radius 1 that is centered at $(0, 0)$. Return `1` if the point falls within the circle and `0` if not.\n", 278 | "\n", 279 | "*Hint:* To fall within the circle, the distance of the point to the circle's center should be less than the radius." 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": null, 285 | "metadata": {}, 286 | "outputs": [], 287 | "source": [] 288 | } 289 | ], 290 | "metadata": { 291 | "kernelspec": { 292 | "display_name": "Julia 1.0.1", 293 | "language": "julia", 294 | "name": "julia-1.0" 295 | }, 296 | "language_info": { 297 | "file_extension": ".jl", 298 | "mimetype": "application/julia", 299 | "name": "julia", 300 | "version": "1.0.1" 301 | } 302 | }, 303 | "nbformat": 4, 304 | "nbformat_minor": 2 305 | } 306 | -------------------------------------------------------------------------------- /06.Loops.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true 7 | }, 8 | "source": [ 9 | "# Loops\n", 10 | "\n", 11 | "Topics:\n", 12 | "1. `while` loops\n", 13 | "2. `for` loops\n", 14 | "
\n", 15 | "\n", 16 | "## while loops\n", 17 | "\n", 18 | "The syntax for a `while` is\n", 19 | "\n", 20 | "```julia\n", 21 | "while *condition*\n", 22 | " *loop body*\n", 23 | "end\n", 24 | "```\n", 25 | "\n", 26 | "For example, we could use `while` to count or to iterate over an array." 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "n = 0\n", 36 | "while n < 10\n", 37 | " n += 1\n", 38 | " println(n)\n", 39 | "end\n", 40 | "n" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "myfriends = [\"Ted\", \"Robyn\", \"Barney\", \"Lily\", \"Marshall\"]\n", 50 | "\n", 51 | "i = 1\n", 52 | "while i <= length(myfriends)\n", 53 | " friend = myfriends[i]\n", 54 | " println(\"Hi $friend, it's great to see you!\")\n", 55 | " i += 1\n", 56 | "end" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "## for loops\n", 64 | "\n", 65 | "The syntax for a `for` loop is\n", 66 | "\n", 67 | "```julia\n", 68 | "for *var* in *loop iterable*\n", 69 | " *loop body*\n", 70 | "end\n", 71 | "```\n", 72 | "\n", 73 | "We could use a for loop to generate the same results as either of the examples above:" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "for n in 1:10\n", 83 | " println(n)\n", 84 | "end" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "myfriends = [\"Ted\", \"Robyn\", \"Barney\", \"Lily\", \"Marshall\"]\n", 94 | "\n", 95 | "for friend in myfriends\n", 96 | " println(\"Hi $friend, it's great to see you!\")\n", 97 | "end" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "Now let's use `for` loops to create some addition tables, where the value of every entry is the sum of its row and column indices.
\n", 105 | "\n", 106 | "First, we initialize an array with zeros." 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "m, n = 5, 5\n", 116 | "A = fill(0, (m, n))" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "for i in 1:m\n", 126 | " for j in 1:n\n", 127 | " A[i, j] = i + j\n", 128 | " end\n", 129 | "end\n", 130 | "A" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "Here's some syntactic sugar for the same nested `for` loop" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "B = fill(0, (m, n))" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "for i in 1:m, j in 1:n\n", 156 | " B[i, j] = i + j\n", 157 | "end\n", 158 | "B" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "The more \"Julia\" way to create this addition table would have been with an *array comprehension*.\n", 166 | "\n", 167 | "Array comprehensions allow us to create and populate arrays on the fly. For example, in" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "metadata": {}, 174 | "outputs": [], 175 | "source": [ 176 | "[i for i in 1:10]" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "we create an array that contains integers between 1 and 10 by putting a `for` loop inside square brackets, `[ ]`, rather than the elements we want the array to contain.\n", 184 | "\n", 185 | "Here's how we create our additional table with an array comprehension:" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "C = [i + j for i in 1:m, j in 1:n]" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "Note this is the first of three additional table examples where we didn't first have to initialize an array before populating it with the desired values!" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "### Exercises\n", 209 | "\n", 210 | "#### 6.1 \n", 211 | "Loop over integers between 1 and 100 and print their squares." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": {}, 224 | "source": [ 225 | "#### 6.2 \n", 226 | "Add to the code above a bit to create a dictionary, `squares` that holds integers and their squares as key, value pairs such that\n", 227 | "\n", 228 | "```julia\n", 229 | "squares[10] == 100\n", 230 | "```" 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": null, 236 | "metadata": {}, 237 | "outputs": [], 238 | "source": [] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": { 243 | "collapsed": true 244 | }, 245 | "source": [ 246 | "#### 6.3 \n", 247 | "Use an array comprehension to create an an array that stores the squares for all integers between 1 and 100." 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "#### Bonus\n", 262 | "\n", 263 | "**6.4**\n", 264 | "\n", 265 | "Use a loop to generate 100 random points $(x_i, y_i)$ where $-1.0 <= x <= 1.0$ and $-1.0 <= y <= 1.0$. Print the number of times the points fell within a circle of radius 1, centered at $(0, 0)$." 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "**6.5**\n", 280 | "\n", 281 | "Use an array comprehension to create an array of 100 points in 2D Cartesian space." 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": null, 287 | "metadata": {}, 288 | "outputs": [], 289 | "source": [] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "**6.6**\n", 296 | "\n", 297 | "Use an array comprehension to create an array of the distances of 100 points in 2D Cartesian space from a point at $(0, 0)$.\n", 298 | "\n", 299 | "*Hint:* You may find \"splat\", i.e. `...`, useful here. Adding `...` after a collection passed as an input argument to a function \"opens up\" that collection, passing each of the elements of the collection as inputs to the function. For example, if\n", 300 | "\n", 301 | "```\n", 302 | "a = [1, 2, 3]\n", 303 | "add_three_things(x, y, z) = x + y + z\n", 304 | "```\n", 305 | "then `add_three_things(a)` will give an error, but `add_three_things(a...)` will yield `6`, just as if you had run `add_three_things(a[1], a[2], a[3])`" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [] 314 | } 315 | ], 316 | "metadata": { 317 | "kernelspec": { 318 | "display_name": "Julia 1.0.1", 319 | "language": "julia", 320 | "name": "julia-1.0" 321 | }, 322 | "language_info": { 323 | "file_extension": ".jl", 324 | "mimetype": "application/julia", 325 | "name": "julia", 326 | "version": "1.0.1" 327 | } 328 | }, 329 | "nbformat": 4, 330 | "nbformat_minor": 2 331 | } 332 | -------------------------------------------------------------------------------- /Monte_Carlo_calculation_of_pi.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Monte Carlo determination of $\\pi$\n", 8 | "\n", 9 | "Imagine that we have a circle of radius 1 ($r = 1$), centered at the point $(0, 0)$ in Cartesian coordinates.\n", 10 | "\n", 11 | "We can further imagine that circle being enclosed by a square with the same center and with sides of length $2r$, in this case 2.\n", 12 | "\n", 13 | "\"Drawing\"\n", 14 | "\n", 15 | "\n", 16 | "Given a square with sides of length $2r$, the square's area is\n", 17 | "\n", 18 | "$$A_{square} = (2r)^2 = 4r^2$$\n", 19 | "\n", 20 | "whereas the area of a circle with radius $r$ is\n", 21 | "$$A_{circle} = \\pi r^2$$\n", 22 | "\n", 23 | "Therefore the ratio of the area of the circle to that of the enclosing square is\n", 24 | "\n", 25 | "$$\\frac{A_{circle}}{A_{square}} = \\frac{\\pi r^2}{4r^2} = \\frac{\\pi}{4}$$.\n", 26 | "\n", 27 | "By rearranging this expression, we see we can define $\\pi$ as\n", 28 | "\n", 29 | "$$\\pi = 4\\frac{A_{circle}}{A_{square}}$$\n", 30 | "\n", 31 | "**And *this* suggests a way to calculate $\\pi$!**\n", 32 | "\n", 33 | "If we're able to figure out the ratio of the areas of a circle and the smallest square that can hold that circle, we can figure out $\\pi$. And fortunately, this ratio is equal to the probability that a randomly chosen point inside the square also falls inside the circle. \n", 34 | "\n", 35 | "This means that we can calculate this ratio (and therefore $\\pi$) using a Monte Carlo simulation by choosing a large number of random points inside a square and tracking how many fall inside the circle.\n", 36 | "\n", 37 | "#### Pseudo-code\n", 38 | "\n", 39 | "Given the above, our algorithm for determining $\\pi$ looks like this:\n", 40 | "\n", 41 | "1. For each of $N$ iterations,\n", 42 | " 1. Select a random point inside the square depicted above.\n", 43 | " 1. Determine if the point also falls inside the largest circle that can be enclosed within this square.\n", 44 | " 1. Keep track of whether or not this point fell inside the circle. At the end of $N$ iterations, you want to know $M$ -- the number of the $N$ random points that fell inside the circle!\n", 45 | "1. Calculate $\\pi$ as $4\\frac{M}{N}$\n", 46 | "\n", 47 | "Note: As you increase the value of $N$, you'll be able to estimate pi with greater accuracy!\n", 48 | "\n", 49 | "### Exercise\n", 50 | "\n", 51 | "Write a function that calculates $\\pi$ using Julia.\n", 52 | "\n", 53 | "Feel free to get started immediately, or to make use of the practice exercises below which have you solve pieces of the problem one at a time." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "### Function practice\n", 89 | "\n", 90 | "#### Exercise\n", 91 | "\n", 92 | "Given variables `x` and `y` defining a point $(x, y)$, write a function `dist(x, y)` that returns the distance of $(x, y)$ from $(0, 0)$." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "#### Exercise\n", 121 | "\n", 122 | "Write a function `myrand` that returns `(x, y)`, where `x` and `y` are pseudo-random numbers uniformly distributed between -1 and +1.\n", 123 | "\n", 124 | "*Hint:* The `rand()` function returns a random number between 0 and 1. Passing a collection as the first argument of `rand` will cause `rand` to return a random value from amongst the elements of the collection.\n", 125 | "\n", 126 | "Ex. rand(animals) will return one of the strings contained in `animals`:" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": null, 132 | "metadata": {}, 133 | "outputs": [], 134 | "source": [ 135 | "animals = [\"cat\", \"dog\", \"bird\"]\n", 136 | "rand(animals)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": null, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "### Conditional practice\n", 158 | "\n", 159 | "#### Exercise\n", 160 | "\n", 161 | "Given variables `x` and `y` defining a point $(x, y)$, write a conditional statement that prints \"Less than 1!\" if the distance of $(x, y)$ from $(0, 0)$ is less than 1." 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "x, y = rand(2)" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "#### Exercise\n", 192 | "\n", 193 | "Write a function `inside_circle(x, y)` that takes coordinates/variables `x` and `y` and determines whether the point $(x, y)$ falls inside a circle of radius 1 that is centered at $(0, 0)$. Return `1` if the point falls within the circle and `0` if not.\n", 194 | "\n", 195 | "*Hint:* To fall within the circle, the distance of the point to the circle's center should be less than the radius." 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "### Loop practice" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "#### Exercise\n", 224 | "\n", 225 | "Use a loop to generate 100 random points $(x_i, y_i)$ where $-1.0 <= x <= 1.0$ and $-1.0 <= y <= 1.0$. Print the number of times the points fell within a circle of radius 1, centered at $(0, 0)$." 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": {}, 232 | "outputs": [], 233 | "source": [] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "### Array practice" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "#### Exercise\n", 254 | "\n", 255 | "Use an array comprehension to create an array of 100 points in 2D Cartesian space." 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": null, 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "#### Exercise\n", 277 | "\n", 278 | "Use an array comprehension to create an array of the distances of 100 points in 2D Cartesian space from a point at $(0, 0)$.\n", 279 | "\n", 280 | "*Hint:* You may find \"splat\", i.e. `...`, useful here. Adding `...` after a collection passed as an input argument to a function \"opens up\" that collection, passing each of the elements of the collection as inputs to the function. For example, if\n", 281 | "\n", 282 | "```\n", 283 | "a = [1, 2, 3]\n", 284 | "add_three_things(x, y, z) = x + y + z\n", 285 | "```\n", 286 | "then `add_three_things(a)` will give an error, but `add_three_things(a...)` will yield `6`, just as if you had run `add_three_things(a[1], a[2], a[3])`" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": null, 299 | "metadata": {}, 300 | "outputs": [], 301 | "source": [] 302 | } 303 | ], 304 | "metadata": { 305 | "kernelspec": { 306 | "display_name": "Julia 1.0.1", 307 | "language": "julia", 308 | "name": "julia-1.0" 309 | }, 310 | "language_info": { 311 | "file_extension": ".jl", 312 | "mimetype": "application/julia", 313 | "name": "julia", 314 | "version": "1.0.1" 315 | } 316 | }, 317 | "nbformat": 4, 318 | "nbformat_minor": 2 319 | } 320 | -------------------------------------------------------------------------------- /10.Multiple_dispatch.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Multiple dispatch" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "In this notebook we'll explore **multiple dispatch**, which is a key feature of Julia.\n", 15 | "\n", 16 | "Multiple dispatch makes software *generic* and *fast*!\n", 17 | "\n", 18 | "#### Starting with the familiar\n", 19 | "\n", 20 | "To understand multiple dispatch in Julia, let's start with what we've already seen.\n", 21 | "\n", 22 | "We can declare functions in Julia without giving Julia any information about the types of the input arguments that function will receive:" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "f(x) = x^2" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "and then Julia will determine on its own which input argument types make sense and which do not:" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "f(10)" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "f([1, 2, 3])" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "#### Specifying the types of our input arguments\n", 64 | "\n", 65 | "However, we also have the *option* to tell Julia explicitly what types our input arguments are allowed to have.\n", 66 | "\n", 67 | "For example, let's write a function `foo` that only takes strings as inputs." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "foo(x::String, y::String) = println(\"My inputs x and y are both strings!\")" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "We see here that in order to restrict the type of `x` and `y` to `String`s, we just follow the input argument name by a double colon and the keyword `String`.\n", 84 | "\n", 85 | "Now we'll see that `foo` works on `String`s and doesn't work on other input argument types." 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "foo(\"hello\", \"hi!\")" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "foo(3, 4)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "To get `foo` to work on integer (`Int`) inputs, let's tack `::Int` onto our input arguments when we declare `foo`." 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "foo(x::Int, y::Int) = println(\"My inputs x and y are both integers!\")" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "foo(3, 4)" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "Now `foo` works on integers! But look, `foo` also still works when `x` and `y` are strings!" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "foo(\"hello\", \"hi!\")" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "This is starting to get to the heart of multiple dispatch. When we declared\n", 152 | "\n", 153 | "```julia\n", 154 | "foo(x::Int, y::Int) = println(\"My inputs x and y are both integers!\")\n", 155 | "```\n", 156 | "we didn't overwrite or replace\n", 157 | "```julia\n", 158 | "foo(y::String, y::String)```\n", 159 | "\n", 160 | "Instead, we just added an additional ***method*** to the ***generic function*** called `foo`.\n", 161 | "\n", 162 | "A ***generic function*** is the abstract concept associated with a particular operation.\n", 163 | "\n", 164 | "For example, the generic function `+` represents the concept of addition.\n", 165 | "\n", 166 | "A ***method*** is a specific implementation of a generic function for *particular argument types*.\n", 167 | "\n", 168 | "For example, `+` has methods that accept floating point numbers, integers, matrices, etc.\n", 169 | "\n", 170 | "We can use the `methods` to see how many methods there are for `foo`." 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "methods(foo)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "Aside: how many methods do you think there are for addition?" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "methods(+)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "So, we now can call `foo` on integers or strings. When you call `foo` on a particular set of arguments, Julia will infer the types of the inputs and dispatch the appropriate method. *This* is multiple dispatch.\n", 203 | "\n", 204 | "Multiple dispatch makes our code generic and fast. Our code can be generic and flexible because we can write code in terms of abstract operations such as addition and multiplication, rather than in terms of specific implementations. At the same time, our code runs quickly because Julia is able to call efficient methods for the relevant types.\n", 205 | "\n", 206 | "To see which method is being dispatched when we call a generic function, we can use the @which macro:" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "@which foo(3, 4)" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "Let's see what happens when we use `@which` with the addition operator!" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "@which 3.0 + 3.0" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "And we can continue to add other methods to our generic function `foo`. Let's add one that takes the ***abstract type*** `Number`, which includes subtypes such as `Int`, `Float64`, and other objects you would think of as numbers:" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "foo(x::Number, y::Number) = println(\"My inputs x and y are both numbers!\")" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "This method for `foo` will work on, for example, floating point numbers:" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": {}, 261 | "outputs": [], 262 | "source": [ 263 | "foo(3.0, 4.0)" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "We can also add a fallback, duck-typed method for `foo` that takes inputs of any type:" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": {}, 277 | "outputs": [], 278 | "source": [ 279 | "foo(x, y) = println(\"I accept inputs of any type!\")" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "Given the methods we've already written for `foo` so far, this method will be called whenever we pass non-numbers to `foo`:" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "v = rand(3)\n", 296 | "foo(v, v)" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": { 302 | "collapsed": true 303 | }, 304 | "source": [ 305 | "### Exercises\n", 306 | "\n", 307 | "#### 9.1\n", 308 | "\n", 309 | "Extend the function `foo`, adding a method that takes only one input argument, which is of type `Bool`, and prints \"foo with one boolean!\"" 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": null, 315 | "metadata": {}, 316 | "outputs": [], 317 | "source": [] 318 | }, 319 | { 320 | "cell_type": "markdown", 321 | "metadata": {}, 322 | "source": [ 323 | "#### 9.2\n", 324 | "\n", 325 | "Check that the method being dispatched when you execute \n", 326 | "```julia\n", 327 | "foo(true)\n", 328 | "```\n", 329 | "is the one you wrote." 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": null, 335 | "metadata": {}, 336 | "outputs": [], 337 | "source": [] 338 | } 339 | ], 340 | "metadata": { 341 | "anaconda-cloud": {}, 342 | "kernelspec": { 343 | "display_name": "Julia 1.0.0", 344 | "language": "julia", 345 | "name": "julia-1.0" 346 | }, 347 | "language": "Julia", 348 | "language_info": { 349 | "file_extension": ".jl", 350 | "mimetype": "application/julia", 351 | "name": "julia", 352 | "version": "1.0.0" 353 | }, 354 | "toc": { 355 | "nav_menu": { 356 | "height": "119px", 357 | "width": "251px" 358 | }, 359 | "navigate_menu": true, 360 | "number_sections": true, 361 | "sideBar": true, 362 | "threshold": "2", 363 | "toc_cell": false, 364 | "toc_section_display": "block", 365 | "toc_window_display": false 366 | } 367 | }, 368 | "nbformat": 4, 369 | "nbformat_minor": 1 370 | } 371 | -------------------------------------------------------------------------------- /08.Plotting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Plotting\n", 8 | "\n", 9 | "## Basics\n", 10 | "There are a few different ways to plot in Julia (including calling PyPlot).
\n", 11 | "\n", 12 | "Here we'll show you how to use `Plots.jl`. If it's not installed yet, you need to use the package manager to install it, and Julia will precompile it for you the first time you use it:" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": null, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "# using Pkg\n", 22 | "# Pkg.add(\"Plots\")\n", 23 | "using Plots" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "One of the advantages to `Plots.jl` is that it allows you to seamlessly change backends. In this notebook, we'll try out the `gr()`, `pyplot()`, and `unicodeplots()` backends.
\n", 31 | "\n", 32 | "In the name of scientific inquiry, let's use this notebook to examine the relationship between the global temperature and the number of pirates between roughly 1860 and 2000." 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "globaltemperatures = [14.4, 14.5, 14.8, 15.2, 15.5, 15.8]\n", 42 | "numpirates = [45000, 20000, 15000, 5000, 400, 17];" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "Plots supports multiple backends — that is, libraries that actually do the drawing — all with the same API. To start out, let's try the GR backend. You choose it with a call to `gr()`:" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "gr()" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "and now we can use commands like `plot` and `scatter` to generate plots." 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "plot(numpirates, globaltemperatures, label=\"line\") \n", 75 | "scatter!(numpirates, globaltemperatures, label=\"points\") " 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "The `!` at the end of the `scatter!` function name makes `scatter!` a mutating function, indicating that the scattered points will be added onto the pre-existing plot.\n", 83 | "\n", 84 | "In contrast, see what happens when you replace `scatter!` in the above with the non-mutating function `scatter`.\n", 85 | "\n", 86 | "Next, let's update this plot with the `xlabel!`, `ylabel!`, and `title!` commands to add more information to our plot." 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "xlabel!(\"Number of Pirates [Approximate]\")\n", 96 | "ylabel!(\"Global Temperature (C)\")\n", 97 | "title!(\"Influence of pirate population on global warming\")" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "This still doesn't look quite right. The number of pirates has decreased since 1860, so reading the plot from left to right is like looking backwards in time rather than forwards. Let's flip the x axis to better see how pirate populations have caused global temperatures to change over time!" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "xflip!()" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "And there we have it!\n", 121 | "\n", 122 | "Note: We've had some confusion about this exercise. :) This is a joke about how people often conflate correlation and causation." 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "### Changing backends\n", 130 | "\n", 131 | "Without changing syntax, we can create the same plot with various backends" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [ 140 | "x = [i for i in 1:20]\n", 141 | "y = x .^ 2 / 2\n", 142 | ";" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": null, 148 | "metadata": {}, 149 | "outputs": [], 150 | "source": [ 151 | "for backend in [gr, unicodeplots, pyplot]\n", 152 | " backend()\n", 153 | " f = plot(x, y)\n", 154 | " xlabel!(\"x\")\n", 155 | " ylabel!(\"x^2 / 2\")\n", 156 | " title!(\"x^2 / 2 vs. x\")\n", 157 | " display(f)\n", 158 | "end" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "And notice how this second plot differs from the first! Using text like this is a little silly in a Jupyter notebook where we have fancy drawing capabilities, but it can be very useful for quick and dirty visualization in a terminal." 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "### LaTeXStrings & annotations\n", 173 | "\n", 174 | "Add pretty math equations and annotations to plots!" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "# Pkg.add(LaTeXStrings)\n", 184 | "using LaTeXStrings" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "f = plot(x, y)\n", 194 | "xlabel!(L\"x\")\n", 195 | "ylabel!(L\"\\frac{x^2}{2}\")\n", 196 | "title!(L\"\\frac{x^2}{2} \\ vs.\\ x\")" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "annotate!(f, [(10, 50,text(L\"So\\ exponential!\",16,:center))])" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "### Layouts\n", 213 | "\n", 214 | "Arrange subplots within a larger plot using either **grid** or **custom** layouts." 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": null, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [ 223 | "x = -10:10" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "metadata": {}, 230 | "outputs": [], 231 | "source": [ 232 | "myplots = [plot(x, x.^i) for i in 1:4]\n", 233 | "plot(myplots..., layout = (2, 2), legend = false)\n", 234 | "# Same as:\n", 235 | "# plot(myplots[1], myplots[2], myplots[3], myplots[4], layout = (2, 2), legend = false)" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "# mylayout = @layout([a{0.5h};[b{0.7w} c]; d])\n", 245 | "mylayout = @layout([a;[b{0.5w} c{0.5w}]; d])\n", 246 | "plot(myplots..., layout = mylayout, legend = false)" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "### Going beyond line and scatter plots" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "n = 10000\n", 263 | "x = randn(n)\n", 264 | "y = randn(n)\n", 265 | "histogram2d(x, y,nbins=100,colorbar=true)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "n = 1000\n", 275 | "y = hcat(rand(n), randn(n)) # generate 2 random samples of size 1000 each\n", 276 | "boxplot([\"Uniform\" \"Normal\"], y, leg=false, color=:red)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": { 282 | "collapsed": true 283 | }, 284 | "source": [ 285 | "### Exercises\n", 286 | "\n", 287 | "#### 8.1 \n", 288 | "Given\n", 289 | "```julia\n", 290 | "x = -10:10\n", 291 | "```\n", 292 | "plot y vs. x for $y = x^2$. You may want to change backends back again." 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": null, 298 | "metadata": {}, 299 | "outputs": [], 300 | "source": [ 301 | "x = -10:10" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": null, 307 | "metadata": {}, 308 | "outputs": [], 309 | "source": [] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": {}, 314 | "source": [ 315 | "#### 8.2 \n", 316 | "Execute the following code" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": {}, 323 | "outputs": [], 324 | "source": [ 325 | "x = -10:10\n", 326 | "p1 = plot(x, x)\n", 327 | "p2 = plot(x, x.^2)\n", 328 | "p3 = plot(x, x.^3)\n", 329 | "p4 = plot(x, x.^4)" 330 | ] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": {}, 335 | "source": [ 336 | "and then create a $4x1$ plot that uses `p1`, `p2`, `p3`, and `p4` as subplots." 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": null, 342 | "metadata": {}, 343 | "outputs": [], 344 | "source": [] 345 | } 346 | ], 347 | "metadata": { 348 | "@webio": { 349 | "lastCommId": null, 350 | "lastKernelId": null 351 | }, 352 | "anaconda-cloud": {}, 353 | "kernelspec": { 354 | "display_name": "Julia 1.0.1", 355 | "language": "julia", 356 | "name": "julia-1.0" 357 | }, 358 | "language_info": { 359 | "file_extension": ".jl", 360 | "mimetype": "application/julia", 361 | "name": "julia", 362 | "version": "1.0.1" 363 | }, 364 | "toc": { 365 | "nav_menu": { 366 | "height": "66px", 367 | "width": "252px" 368 | }, 369 | "navigate_menu": true, 370 | "number_sections": true, 371 | "sideBar": true, 372 | "threshold": "2", 373 | "toc_cell": false, 374 | "toc_section_display": "block", 375 | "toc_window_display": false 376 | } 377 | }, 378 | "nbformat": 4, 379 | "nbformat_minor": 2 380 | } 381 | -------------------------------------------------------------------------------- /JuliaCon2019_Huda/Julia Wrappers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## We need the package `PyCall` for importing Python packages and code" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "# wrapping functions:\n", 17 | "using PyCall #if calling this for the first time, add the package first by typing Pkg.add(\"PyCall\")" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "pushfirst!(PyVector(pyimport(\"sys\").\"path\"), \"\") #to tell pyimport search in the local directory" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "### 1. take your existing python function and wrap it into a julia function\n", 34 | "_filename: python_sum.py_\n", 35 | "\n", 36 | "```\n", 37 | "def py_sum(A):\n", 38 | " s = 0.0\n", 39 | " for a in A:\n", 40 | " s += a\n", 41 | " return s\n", 42 | "```" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "python_sum = pyimport(\"python_sum\") # wrote a function out side julia" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "m = [1,2,3]\n", 61 | "python_sum.py_sum(m)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "### 2. You can also write quick and easy python code from within julia" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "py\"\"\"\n", 78 | "def py_sum2(A):\n", 79 | " s = 0.0\n", 80 | " for a in A:\n", 81 | " s += a\n", 82 | " return s\n", 83 | "\"\"\"\n", 84 | "sum_py = py\"py_sum2\"" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "sum_py([1,2,3])" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## 3. You can also import your favorite python package" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "pyimport(\"cvxpy\")" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "```\n", 117 | "# if the above doesn't work, and you get something like what I get when I add networkx, try:\n", 118 | "using Conda\n", 119 | "Conda.add(\"cvxpy\")\n", 120 | "```" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "pyimport(\"networkx\")" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "my_cvxpy = pyimport(\"cvxpy\")" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": null, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "x1 = my_cvxpy.Variable(1, name=\"x1\")" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "obj = my_cvxpy.square(x1)" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "#old syntax: @pyimport cvxpy.constraints as cvxpyconstraints\n", 166 | "x1 = my_cvxpy.Variable(1, name=\"x1\")" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [ 175 | "cvxpyconstraints = pyimport(\"cvxpy.constraints\")" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "Least squares example from the CVXPY page\n", 183 | "https://www.cvxpy.org/examples/basic/least_squares.html\n", 184 | "\n", 185 | "```\n", 186 | "# Import packages.\n", 187 | "import cvxpy as cp\n", 188 | "import numpy as np\n", 189 | "\n", 190 | "# Generate data.\n", 191 | "m = 20\n", 192 | "n = 15\n", 193 | "np.random.seed(1)\n", 194 | "A = np.random.randn(m, n)\n", 195 | "b = np.random.randn(m)\n", 196 | "\n", 197 | "# Define and solve the CVXPY problem.\n", 198 | "x = cp.Variable(n)\n", 199 | "cost = cp.sum_squares(A*x - b)\n", 200 | "prob = cp.Problem(cp.Minimize(cost))\n", 201 | "prob.solve()\n", 202 | "\n", 203 | "# Print result.\n", 204 | "print(\"\\nThe optimal value is\", prob.value)\n", 205 | "print(\"The optimal x is\")\n", 206 | "print(x.value)\n", 207 | "print(\"The norm of the residual is \", cp.norm(A*x - b, p=2).value)\n", 208 | "```" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": {}, 215 | "outputs": [], 216 | "source": [ 217 | "m = 20\n", 218 | "n = 15\n", 219 | "A = randn(m,n)\n", 220 | "b = randn(m)\n", 221 | ";" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "x = my_cvxpy.Variable(n)\n", 231 | "cost = my_cvxpy.sum_squares(A*x - b)\n", 232 | "prob = my_cvxpy.Problem(my_cvxpy.Minimize(cost))\n", 233 | "prob.solve()" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "println(\"\\nThe optimal value is\", prob.value)\n", 243 | "println(\"The optimal x is\")\n", 244 | "println(x.value)\n", 245 | "println(\"The norm of the residual is \", my_cvxpy.norm(A*x - b, p=2).value)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "# Wrapping C code with `ccall`" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "metadata": {}, 259 | "outputs": [], 260 | "source": [ 261 | "?ccall" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "More references in this link:\n", 269 | "https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/index.html" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "t = ccall((:clock, \"libc\"), Int32, ())" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "ccall((:floor,\"math\"),Float64,(Float64,),10.1)" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": null, 293 | "metadata": {}, 294 | "outputs": [], 295 | "source": [ 296 | "ccall((:floor,\"libm\"),Float64,(Float64,),10.1)" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "## Now let's wrap our own `C` function\n", 304 | "\n", 305 | "* Switch to editor `hello_world.c`\n", 306 | "\n", 307 | "```\n", 308 | "#include \n", 309 | "int hello_world()\n", 310 | "{\n", 311 | " printf(\"Hello, World!\\n\");\n", 312 | " return 0;\n", 313 | "}\n", 314 | "\n", 315 | "int hello_world_repeated(int n)\n", 316 | "{\n", 317 | " for (int i = 0; i\n", 363 | "\n", 364 | "extern \"C\"\n", 365 | "{\n", 366 | "int64_t Fibonacci_I(int64_t n)\n", 367 | "{\n", 368 | "\tint x = 0;\n", 369 | "\tint y = 1;\n", 370 | "\tint t;\n", 371 | "\tfor(int i=1; i println(\"Hi $name, it's great to see you!\")" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "f3 = x -> x^2" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "sayhi3(\"Chewbacca\")" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "f3(42)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "## Duck-typing in Julia\n", 162 | "*\"If it quacks like a duck, it's a duck.\"*

\n", 163 | "Julia functions will just work on whatever inputs make sense.

\n", 164 | "For example, `sayhi` works on the name of this minor tv character, written as an integer..." 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "sayhi(55595472)" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "And `f` will work on a matrix. " 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": {}, 187 | "outputs": [], 188 | "source": [ 189 | "A = rand(3, 3)\n", 190 | "A" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": {}, 197 | "outputs": [], 198 | "source": [ 199 | "f(A)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "`f` will also work on a string like \"hi\" because `*` is defined for string inputs as string concatenation." 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "f(\"hi\")" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "On the other hand, `f` will not work on a vector. Unlike `A^2`, which is well-defined, the meaning of `v^2` for a vector, `v`, is not a well-defined algebraic operation. " 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "v = rand(3)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "f(v)" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": { 246 | "collapsed": true 247 | }, 248 | "source": [ 249 | "## Mutating vs. non-mutating functions\n", 250 | "\n", 251 | "By convention, functions followed by `!` alter their contents and functions lacking `!` do not.\n", 252 | "\n", 253 | "For example, let's look at the difference between `sort` and `sort!`.\n" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "v = [3, 5, 2]" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": null, 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [ 271 | "sort(v)" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": {}, 278 | "outputs": [], 279 | "source": [ 280 | "v" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "`sort(v)` returns a sorted array that contains the same elements as `v`, but `v` is left unchanged.

\n", 288 | "\n", 289 | "On the other hand, when we run `sort!(v)`, the contents of v are sorted within the array `v`." 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "sort!(v)" 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": null, 304 | "metadata": {}, 305 | "outputs": [], 306 | "source": [ 307 | "v" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "## Some higher order functions\n", 315 | "\n", 316 | "### map\n", 317 | "\n", 318 | "`map` is a \"higher-order\" function in Julia that *takes a function* as one of its input arguments. \n", 319 | "`map` then applies that function to every element of the data structure you pass it. For example, executing\n", 320 | "\n", 321 | "```julia\n", 322 | "map(f, [1, 2, 3])\n", 323 | "```\n", 324 | "will give you an output array where the function `f` has been applied to all elements of `[1, 2, 3]`\n", 325 | "```julia\n", 326 | "[f(1), f(2), f(3)]\n", 327 | "```" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "metadata": {}, 334 | "outputs": [], 335 | "source": [ 336 | "map(f, [1, 2, 3])" 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "Here we've squared all the elements of the vector `[1, 2, 3]`, rather than squaring the vector `[1, 2, 3]`.\n", 344 | "\n", 345 | "To do this, we could have passed to `map` an anonymous function rather than a named function, such as" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": null, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "x -> x^3" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "via" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": null, 367 | "metadata": {}, 368 | "outputs": [], 369 | "source": [ 370 | "map(x -> x^3, [1, 2, 3])" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "and now we've cubed all the elements of `[1, 2, 3]`!" 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "### broadcast\n", 385 | "\n", 386 | "`broadcast` is another higher-order function like `map`. `broadcast` is a generalization of `map`, so it can do every thing `map` can do and more. The syntax for calling `broadcast` is the same as for calling `map`" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": {}, 393 | "outputs": [], 394 | "source": [ 395 | "broadcast(f, [1, 2, 3])" 396 | ] 397 | }, 398 | { 399 | "cell_type": "markdown", 400 | "metadata": {}, 401 | "source": [ 402 | "and again, we've applied `f` (squared) to all the elements of `[1, 2, 3]` - this time by \"broadcasting\" `f`!\n", 403 | "\n", 404 | "Some syntactic sugar for calling `broadcast` is to place a `.` between the name of the function you want to `broadcast` and its input arguments. For example,\n", 405 | "\n", 406 | "```julia\n", 407 | "broadcast(f, [1, 2, 3])\n", 408 | "```\n", 409 | "is the same as\n", 410 | "```julia\n", 411 | "f.([1, 2, 3])\n", 412 | "```" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": null, 418 | "metadata": {}, 419 | "outputs": [], 420 | "source": [ 421 | "f.([1, 2, 3])" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": {}, 427 | "source": [ 428 | "Notice again how different this is from calling \n", 429 | "```julia\n", 430 | "f([1, 2, 3])\n", 431 | "```\n", 432 | "We can square every element of a vector, but we can't square a vector!" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "To drive home the point, let's look at the difference between\n", 440 | "\n", 441 | "```julia\n", 442 | "f(A)\n", 443 | "```\n", 444 | "and\n", 445 | "```julia\n", 446 | "f.(A)\n", 447 | "```\n", 448 | "for a matrix `A`:" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": null, 454 | "metadata": {}, 455 | "outputs": [], 456 | "source": [ 457 | "A = [i + 3*j for j in 0:2, i in 1:3]" 458 | ] 459 | }, 460 | { 461 | "cell_type": "code", 462 | "execution_count": null, 463 | "metadata": {}, 464 | "outputs": [], 465 | "source": [ 466 | "f(A)" 467 | ] 468 | }, 469 | { 470 | "cell_type": "markdown", 471 | "metadata": {}, 472 | "source": [ 473 | "As before we see that for a matrix, `A`,\n", 474 | "```\n", 475 | "f(A) = A^2 = A * A\n", 476 | "``` \n", 477 | "\n", 478 | "On the other hand," 479 | ] 480 | }, 481 | { 482 | "cell_type": "code", 483 | "execution_count": null, 484 | "metadata": {}, 485 | "outputs": [], 486 | "source": [ 487 | "B = f.(A)" 488 | ] 489 | }, 490 | { 491 | "cell_type": "markdown", 492 | "metadata": { 493 | "collapsed": true 494 | }, 495 | "source": [ 496 | "contains the squares of all the entries of `A`.\n", 497 | "\n", 498 | "This dot syntax for broadcasting allows us to write relatively complex compound elementwise expressions in a way that looks natural/closer to mathematical notation. For example, we can write" 499 | ] 500 | }, 501 | { 502 | "cell_type": "code", 503 | "execution_count": null, 504 | "metadata": {}, 505 | "outputs": [], 506 | "source": [ 507 | "A .+ 2 .* f.(A) ./ A" 508 | ] 509 | }, 510 | { 511 | "cell_type": "markdown", 512 | "metadata": {}, 513 | "source": [ 514 | "instead of" 515 | ] 516 | }, 517 | { 518 | "cell_type": "code", 519 | "execution_count": null, 520 | "metadata": {}, 521 | "outputs": [], 522 | "source": [ 523 | "broadcast(x -> x + 2 * f(x) / x, A)" 524 | ] 525 | }, 526 | { 527 | "cell_type": "markdown", 528 | "metadata": {}, 529 | "source": [ 530 | "and the two will perform exactly the same." 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": { 536 | "collapsed": true 537 | }, 538 | "source": [ 539 | "### Exercises\n", 540 | "\n", 541 | "#### 4.1 \n", 542 | "Write a function that adds 1 to its input." 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": null, 548 | "metadata": {}, 549 | "outputs": [], 550 | "source": [] 551 | }, 552 | { 553 | "cell_type": "markdown", 554 | "metadata": {}, 555 | "source": [ 556 | "#### 4.2 \n", 557 | "Use `map` or `broadcast` to increment every element of matrix `A` by `1`." 558 | ] 559 | }, 560 | { 561 | "cell_type": "code", 562 | "execution_count": null, 563 | "metadata": {}, 564 | "outputs": [], 565 | "source": [] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": { 570 | "collapsed": true 571 | }, 572 | "source": [ 573 | "#### 4.3 \n", 574 | "Use the broadcast dot syntax to increment every element of matrix `A` by `1`." 575 | ] 576 | }, 577 | { 578 | "cell_type": "code", 579 | "execution_count": null, 580 | "metadata": {}, 581 | "outputs": [], 582 | "source": [] 583 | }, 584 | { 585 | "cell_type": "markdown", 586 | "metadata": {}, 587 | "source": [ 588 | "#### Bonus\n", 589 | "\n", 590 | "**4.4**\n", 591 | "\n", 592 | "Given variables `x` and `y` defining a point $(x, y)$, write a function `dist(x, y)` that returns the distance of $(x, y)$ from $(0, 0)$." 593 | ] 594 | }, 595 | { 596 | "cell_type": "code", 597 | "execution_count": null, 598 | "metadata": {}, 599 | "outputs": [], 600 | "source": [] 601 | }, 602 | { 603 | "cell_type": "markdown", 604 | "metadata": {}, 605 | "source": [ 606 | "**4.5**\n", 607 | "\n", 608 | "Write a function `myrand` that returns `(x, y)`, where `x` and `y` are pseudo-random numbers uniformly distributed between -1 and +1.\n", 609 | "\n", 610 | "*Hint:* The `rand()` function returns a random number between 0 and 1. Passing a collection as the first argument of `rand` will cause `rand` to return a random value from amongst the elements of the collection.\n", 611 | "\n", 612 | "Ex. rand(animals) will return one of the strings contained in `animals`:" 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": null, 618 | "metadata": {}, 619 | "outputs": [], 620 | "source": [ 621 | "animals = [\"cat\", \"dog\", \"bird\"]\n", 622 | "rand(animals)" 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": null, 628 | "metadata": {}, 629 | "outputs": [], 630 | "source": [] 631 | } 632 | ], 633 | "metadata": { 634 | "kernelspec": { 635 | "display_name": "Julia 1.0.1", 636 | "language": "julia", 637 | "name": "julia-1.0" 638 | }, 639 | "language_info": { 640 | "file_extension": ".jl", 641 | "mimetype": "application/julia", 642 | "name": "julia", 643 | "version": "1.0.1" 644 | } 645 | }, 646 | "nbformat": 4, 647 | "nbformat_minor": 2 648 | } 649 | -------------------------------------------------------------------------------- /03.Data_structures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Data structures\n", 8 | "\n", 9 | "Once we start working with many pieces of data at once, it will be convenient for us to store data in structures like arrays or dictionaries (rather than just relying on variables).
\n", 10 | "\n", 11 | "Types of data structures covered:\n", 12 | "1. Arrays\n", 13 | "2. Tuples\n", 14 | "3. Dictionaries\n", 15 | "\n", 16 | "\n", 17 | "
\n", 18 | "As an overview, tuples and arrays are both ordered sequences of elements (so we can index into them). Dictionaries and arrays are both mutable.\n", 19 | "We'll explain this more below!" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "## Arrays\n", 27 | "\n", 28 | "Arrays contain ordered collections that can be updated.
\n", 29 | "\n", 30 | "#### Defining Arrays \n", 31 | "\n", 32 | "We can create an array by enclosing a collection in `[ ]`.\n", 33 | "\n", 34 | "Syntax:
\n", 35 | "```julia\n", 36 | "[item1, item2, ...]```\n", 37 | "\n", 38 | "\n", 39 | "For example, we might create an array to keep track of my friends" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 3, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "data": { 49 | "text/plain": [ 50 | "5-element Array{String,1}:\n", 51 | " \"Ted\" \n", 52 | " \"Robyn\" \n", 53 | " \"Barney\" \n", 54 | " \"Lily\" \n", 55 | " \"Marshall\"" 56 | ] 57 | }, 58 | "execution_count": 3, 59 | "metadata": {}, 60 | "output_type": "execute_result" 61 | } 62 | ], 63 | "source": [ 64 | "myfriends = [\"Ted\", \"Robyn\", \"Barney\", \"Lily\", \"Marshall\"]" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "or to store a sequence of numbers" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 1, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "data": { 81 | "text/plain": [ 82 | "7-element Array{Int64,1}:\n", 83 | " 1\n", 84 | " 1\n", 85 | " 2\n", 86 | " 3\n", 87 | " 5\n", 88 | " 8\n", 89 | " 13" 90 | ] 91 | }, 92 | "execution_count": 1, 93 | "metadata": {}, 94 | "output_type": "execute_result" 95 | } 96 | ], 97 | "source": [ 98 | "fibonacci = [1, 1, 2, 3, 5, 8, 13]" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "For the `Array` `friends`, the `1` in `Array{String,1}` means this is a one dimensional array. The `String` tells us the type of each element.\n", 106 | "\n", 107 | "Similarly, `Array{Int64,1}` for `fibonacci` tells us `fibonacci` is a 1D array (also known in Julia as a \"vector\") containing integers. On the other hand, `Array{String,2}` would be a 2D matrix of `String`s.\n", 108 | "\n", 109 | "But we're not limited to creating arrays that only hold one datatype!" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "mixture = [1, 1, 2, 3, \"Ted\", \"Robyn\"]" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "#### Accessing array elements" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "Once we have an array, we can grab individual pieces of data from inside that array by indexing into the array. For example, if we want the third friend listed in `myfriends`, we write" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "myfriends[3]" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "We can grab multiple elements by specifying ranges inside `[]` rather than Integers:" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 4, 154 | "metadata": {}, 155 | "outputs": [ 156 | { 157 | "data": { 158 | "text/plain": [ 159 | "2-element Array{String,1}:\n", 160 | " \"Barney\"\n", 161 | " \"Lily\" " 162 | ] 163 | }, 164 | "execution_count": 4, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "myfriends[3:4]" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "#### Updating arrays" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "We can use indexing to edit an existing element of an array" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "myfriends[3] = \"Baby Bop\"" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "This last example shows us that Julia has 1-based indexing, not 0-based like Python. This means that in Julia, we start counting from `1` rather than from `0`.\n", 201 | "\n", 202 | "Wars are fought over lesser issues. I have a friend with the wisdom of Solomon who proposes settling this once and for all with ½ 😃" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "We can also edit the array by using the `push!` and `pop!` functions. `push!` adds an element to the end of an array and `pop!` removes the **last** element of an array.\n", 210 | "\n", 211 | "We can add another number to our fibonnaci sequence" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "push!(fibonacci, 21)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "and then remove it" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": null, 233 | "metadata": {}, 234 | "outputs": [], 235 | "source": [ 236 | "pop!(fibonacci)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "fibonacci" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "#### Moving past 1D arrays of scalars" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "So far I've given examples of only 1D arrays of scalars, but arrays can have an arbitrary number of dimensions.\n", 260 | "\n", 261 | "We can easily type out small 2D arrays" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": null, 267 | "metadata": {}, 268 | "outputs": [], 269 | "source": [ 270 | "my2D = [\n", 271 | " 1 2 3\n", 272 | " 4 5 6 ]" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "And we can use `rand` to create, for example, 2D and 3D arrays populated with random values." 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": null, 285 | "metadata": {}, 286 | "outputs": [], 287 | "source": [ 288 | "rand(4, 3)" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": null, 294 | "metadata": {}, 295 | "outputs": [], 296 | "source": [ 297 | "rand(4, 3, 2)" 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "We can also create arrays that store other arrays. \n", 305 | "

\n", 306 | "For example, the following are arrays of arrays:" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": null, 312 | "metadata": {}, 313 | "outputs": [], 314 | "source": [ 315 | "favorites = [[\"koobideh\", \"chocolate\", \"eggs\"],[\"penguins\", \"cats\", \"sugargliders\"]]" 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": null, 321 | "metadata": {}, 322 | "outputs": [], 323 | "source": [ 324 | "numbers = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]" 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": {}, 330 | "source": [ 331 | "We can also call these \"vectors of vectors\"!" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "metadata": {}, 337 | "source": [ 338 | "#### Copying arrays\n", 339 | "\n", 340 | "Be careful when you want to copy arrays!" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": null, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "fibonacci" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": null, 355 | "metadata": {}, 356 | "outputs": [], 357 | "source": [ 358 | "somenumbers = fibonacci" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": null, 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [ 367 | "somenumbers[1] = 404" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": null, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "fibonacci" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "Editing `somenumbers` caused `fibonacci` to get updated as well!\n", 384 | "\n", 385 | "In the above example, we didn't actually make a copy of `fibonacci`. We just created a new way to access the entries in the array bound to `fibonacci`.\n", 386 | "\n", 387 | "If we'd like to make a copy of the array bound to `fibonacci`, we can use the `copy` function." 388 | ] 389 | }, 390 | { 391 | "cell_type": "code", 392 | "execution_count": null, 393 | "metadata": {}, 394 | "outputs": [], 395 | "source": [ 396 | "# First, restore fibonacci\n", 397 | "fibonacci[1] = 1\n", 398 | "fibonacci" 399 | ] 400 | }, 401 | { 402 | "cell_type": "code", 403 | "execution_count": null, 404 | "metadata": {}, 405 | "outputs": [], 406 | "source": [ 407 | "somemorenumbers = copy(fibonacci)" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": null, 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [ 416 | "somemorenumbers[1] = 404" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": null, 422 | "metadata": {}, 423 | "outputs": [], 424 | "source": [ 425 | "fibonacci" 426 | ] 427 | }, 428 | { 429 | "cell_type": "markdown", 430 | "metadata": {}, 431 | "source": [ 432 | "In this last example, fibonacci was not updated. Therefore we see that the arrays bound to `somemorenumbers` and `fibonacci` are distinct." 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "## Tuples\n", 440 | "\n", 441 | "We can create a tuple by enclosing an ordered collection of elements in `( )`.\n", 442 | "\n", 443 | "Syntax:
\n", 444 | "```julia\n", 445 | "(item1, item2, ...)```" 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": null, 451 | "metadata": {}, 452 | "outputs": [], 453 | "source": [ 454 | "myfavoriteanimals = (\"penguins\", \"cats\", \"sugargliders\")" 455 | ] 456 | }, 457 | { 458 | "cell_type": "markdown", 459 | "metadata": {}, 460 | "source": [ 461 | "We can index into this tuple," 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "execution_count": null, 467 | "metadata": {}, 468 | "outputs": [], 469 | "source": [ 470 | "myfavoriteanimals[1]" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "but since tuples are immutable, we can't update it" 478 | ] 479 | }, 480 | { 481 | "cell_type": "code", 482 | "execution_count": null, 483 | "metadata": {}, 484 | "outputs": [], 485 | "source": [ 486 | "myfavoriteanimals[1] = \"otters\"" 487 | ] 488 | }, 489 | { 490 | "cell_type": "markdown", 491 | "metadata": {}, 492 | "source": [ 493 | "## Now in 1.0: NamedTuples\n", 494 | "\n", 495 | "As you might guess, `NamedTuple`s are just like `Tuple`s except that each element additionally has a name! They have a special syntax using `=` inside a tuple:\n", 496 | "\n", 497 | "```julia\n", 498 | "(name1 = item1, name2 = item2, ...)\n", 499 | "```" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": null, 505 | "metadata": {}, 506 | "outputs": [], 507 | "source": [ 508 | "myfavoriteanimals = (bird = \"penguins\", mammal = \"cats\", marsupial = \"sugargliders\")" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "Like regular `Tuples`, `NamedTuples` are ordered, so we can retrieve their elements via indexing:" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": null, 521 | "metadata": {}, 522 | "outputs": [], 523 | "source": [ 524 | "myfavoriteanimals[1]" 525 | ] 526 | }, 527 | { 528 | "cell_type": "markdown", 529 | "metadata": {}, 530 | "source": [ 531 | "They also add the special ability to access values by their name:" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": null, 537 | "metadata": {}, 538 | "outputs": [], 539 | "source": [ 540 | "myfavoriteanimals.bird" 541 | ] 542 | }, 543 | { 544 | "cell_type": "markdown", 545 | "metadata": {}, 546 | "source": [ 547 | "## Dictionaries\n", 548 | "\n", 549 | "If we have sets of data related to one another, we may choose to store that data in a dictionary. We can create a dictionary using the `Dict()` function, which we can initialize as an empty dictionary or one storing key, value pairs.\n", 550 | "\n", 551 | "Syntax:\n", 552 | "```julia\n", 553 | "Dict(key1 => value1, key2 => value2, ...)```\n", 554 | "\n", 555 | "A good example is a contacts list, where we associate names with phone numbers." 556 | ] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "execution_count": null, 561 | "metadata": {}, 562 | "outputs": [], 563 | "source": [ 564 | "myphonebook = Dict(\"Jenny\" => \"867-5309\", \"Ghostbusters\" => \"555-2368\")" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": { 570 | "collapsed": true 571 | }, 572 | "source": [ 573 | "In this example, each name and number is a \"key\" and \"value\" pair. We can grab Jenny's number (a value) using the associated key" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": null, 579 | "metadata": {}, 580 | "outputs": [], 581 | "source": [ 582 | "myphonebook[\"Jenny\"]" 583 | ] 584 | }, 585 | { 586 | "cell_type": "markdown", 587 | "metadata": {}, 588 | "source": [ 589 | "We can add another entry to this dictionary as follows" 590 | ] 591 | }, 592 | { 593 | "cell_type": "code", 594 | "execution_count": null, 595 | "metadata": {}, 596 | "outputs": [], 597 | "source": [ 598 | "myphonebook[\"Kramer\"] = \"555-FILK\"" 599 | ] 600 | }, 601 | { 602 | "cell_type": "markdown", 603 | "metadata": {}, 604 | "source": [ 605 | "Let's check what our phonebook looks like now..." 606 | ] 607 | }, 608 | { 609 | "cell_type": "code", 610 | "execution_count": null, 611 | "metadata": {}, 612 | "outputs": [], 613 | "source": [ 614 | "myphonebook" 615 | ] 616 | }, 617 | { 618 | "cell_type": "markdown", 619 | "metadata": {}, 620 | "source": [ 621 | "We can delete Kramer from our contact list - and simultaneously grab his number - by using `pop!`" 622 | ] 623 | }, 624 | { 625 | "cell_type": "code", 626 | "execution_count": null, 627 | "metadata": {}, 628 | "outputs": [], 629 | "source": [ 630 | "pop!(myphonebook, \"Kramer\")" 631 | ] 632 | }, 633 | { 634 | "cell_type": "code", 635 | "execution_count": null, 636 | "metadata": {}, 637 | "outputs": [], 638 | "source": [ 639 | "myphonebook" 640 | ] 641 | }, 642 | { 643 | "cell_type": "markdown", 644 | "metadata": {}, 645 | "source": [ 646 | "Unlike tuples and arrays, dictionaries are not ordered. So, we can't index into them." 647 | ] 648 | }, 649 | { 650 | "cell_type": "code", 651 | "execution_count": null, 652 | "metadata": {}, 653 | "outputs": [], 654 | "source": [ 655 | "myphonebook[1]" 656 | ] 657 | }, 658 | { 659 | "cell_type": "markdown", 660 | "metadata": {}, 661 | "source": [ 662 | "In the example above, `julia` thinks you're trying to access a value associated with the key `1`." 663 | ] 664 | }, 665 | { 666 | "cell_type": "markdown", 667 | "metadata": { 668 | "collapsed": true 669 | }, 670 | "source": [ 671 | "### Exercises\n", 672 | "\n", 673 | "#### 3.1 \n", 674 | "Create an array, `a_ray`, with the following code:\n", 675 | "\n", 676 | "```julia\n", 677 | "a_ray = [1, 2, 3]\n", 678 | "```\n", 679 | "\n", 680 | "Add the number `4` to the end of this array and then remove it." 681 | ] 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": null, 686 | "metadata": {}, 687 | "outputs": [], 688 | "source": [] 689 | }, 690 | { 691 | "cell_type": "markdown", 692 | "metadata": {}, 693 | "source": [ 694 | "#### 3.2 \n", 695 | "Try to add \"Emergency\" as key to `myphonebook` with the value `string(911)` with the following code\n", 696 | "```julia\n", 697 | "myphonebook[\"Emergency\"] = 911\n", 698 | "```\n", 699 | "\n", 700 | "Why doesn't this work?" 701 | ] 702 | }, 703 | { 704 | "cell_type": "code", 705 | "execution_count": null, 706 | "metadata": {}, 707 | "outputs": [], 708 | "source": [] 709 | }, 710 | { 711 | "cell_type": "markdown", 712 | "metadata": {}, 713 | "source": [ 714 | "#### 3.3 \n", 715 | "Create a new dictionary called `flexible_phonebook` that has Jenny's number stored as an integer and Ghostbusters' number stored as a string with the following code\n", 716 | "\n", 717 | "```julia\n", 718 | "flexible_phonebook = Dict(\"Jenny\" => 8675309, \"Ghostbusters\" => \"555-2368\")\n", 719 | "```" 720 | ] 721 | }, 722 | { 723 | "cell_type": "code", 724 | "execution_count": null, 725 | "metadata": {}, 726 | "outputs": [], 727 | "source": [] 728 | }, 729 | { 730 | "cell_type": "markdown", 731 | "metadata": {}, 732 | "source": [ 733 | "#### 3.4 \n", 734 | "Add the key \"Emergency\" with the value `911` (an integer) to `flexible_phonebook`." 735 | ] 736 | }, 737 | { 738 | "cell_type": "code", 739 | "execution_count": null, 740 | "metadata": {}, 741 | "outputs": [], 742 | "source": [] 743 | }, 744 | { 745 | "cell_type": "markdown", 746 | "metadata": {}, 747 | "source": [ 748 | "#### 3.5 \n", 749 | "Why can we add an integer as a value to `flexible_phonebook` but not `myphonebook`? How could we have initialized `myphonebook` so that it would accept integers as values?" 750 | ] 751 | }, 752 | { 753 | "cell_type": "code", 754 | "execution_count": null, 755 | "metadata": {}, 756 | "outputs": [], 757 | "source": [] 758 | } 759 | ], 760 | "metadata": { 761 | "kernelspec": { 762 | "display_name": "Julia 1.0.1", 763 | "language": "julia", 764 | "name": "julia-1.0" 765 | }, 766 | "language_info": { 767 | "file_extension": ".jl", 768 | "mimetype": "application/julia", 769 | "name": "julia", 770 | "version": "1.0.1" 771 | } 772 | }, 773 | "nbformat": 4, 774 | "nbformat_minor": 2 775 | } 776 | -------------------------------------------------------------------------------- /SOLUTIONS_Monte_Carlo_calculation_of_pi.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Monte Carlo determination of $\\pi$\n", 8 | "\n", 9 | "Imagine that we have a circle of radius 1 ($r = 1$), centered at the point $(0, 0)$ in Cartesian coordinates.\n", 10 | "\n", 11 | "We can further imagine that circle being enclosed by a square with the same center and with sides of length $2r$, in this case 2.\n", 12 | "\n", 13 | "\"Drawing\"\n", 14 | "\n", 15 | "\n", 16 | "Given a square with sides of length $2r$, the square's area is\n", 17 | "\n", 18 | "$$A_{square} = (2r)^2 = 4r^2$$\n", 19 | "\n", 20 | "whereas the area of a circle with radius $r$ is\n", 21 | "$$A_{circle} = \\pi r^2$$\n", 22 | "\n", 23 | "Therefore the ratio of the area of the circle to that of the enclosing square is\n", 24 | "\n", 25 | "$$\\frac{A_{circle}}{A_{square}} = \\frac{\\pi r^2}{4r^2} = \\frac{\\pi}{4}$$.\n", 26 | "\n", 27 | "By rearranging this expression, we see we can define $\\pi$ as\n", 28 | "\n", 29 | "$$\\pi = 4\\frac{A_{circle}}{A_{square}}$$\n", 30 | "\n", 31 | "**And *this* suggests a way to calculate $\\pi$!**\n", 32 | "\n", 33 | "If we're able to figure out the ratio of the areas of a circle and the smallest square that can hold that circle, we can figure out $\\pi$. And fortunately, this ratio is equal to the probability that a randomly chosen point inside the square also falls inside the circle. \n", 34 | "\n", 35 | "This means that we can calculate this ratio (and therefore $\\pi$) using a Monte Carlo simulation by choosing a large number of random points inside a square and tracking how many fall inside the circle.\n", 36 | "\n", 37 | "#### Pseudo-code\n", 38 | "\n", 39 | "Given the above, our algorithm for determining $\\pi$ looks like this:\n", 40 | "\n", 41 | "1. For each of $N$ iterations,\n", 42 | " 1. Select a random point inside the square depicted above.\n", 43 | " 1. Determine if the point also falls inside the largest circle that can be enclosed within this square.\n", 44 | " 1. Keep track of whether or not this point fell inside the circle. At the end of $N$ iterations, you want to know $M$ -- the number of the $N$ random points that fell inside the circle!\n", 45 | "1. Calculate $\\pi$ as $4\\frac{M}{N}$\n", 46 | "\n", 47 | "Note: As you increase the value of $N$, you'll be able to estimate pi with greater accuracy!\n", 48 | "\n", 49 | "### Exercise\n", 50 | "\n", 51 | "Write a function that calculates $\\pi$ using Julia.\n", 52 | "\n", 53 | "Feel free to get started immediately, or to make use of the practice exercises below which have you solve pieces of the problem one at a time." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 35, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "data": { 63 | "text/plain": [ 64 | "dist (generic function with 1 method)" 65 | ] 66 | }, 67 | "execution_count": 35, 68 | "metadata": {}, 69 | "output_type": "execute_result" 70 | } 71 | ], 72 | "source": [ 73 | "function dist(x, y)\n", 74 | " return sqrt(x^2 + y^2)\n", 75 | "end" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 36, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/plain": [ 86 | "myrand (generic function with 1 method)" 87 | ] 88 | }, 89 | "execution_count": 36, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "function myrand()\n", 96 | " return rand([-1, 1]) * rand(), rand([-1, 1]) * rand() \n", 97 | "end" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 37, 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "data": { 107 | "text/plain": [ 108 | "inside_circle (generic function with 1 method)" 109 | ] 110 | }, 111 | "execution_count": 37, 112 | "metadata": {}, 113 | "output_type": "execute_result" 114 | } 115 | ], 116 | "source": [ 117 | "function inside_circle(x, y)\n", 118 | " if dist(x, y) < 1.0\n", 119 | " return 1\n", 120 | " else\n", 121 | " return 0\n", 122 | " end\n", 123 | "end" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 38, 129 | "metadata": {}, 130 | "outputs": [ 131 | { 132 | "data": { 133 | "text/plain": [ 134 | "calc_pi" 135 | ] 136 | }, 137 | "execution_count": 38, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "\"\"\"\n", 144 | " calc_pi(N)\n", 145 | " \n", 146 | "Calculate pi using a Monte Carlo simulation in which `N` sampling points are chosen within a square.\n", 147 | "\"\"\"\n", 148 | "function calc_pi(N)\n", 149 | " points_inside = 0\n", 150 | " for i in 1:N\n", 151 | " x, y = myrand()\n", 152 | " points_inside += inside_circle(x, y)\n", 153 | " end\n", 154 | " return 4 * (points_inside / N)\n", 155 | "end" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "### Function practice\n", 163 | "\n", 164 | "#### Exercise\n", 165 | "\n", 166 | "Given variables `x` and `y` defining a point $(x, y)$, write a function `dist(x, y)` that returns the distance of $(x, y)$ from $(0, 0)$." 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 4, 172 | "metadata": {}, 173 | "outputs": [ 174 | { 175 | "data": { 176 | "text/plain": [ 177 | "dist (generic function with 1 method)" 178 | ] 179 | }, 180 | "execution_count": 4, 181 | "metadata": {}, 182 | "output_type": "execute_result" 183 | } 184 | ], 185 | "source": [ 186 | "function dist(x, y)\n", 187 | " return sqrt(x^2 + y^2)\n", 188 | "end" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": 6, 194 | "metadata": {}, 195 | "outputs": [ 196 | { 197 | "data": { 198 | "text/plain": [ 199 | "(0.09177130543526113, 0.880104215610646)" 200 | ] 201 | }, 202 | "execution_count": 6, 203 | "metadata": {}, 204 | "output_type": "execute_result" 205 | } 206 | ], 207 | "source": [ 208 | "x, y = rand(), rand()" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 7, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "data": { 218 | "text/plain": [ 219 | "0.8848759251086687" 220 | ] 221 | }, 222 | "execution_count": 7, 223 | "metadata": {}, 224 | "output_type": "execute_result" 225 | } 226 | ], 227 | "source": [ 228 | "dist(x, y)" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "#### Exercise\n", 236 | "\n", 237 | "Write a function `myrand` that returns `(x, y)`, where `x` and `y` are pseudo-random numbers uniformly distributed between -1 and +1.\n", 238 | "\n", 239 | "*Hint:* The `rand()` function returns a random number between 0 and 1. Passing a collection as the first argument of `rand` will cause `rand` to return a random value from amongst the elements of the collection.\n", 240 | "\n", 241 | "Ex. rand(animals) will return one of the strings contained in `animals`:" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 8, 247 | "metadata": {}, 248 | "outputs": [ 249 | { 250 | "data": { 251 | "text/plain": [ 252 | "\"cat\"" 253 | ] 254 | }, 255 | "execution_count": 8, 256 | "metadata": {}, 257 | "output_type": "execute_result" 258 | } 259 | ], 260 | "source": [ 261 | "animals = [\"cat\", \"dog\", \"bird\"]\n", 262 | "rand(animals)" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 9, 268 | "metadata": {}, 269 | "outputs": [ 270 | { 271 | "data": { 272 | "text/plain": [ 273 | "myrand (generic function with 1 method)" 274 | ] 275 | }, 276 | "execution_count": 9, 277 | "metadata": {}, 278 | "output_type": "execute_result" 279 | } 280 | ], 281 | "source": [ 282 | "function myrand()\n", 283 | " return rand([-1, 1]) * rand(), rand([-1, 1]) * rand() \n", 284 | "end" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 13, 290 | "metadata": {}, 291 | "outputs": [ 292 | { 293 | "data": { 294 | "text/plain": [ 295 | "(-0.9230968519773852, -0.38550538642272825)" 296 | ] 297 | }, 298 | "execution_count": 13, 299 | "metadata": {}, 300 | "output_type": "execute_result" 301 | } 302 | ], 303 | "source": [ 304 | "myrand()" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "### Conditional practice\n", 312 | "\n", 313 | "#### Exercise\n", 314 | "\n", 315 | "Given variables `x` and `y` defining a point $(x, y)$, write a conditional statement that prints \"Less than 1!\" if the distance of $(x, y)$ from $(0, 0)$ is less than 1." 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": 2, 321 | "metadata": {}, 322 | "outputs": [ 323 | { 324 | "data": { 325 | "text/plain": [ 326 | "2-element Array{Float64,1}:\n", 327 | " 0.2753495990422792 \n", 328 | " 0.011453969623016924" 329 | ] 330 | }, 331 | "execution_count": 2, 332 | "metadata": {}, 333 | "output_type": "execute_result" 334 | } 335 | ], 336 | "source": [ 337 | "x, y = rand(2)" 338 | ] 339 | }, 340 | { 341 | "cell_type": "code", 342 | "execution_count": 3, 343 | "metadata": {}, 344 | "outputs": [ 345 | { 346 | "name": "stdout", 347 | "output_type": "stream", 348 | "text": [ 349 | "Less than 1!\n" 350 | ] 351 | } 352 | ], 353 | "source": [ 354 | "if sqrt(x^2 + y^2) < 1.0\n", 355 | " println(\"Less than 1!\")\n", 356 | "end" 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": 5, 362 | "metadata": {}, 363 | "outputs": [ 364 | { 365 | "name": "stdout", 366 | "output_type": "stream", 367 | "text": [ 368 | "Less than 1!\n" 369 | ] 370 | } 371 | ], 372 | "source": [ 373 | "if dist(x, y) < 1.0\n", 374 | " println(\"Less than 1!\")\n", 375 | "end" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "#### Exercise\n", 383 | "\n", 384 | "Write a function `inside_circle(x, y)` that takes coordinates/variables `x` and `y` and determines whether the point $(x, y)$ falls inside a circle of radius 1 that is centered at $(0, 0)$. Return `1` if the point falls within the circle and `0` if not.\n", 385 | "\n", 386 | "*Hint:* To fall within the circle, the distance of the point to the circle's center should be less than the radius." 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 15, 392 | "metadata": {}, 393 | "outputs": [ 394 | { 395 | "data": { 396 | "text/plain": [ 397 | "inside_circle (generic function with 1 method)" 398 | ] 399 | }, 400 | "execution_count": 15, 401 | "metadata": {}, 402 | "output_type": "execute_result" 403 | } 404 | ], 405 | "source": [ 406 | "function inside_circle(x, y)\n", 407 | " if sqrt(x^2 + y^2) < 1.0\n", 408 | " return 1\n", 409 | " else\n", 410 | " return 0\n", 411 | " end\n", 412 | "end" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 14, 418 | "metadata": {}, 419 | "outputs": [ 420 | { 421 | "data": { 422 | "text/plain": [ 423 | "inside_circle (generic function with 1 method)" 424 | ] 425 | }, 426 | "execution_count": 14, 427 | "metadata": {}, 428 | "output_type": "execute_result" 429 | } 430 | ], 431 | "source": [ 432 | "inside_circle(x, y) = (sqrt(x^2 + y^2) < 1.0) ? 1 : 0" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "### Loop practice" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "#### Exercise\n", 447 | "\n", 448 | "Use a loop to generate 100 random points $(x_i, y_i)$ where $-1.0 <= x <= 1.0$ and $-1.0 <= y <= 1.0$. Print the number of times the points fell within a circle of radius 1, centered at $(0, 0)$." 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": 27, 454 | "metadata": {}, 455 | "outputs": [ 456 | { 457 | "name": "stdout", 458 | "output_type": "stream", 459 | "text": [ 460 | "83 points fell inside the circle!\n" 461 | ] 462 | } 463 | ], 464 | "source": [ 465 | "N = 0\n", 466 | "for i in 1:100\n", 467 | " x, y = myrand()\n", 468 | " N += inside_circle(x, y)\n", 469 | "end\n", 470 | "println(\"$N points fell inside the circle!\")" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "Without work that we've already done in previous exercises:" 478 | ] 479 | }, 480 | { 481 | "cell_type": "code", 482 | "execution_count": 29, 483 | "metadata": {}, 484 | "outputs": [ 485 | { 486 | "name": "stdout", 487 | "output_type": "stream", 488 | "text": [ 489 | "78 points fell inside the circle!\n" 490 | ] 491 | } 492 | ], 493 | "source": [ 494 | "N = 0\n", 495 | "for i in 1:100\n", 496 | " x = rand([-1, 1]) * rand()\n", 497 | " y = rand([-1, 1]) * rand()\n", 498 | " if sqrt(x^2 + y^2) < 1.0\n", 499 | " N += 1\n", 500 | " end\n", 501 | "end\n", 502 | "println(\"$N points fell inside the circle!\")" 503 | ] 504 | }, 505 | { 506 | "cell_type": "markdown", 507 | "metadata": {}, 508 | "source": [ 509 | "### Array practice" 510 | ] 511 | }, 512 | { 513 | "cell_type": "markdown", 514 | "metadata": {}, 515 | "source": [ 516 | "#### Exercise\n", 517 | "\n", 518 | "Use an array comprehension to create an array of 100 points in 2D Cartesian space." 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": 30, 524 | "metadata": {}, 525 | "outputs": [ 526 | { 527 | "data": { 528 | "text/plain": [ 529 | "100-element Array{Tuple{Float64,Float64},1}:\n", 530 | " (0.8235803117901142, -0.6736936601474774) \n", 531 | " (0.3558640960890065, -0.7080181200055458) \n", 532 | " (0.6161108313295864, 0.10128327704482909) \n", 533 | " (0.06767258090743411, 0.48567762731410147) \n", 534 | " (-0.01869616622547987, -0.4229478969051781)\n", 535 | " (0.8599279235169288, -0.20686834775240293) \n", 536 | " (0.25769489684403424, -0.9587876421300074) \n", 537 | " (-0.7108573976816956, -0.7344179861513818) \n", 538 | " (0.7646953306782522, 0.33019531478167496) \n", 539 | " (0.20513540415981146, -0.9106607051488109) \n", 540 | " (-0.15357265925894148, -0.4578539987702732)\n", 541 | " (0.76617200964695, -0.7296079522154135) \n", 542 | " (-0.5640083749041798, -0.8156093136312135) \n", 543 | " ⋮ \n", 544 | " (0.4825477312267852, -0.6023767911672253) \n", 545 | " (0.20483110741326693, 0.16210952105073861) \n", 546 | " (-0.3645209544985353, -0.46411948118371793)\n", 547 | " (0.1762587416098942, -0.876202029020815) \n", 548 | " (-0.4087320814383706, 0.3464881102351882) \n", 549 | " (0.803515030181229, 0.227084405652221) \n", 550 | " (-0.14559086789114306, -0.543519582178885) \n", 551 | " (0.770377554719148, -0.5780172129728407) \n", 552 | " (0.9773512106749624, 0.7160989375188618) \n", 553 | " (0.5643735149375608, -0.9564993822734364) \n", 554 | " (0.31253625667570106, 0.9430302711198242) \n", 555 | " (-0.7897705751424646, -0.8060195845846594) " 556 | ] 557 | }, 558 | "execution_count": 30, 559 | "metadata": {}, 560 | "output_type": "execute_result" 561 | } 562 | ], 563 | "source": [ 564 | "[myrand() for i in 1:100]" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": {}, 570 | "source": [ 571 | "#### Exercise\n", 572 | "\n", 573 | "Use an array comprehension to create an array of the distances of 100 points in 2D Cartesian space from a point at $(0, 0)$.\n", 574 | "\n", 575 | "*Hint:* You may find \"splat\", i.e. `...`, useful here. Adding `...` after a collection passed as an input argument to a function \"opens up\" that collection, passing each of the elements of the collection as inputs to the function. For example, if\n", 576 | "\n", 577 | "```\n", 578 | "a = [1, 2, 3]\n", 579 | "add_three_things(x, y, z) = x + y + z\n", 580 | "```\n", 581 | "then `add_three_things(a)` will give an error, but `add_three_things(a...)` will yield `6`, just as if you had run `add_three_things(a[1], a[2], a[3])`" 582 | ] 583 | }, 584 | { 585 | "cell_type": "code", 586 | "execution_count": 34, 587 | "metadata": {}, 588 | "outputs": [ 589 | { 590 | "data": { 591 | "text/plain": [ 592 | "6" 593 | ] 594 | }, 595 | "execution_count": 34, 596 | "metadata": {}, 597 | "output_type": "execute_result" 598 | } 599 | ], 600 | "source": [ 601 | "a = [1, 2, 3]\n", 602 | "add_three_things(x, y, z) = x + y + z\n", 603 | "add_three_things(a...)" 604 | ] 605 | }, 606 | { 607 | "cell_type": "code", 608 | "execution_count": 31, 609 | "metadata": {}, 610 | "outputs": [ 611 | { 612 | "data": { 613 | "text/plain": [ 614 | "100-element Array{Float64,1}:\n", 615 | " 0.9383872456685842 \n", 616 | " 0.5839277168087241 \n", 617 | " 0.7355502495040855 \n", 618 | " 0.8441859785114507 \n", 619 | " 0.6807536016582622 \n", 620 | " 0.7632412130157962 \n", 621 | " 0.7317234224262192 \n", 622 | " 0.8824052199190965 \n", 623 | " 0.7755182140496781 \n", 624 | " 0.9744510181703258 \n", 625 | " 0.25005959593047916\n", 626 | " 1.0612231389451416 \n", 627 | " 1.0606971366415012 \n", 628 | " ⋮ \n", 629 | " 0.9484156186801598 \n", 630 | " 0.9270152199659667 \n", 631 | " 0.6614786312111012 \n", 632 | " 0.6478811880980543 \n", 633 | " 0.23342156646680173\n", 634 | " 1.1057076816888292 \n", 635 | " 0.5958913950161429 \n", 636 | " 1.2529131820213943 \n", 637 | " 0.7256403533033896 \n", 638 | " 0.910877586092377 \n", 639 | " 0.779338060314894 \n", 640 | " 0.16368015145789885" 641 | ] 642 | }, 643 | "execution_count": 31, 644 | "metadata": {}, 645 | "output_type": "execute_result" 646 | } 647 | ], 648 | "source": [ 649 | "[dist(myrand()...) for i in 1:100]" 650 | ] 651 | }, 652 | { 653 | "cell_type": "code", 654 | "execution_count": null, 655 | "metadata": {}, 656 | "outputs": [], 657 | "source": [] 658 | }, 659 | { 660 | "cell_type": "code", 661 | "execution_count": null, 662 | "metadata": {}, 663 | "outputs": [], 664 | "source": [] 665 | }, 666 | { 667 | "cell_type": "code", 668 | "execution_count": null, 669 | "metadata": {}, 670 | "outputs": [], 671 | "source": [] 672 | }, 673 | { 674 | "cell_type": "code", 675 | "execution_count": null, 676 | "metadata": {}, 677 | "outputs": [], 678 | "source": [] 679 | }, 680 | { 681 | "cell_type": "code", 682 | "execution_count": null, 683 | "metadata": {}, 684 | "outputs": [], 685 | "source": [] 686 | }, 687 | { 688 | "cell_type": "code", 689 | "execution_count": null, 690 | "metadata": {}, 691 | "outputs": [], 692 | "source": [] 693 | }, 694 | { 695 | "cell_type": "code", 696 | "execution_count": null, 697 | "metadata": {}, 698 | "outputs": [], 699 | "source": [] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": null, 704 | "metadata": {}, 705 | "outputs": [], 706 | "source": [] 707 | } 708 | ], 709 | "metadata": { 710 | "kernelspec": { 711 | "display_name": "Julia 1.0.1", 712 | "language": "julia", 713 | "name": "julia-1.0" 714 | }, 715 | "language_info": { 716 | "file_extension": ".jl", 717 | "mimetype": "application/julia", 718 | "name": "julia", 719 | "version": "1.0.1" 720 | } 721 | }, 722 | "nbformat": 4, 723 | "nbformat_minor": 2 724 | } 725 | -------------------------------------------------------------------------------- /JuliaCon2019_Huda/Performance Tips for Julia.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Performance tips for Julia" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## 1. As a rule of thumb, typed functions run faster. \n", 15 | "Let us revisit types first. When a type is not specified, it is assumed to be `Any`. Just a quick recap on types:" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "function _show_subtype_tree(mytype,printlevel)\n", 25 | " allsubtypes = subtypes(mytype)\n", 26 | " for cursubtype in allsubtypes\n", 27 | " print(\"\\t\"^printlevel)\n", 28 | " println(\"|___\",cursubtype)\n", 29 | " printlevel += 1\n", 30 | " _show_subtype_tree(cursubtype,printlevel)\n", 31 | " printlevel -= 1\n", 32 | " end\n", 33 | "end\n", 34 | "function show_type_tree(T)\n", 35 | " println(T)\n", 36 | " _show_subtype_tree(T,0)\n", 37 | "end\n", 38 | "show_type_tree(Number)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "function square_plus_one(v::T) where T <:Number\n", 48 | " g = v*v\n", 49 | " return g+1\n", 50 | "end" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "v = rand()\n", 60 | "typeof(v)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "@code_warntype square_plus_one(v)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "w = 5\n", 79 | "typeof(w)" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "@code_warntype square_plus_one(w)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "Great! In the above two examples, we were able to predict what the output will be. This is because:\n", 96 | "```\n", 97 | "function square_plus_one(v::T) where T <:Number\n", 98 | " g = v*v # Type(T * T) ==> T\n", 99 | " return g+1 # Type(T + Int)) ==> \"max\" (T,Int)\n", 100 | "end\n", 101 | "\n", 102 | "```\n", 103 | "Note that in both calls the return type was different, once `Float64` and once `Int64`. But the function is *still type stable*.\n", 104 | "\n", 105 | "Now let's move to something more interesting. Let's create our first type." 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": null, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "mutable struct Cube\n", 115 | " length\n", 116 | " width\n", 117 | " height\n", 118 | "end" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "volume(c::Cube) = c.length*c.width*c.height" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "mutable struct Cube_typed\n", 137 | " length::Float64\n", 138 | " width::Float64\n", 139 | " height::Float64\n", 140 | "end\n", 141 | "volume(c::Cube_typed) = c.length*c.width*c.height" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "mutable struct Cube_parametric_typed{T <: Real}\n", 151 | " length::T\n", 152 | " width::T\n", 153 | " height::T\n", 154 | "end\n", 155 | "volume(c::Cube_parametric_typed) = c.length*c.width*c.height" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "c1 = Cube(1.1,1.2,1.3)\n", 165 | "c2 = Cube_typed(1.1,1.2,1.3)\n", 166 | "c3 = Cube_parametric_typed(1.1,1.2,1.3)\n", 167 | "@show volume(c1) == volume(c2) == volume(c3)" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "metadata": {}, 174 | "outputs": [], 175 | "source": [ 176 | "using BenchmarkTools\n", 177 | "@btime volume(c1) # not typed\n", 178 | "@btime volume(c2) # typed float\n", 179 | "@btime volume(c3) # typed parametric" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "The second function call is the fastest! Let's call `@code_warntype` and check type stability" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "@code_warntype volume(c1)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [ 204 | "@code_warntype volume(c2)" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": null, 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "@code_warntype volume(c3)" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "### Conclusion: \n", 221 | "Types matter, when you know anything about the types of your variables, include them in your code to make it run faster" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "function zero_or_val(x::Real)\n", 231 | " if x >= 0\n", 232 | " return x\n", 233 | " else\n", 234 | " return 0\n", 235 | " end\n", 236 | "end\n", 237 | "@code_warntype zero_or_val(0.2)" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": null, 243 | "metadata": {}, 244 | "outputs": [], 245 | "source": [ 246 | "function zero_or_val_stable(x::Real)\n", 247 | " T = promote_type(typeof(x),Int)\n", 248 | " if x >= 0\n", 249 | " return T(x)\n", 250 | " else\n", 251 | " return T(0)\n", 252 | " end\n", 253 | "end\n", 254 | "@code_warntype zero_or_val_stable(0.2)" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "### Conclusion\n", 262 | "You can avoid type instable code by using the `promote_type` function which returns the highest of the two types passed." 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "Let us say we want to play the following game, I give you a vector of numbers. And you want to accumulate the sum as follows. For each number in the vector, you toss a coin (`rand()`), if it is heads (`>=0.5`), you add `1`. Otherwise, you add the number itself." 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "function flipcoin_then_add(v::Vector{T}) where T <: Real\n", 279 | " s = 0\n", 280 | " for vi in v\n", 281 | " r = rand()\n", 282 | " if r >=0.5\n", 283 | " s += 1\n", 284 | " else\n", 285 | " s += vi\n", 286 | " end\n", 287 | " end\n", 288 | "end\n", 289 | "\n", 290 | "function flipcoin_then_add_typed(v::Vector{T}) where T <: Real\n", 291 | " s = zero(T)\n", 292 | " for vi in v\n", 293 | " r = rand()\n", 294 | " if r >=0.5\n", 295 | " s += one(T)\n", 296 | " else\n", 297 | " s += vi\n", 298 | " end\n", 299 | " end\n", 300 | "end\n", 301 | "myvec = rand(1000)\n", 302 | "@show flipcoin_then_add(myvec) == flipcoin_then_add_typed(myvec)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [ 311 | "@btime flipcoin_then_add(rand(1000))\n", 312 | "@btime flipcoin_then_add_typed(rand(1000))" 313 | ] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": {}, 318 | "source": [ 319 | "### Conclusion\n", 320 | "Think about the variables you are declaring. Do you know their types? If so, specify the type somehow." 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "metadata": {}, 326 | "source": [ 327 | "## 2. As a rule of thumb, **functions with preallocated memory run faster**" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "metadata": {}, 333 | "source": [ 334 | "A classic example here is to build an array with pre-allocated memory versus pushing to it. Let's try to build Fibonacci using both approaches" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": null, 340 | "metadata": {}, 341 | "outputs": [], 342 | "source": [ 343 | "function build_fibonacci_preallocate(n::Int)\n", 344 | " @assert n >= 2\n", 345 | " v = zeros(Int64,n)\n", 346 | " v[1] = 1\n", 347 | " v[2] = 1\n", 348 | " for i = 3:n\n", 349 | " v[i] = v[i-1] + v[i-2]\n", 350 | " end\n", 351 | " return v\n", 352 | "end" 353 | ] 354 | }, 355 | { 356 | "cell_type": "code", 357 | "execution_count": null, 358 | "metadata": {}, 359 | "outputs": [], 360 | "source": [ 361 | "function build_fibonacci_no_allocation(n::Int)\n", 362 | " @assert n >= 2\n", 363 | " v = Vector{Int64}()\n", 364 | " push!(v,1)\n", 365 | " push!(v,1)\n", 366 | " for i = 3:n\n", 367 | " push!(v,v[i-1]+v[i-2])\n", 368 | " end\n", 369 | " return v\n", 370 | "end" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "@show isequal(build_fibonacci_preallocate(10),build_fibonacci_no_allocation(10))" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": null, 385 | "metadata": {}, 386 | "outputs": [], 387 | "source": [ 388 | "n = 100\n", 389 | "@btime build_fibonacci_no_allocation(n);\n", 390 | "@btime build_fibonacci_preallocate(n);" 391 | ] 392 | }, 393 | { 394 | "cell_type": "markdown", 395 | "metadata": {}, 396 | "source": [ 397 | "### Conclusion\n", 398 | "Whenever possible, preallocate memory." 399 | ] 400 | }, 401 | { 402 | "cell_type": "markdown", 403 | "metadata": {}, 404 | "source": [ 405 | "It's also important to understand **how memory is organized in Julia**. Let's say, for _some reason_ you want to access all the elements of a matrix once. For the sake of this experiment, let's say we want to write `matrix_sum(A)` where A is a matrix" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": null, 411 | "metadata": {}, 412 | "outputs": [], 413 | "source": [ 414 | "# Create a random matrix A of size m-by-n\n", 415 | "m = 10000\n", 416 | "n = 10000\n", 417 | "A = rand(m,n)\n", 418 | ";" 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": null, 424 | "metadata": {}, 425 | "outputs": [], 426 | "source": [ 427 | "function matrix_sum_rows(A::Matrix)\n", 428 | " m,n = size(A)\n", 429 | " mysum = 0\n", 430 | " for i = 1:m # fix a row\n", 431 | " for j = 1:n # loop over cols\n", 432 | " mysum += A[i,j]\n", 433 | " end\n", 434 | " end\n", 435 | " return mysum\n", 436 | "end" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": null, 442 | "metadata": {}, 443 | "outputs": [], 444 | "source": [ 445 | "function matrix_sum_cols(A::Matrix)\n", 446 | " m,n = size(A)\n", 447 | " mysum = 0\n", 448 | " for j = 1:n # fix a column\n", 449 | " for i = 1:m # loop over rows\n", 450 | " mysum += A[i,j]\n", 451 | " end\n", 452 | " end\n", 453 | " return mysum\n", 454 | "end" 455 | ] 456 | }, 457 | { 458 | "cell_type": "code", 459 | "execution_count": null, 460 | "metadata": {}, 461 | "outputs": [], 462 | "source": [ 463 | "function matrix_sum_index(A::Matrix)\n", 464 | " m,n = size(A)\n", 465 | " mysum = 0\n", 466 | " for i = 1:m*n\n", 467 | " mysum += A[i]\n", 468 | " end\n", 469 | " return mysum\n", 470 | "end" 471 | ] 472 | }, 473 | { 474 | "cell_type": "code", 475 | "execution_count": null, 476 | "metadata": {}, 477 | "outputs": [], 478 | "source": [ 479 | "@show matrix_sum_cols(A) ≈ matrix_sum_rows(A) ≈ matrix_sum_index(A)" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": null, 485 | "metadata": {}, 486 | "outputs": [], 487 | "source": [ 488 | "@btime matrix_sum_rows(A)\n", 489 | "@btime matrix_sum_cols(A)\n", 490 | "@btime matrix_sum_index(A)" 491 | ] 492 | }, 493 | { 494 | "cell_type": "markdown", 495 | "metadata": {}, 496 | "source": [ 497 | "## Conclusion \n", 498 | "Matrices are organized column-wise in memory. It's better to access them one column at a time. Consider understanding how your data is organized in memory when you want to access it." 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": {}, 504 | "source": [ 505 | "Memory recycling is when you use a chunk of memory you no longer need for another purpose" 506 | ] 507 | }, 508 | { 509 | "cell_type": "markdown", 510 | "metadata": {}, 511 | "source": [ 512 | "Let's take this example, you have a vector b and a vector h where b[i] is the base length of triangle i and h[i] is the height length. The experiment is to find the hypotenuse value of all triangles" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "execution_count": null, 518 | "metadata": {}, 519 | "outputs": [], 520 | "source": [ 521 | "b = rand(1000)*10\n", 522 | "h = rand(1000)*10\n", 523 | "function find_hypotenuse(b::Vector{T},h::Vector{T}) where T <: Real\n", 524 | " return sqrt.(b.^2+h.^2)\n", 525 | "end" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": null, 531 | "metadata": {}, 532 | "outputs": [], 533 | "source": [ 534 | "# Let's time it\n", 535 | "@btime find_hypotenuse(b,h);" 536 | ] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "execution_count": null, 541 | "metadata": {}, 542 | "outputs": [], 543 | "source": [ 544 | "function find_hypotenuse_optimized(b::Vector{T},h::Vector{T}) where T <: Real\n", 545 | " accum_vec = similar(b)\n", 546 | " for i = 1:length(b)\n", 547 | " accum_vec[i] = b[i]^2\n", 548 | " accum_vec[i] = accum_vec[i] + h[i]^2 # here, we used the same space in memory to hold the sum\n", 549 | " accum_vec[i] = sqrt(accum_vec[i]) # same thing here, to hold the sqrt\n", 550 | " # or:\n", 551 | " # accum_vec[i] = sqrt(b[i]^2+h[i]^2)\n", 552 | " end\n", 553 | " return accum_vec\n", 554 | "end\n", 555 | "@btime find_hypotenuse_optimized(b,h);" 556 | ] 557 | }, 558 | { 559 | "cell_type": "markdown", 560 | "metadata": {}, 561 | "source": [ 562 | "## Conclusion:\n", 563 | "Whenever you can reuse memory, reuse it. \n", 564 | "\n", 565 | "## Bonus conclusion:\n", 566 | "Vectorized operations are not necessarily faster." 567 | ] 568 | }, 569 | { 570 | "cell_type": "markdown", 571 | "metadata": {}, 572 | "source": [ 573 | "One other form of memory recycling is in place operations" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": null, 579 | "metadata": {}, 580 | "outputs": [], 581 | "source": [ 582 | "function function_inplace!(v::Vector{T},myfn::Function) where T\n", 583 | " for i = 1:length(v)\n", 584 | " v[i] = myfn(v[i])\n", 585 | " end\n", 586 | " v\n", 587 | "end\n", 588 | "\n", 589 | "function function_not_inplace(v::Vector{T},myfn::Function) where T\n", 590 | " w = zeros(eltype(v),length(v))\n", 591 | " for i = 1:length(v)\n", 592 | " w[i] = myfn(v[i])\n", 593 | " end\n", 594 | " w\n", 595 | "end" 596 | ] 597 | }, 598 | { 599 | "cell_type": "code", 600 | "execution_count": null, 601 | "metadata": {}, 602 | "outputs": [], 603 | "source": [ 604 | "v = rand(100)\n", 605 | "@btime function_inplace!(v,x->x^2);\n", 606 | "@btime function_not_inplace(v,x->x^2);" 607 | ] 608 | }, 609 | { 610 | "cell_type": "markdown", 611 | "metadata": {}, 612 | "source": [ 613 | "## Conclusion:\n", 614 | "In-place operations are much cheaper, use them if you don't need the original data" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "execution_count": null, 620 | "metadata": {}, 621 | "outputs": [], 622 | "source": [ 623 | "@btime v.^2;" 624 | ] 625 | }, 626 | { 627 | "cell_type": "markdown", 628 | "metadata": {}, 629 | "source": [ 630 | "### What are iterators and why do we care about them?\n", 631 | "* We create iterator objects when we don't want to store/create all the elements in an array at once. \n", 632 | "* A quick example is a Fibonacci sequence: say you want to use the Fibonacci sequence numbers for a simple purpose but you don't necessarily care about storing all of them. You would want something like this:\n", 633 | "``` \n", 634 | "fib_iterator = fib(n)\n", 635 | "for i in fib_iterator\n", 636 | " #do something\n", 637 | "end\n", 638 | "```\n", 639 | "In the above iteration, you are not computing and storing all the fibonacci sequence numbers. Instead, we are just creating them on the fly\n", 640 | "* A lot of types in Julia are iteratable by default. A simple example is an array of numbers.\n", 641 | "```\n", 642 | "for i in rand(10)\n", 643 | " #do something\n", 644 | "end\n", 645 | "```\n", 646 | "`rand(10)` returns a vector, and a vector is iteratable" 647 | ] 648 | }, 649 | { 650 | "cell_type": "code", 651 | "execution_count": null, 652 | "metadata": {}, 653 | "outputs": [], 654 | "source": [ 655 | "struct fib_iterator\n", 656 | " n::Int\n", 657 | "end\n", 658 | "\n", 659 | "function Base.iterate(f::fib_iterator,state=(0,0,1))\n", 660 | " prev1,prev2,stepid = state\n", 661 | " # state the ending conditions first\n", 662 | " if stepid == 1\n", 663 | " return (1,(0,1,2))\n", 664 | " end\n", 665 | " if f.n < stepid\n", 666 | " return nothing\n", 667 | " end\n", 668 | " # else\n", 669 | " y = prev1+prev2\n", 670 | " stepid += 1\n", 671 | " return (y,(prev2,y,stepid))\n", 672 | "end\n", 673 | "\n", 674 | "function myfib(n)\n", 675 | " v = zeros(Int,n+1)\n", 676 | " v[1] = 1\n", 677 | " v[2] = 1\n", 678 | " for i = 3:n+1\n", 679 | " v[i] = v[i-1] + v[i-2]\n", 680 | " end\n", 681 | " return v\n", 682 | "end" 683 | ] 684 | }, 685 | { 686 | "cell_type": "code", 687 | "execution_count": null, 688 | "metadata": {}, 689 | "outputs": [], 690 | "source": [ 691 | "function test_iterator(n)\n", 692 | " f = fib_iterator(n)\n", 693 | " s = 0\n", 694 | " for i in f\n", 695 | " s += i\n", 696 | " end\n", 697 | "end\n", 698 | "function test_allocate(n)\n", 699 | " s = 0\n", 700 | " for i in myfib(n)\n", 701 | " s += i\n", 702 | " end\n", 703 | "end\n", 704 | " \n", 705 | "@btime test_iterator(10);\n", 706 | "@btime test_allocate(10);" 707 | ] 708 | }, 709 | { 710 | "cell_type": "markdown", 711 | "metadata": {}, 712 | "source": [ 713 | "## Conclusion: \n", 714 | "Iterators are a powerful tool, use them when you don't need to store the values." 715 | ] 716 | }, 717 | { 718 | "cell_type": "markdown", 719 | "metadata": {}, 720 | "source": [ 721 | "Always think about memory... Do you really need `A[row_ids,col_ids]`" 722 | ] 723 | }, 724 | { 725 | "cell_type": "code", 726 | "execution_count": null, 727 | "metadata": {}, 728 | "outputs": [], 729 | "source": [ 730 | "using SparseArrays\n", 731 | "using LinearAlgebra\n", 732 | "A = sprand(500,500,0.1)\n", 733 | "function set_sum(A,rowids,colids)\n", 734 | " s = sum(A[rowids,colids])\n", 735 | "end\n", 736 | "function set_sum_view(A,rowids,colids)\n", 737 | " s = sum(view(A,rowids,colids))\n", 738 | "end" 739 | ] 740 | }, 741 | { 742 | "cell_type": "code", 743 | "execution_count": null, 744 | "metadata": {}, 745 | "outputs": [], 746 | "source": [ 747 | "using Random\n", 748 | "@btime set_sum(A,randperm(10), randperm(10))\n", 749 | "@btime set_sum_view(A,randperm(10), randperm(10))" 750 | ] 751 | }, 752 | { 753 | "cell_type": "markdown", 754 | "metadata": {}, 755 | "source": [ 756 | "## Conclusion:\n", 757 | "You can use views if you want to apply a function on a subset of elements." 758 | ] 759 | }, 760 | { 761 | "cell_type": "markdown", 762 | "metadata": {}, 763 | "source": [ 764 | "One more idea to make your code faster: Parallelize it! But that is for a whole separat workshop (later today!)" 765 | ] 766 | }, 767 | { 768 | "cell_type": "markdown", 769 | "metadata": {}, 770 | "source": [ 771 | "## 3. There are many tools in Julia that helps you write faster code\n" 772 | ] 773 | }, 774 | { 775 | "cell_type": "markdown", 776 | "metadata": {}, 777 | "source": [ 778 | "### @profile" 779 | ] 780 | }, 781 | { 782 | "cell_type": "code", 783 | "execution_count": null, 784 | "metadata": {}, 785 | "outputs": [], 786 | "source": [ 787 | "# quick demo on REPL" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "execution_count": null, 793 | "metadata": {}, 794 | "outputs": [], 795 | "source": [ 796 | "function myfunc()\n", 797 | " A = rand(200, 200)\n", 798 | " sum(A)\n", 799 | "end" 800 | ] 801 | }, 802 | { 803 | "cell_type": "code", 804 | "execution_count": null, 805 | "metadata": {}, 806 | "outputs": [], 807 | "source": [ 808 | "using Profile" 809 | ] 810 | }, 811 | { 812 | "cell_type": "code", 813 | "execution_count": null, 814 | "metadata": {}, 815 | "outputs": [], 816 | "source": [ 817 | "@profile myfunc()" 818 | ] 819 | }, 820 | { 821 | "cell_type": "code", 822 | "execution_count": null, 823 | "metadata": {}, 824 | "outputs": [], 825 | "source": [ 826 | "Profile.print()" 827 | ] 828 | }, 829 | { 830 | "cell_type": "markdown", 831 | "metadata": {}, 832 | "source": [ 833 | "If you get a really long output specially when you are not expecting it, that is because Profile adds to a buffer. Try:\n", 834 | "```\n", 835 | "Profile.clear()\n", 836 | "Profile.init()\n", 837 | "```" 838 | ] 839 | }, 840 | { 841 | "cell_type": "markdown", 842 | "metadata": {}, 843 | "source": [ 844 | "### @inbounds" 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": null, 850 | "metadata": {}, 851 | "outputs": [], 852 | "source": [ 853 | "?@inbounds" 854 | ] 855 | }, 856 | { 857 | "cell_type": "code", 858 | "execution_count": null, 859 | "metadata": {}, 860 | "outputs": [], 861 | "source": [ 862 | "# Let us say we want to find the sum of all elements in a vector" 863 | ] 864 | }, 865 | { 866 | "cell_type": "code", 867 | "execution_count": null, 868 | "metadata": {}, 869 | "outputs": [], 870 | "source": [ 871 | "function new_sum(myvec::Vector{Int})\n", 872 | " s = 0\n", 873 | " for i = 1:length(myvec)\n", 874 | " s += myvec[i]\n", 875 | " end\n", 876 | " return s\n", 877 | "end\n", 878 | "\n", 879 | "function new_sum_inbounds(myvec::Vector{Int})\n", 880 | " s = 0\n", 881 | " @inbounds for i = 1:length(myvec)\n", 882 | " s += myvec[i]\n", 883 | " end\n", 884 | " return s\n", 885 | "end" 886 | ] 887 | }, 888 | { 889 | "cell_type": "code", 890 | "execution_count": null, 891 | "metadata": {}, 892 | "outputs": [], 893 | "source": [ 894 | "myvec = collect(1:1000000)\n", 895 | "@btime new_sum(myvec)\n", 896 | "@btime new_sum_inbounds(myvec)" 897 | ] 898 | }, 899 | { 900 | "cell_type": "code", 901 | "execution_count": null, 902 | "metadata": {}, 903 | "outputs": [], 904 | "source": [ 905 | "@show isequal(new_sum(myvec),new_sum_inbounds(myvec))" 906 | ] 907 | }, 908 | { 909 | "cell_type": "code", 910 | "execution_count": null, 911 | "metadata": {}, 912 | "outputs": [], 913 | "source": [ 914 | "# Be careful though!\n", 915 | "function new_sum_WRONG(myvec::Vector{Int})\n", 916 | " s = 0\n", 917 | " for i = 1:length(myvec)+1\n", 918 | " s += myvec[i]\n", 919 | " end\n", 920 | " return s\n", 921 | "end\n", 922 | "\n", 923 | "function new_sum_inbounds_WRONG(myvec::Vector{Int})\n", 924 | " s = 0\n", 925 | " @inbounds for i = 1:length(myvec)+1\n", 926 | " s += myvec[i]\n", 927 | " end\n", 928 | " return s\n", 929 | "end\n", 930 | "\n", 931 | "myvec = collect(1:1000000);" 932 | ] 933 | }, 934 | { 935 | "cell_type": "code", 936 | "execution_count": null, 937 | "metadata": {}, 938 | "outputs": [], 939 | "source": [ 940 | "@btime new_sum_WRONG(myvec)" 941 | ] 942 | }, 943 | { 944 | "cell_type": "code", 945 | "execution_count": null, 946 | "metadata": {}, 947 | "outputs": [], 948 | "source": [ 949 | "@btime new_sum_inbounds_WRONG(myvec) # this actually exectued!" 950 | ] 951 | }, 952 | { 953 | "cell_type": "markdown", 954 | "metadata": {}, 955 | "source": [ 956 | "### @code_XXX\n", 957 | "One cool thing about Julia is that it allows you to see the different stages of the code before all the way to native code! Let's look at these macros that allow you to achieve that" 958 | ] 959 | }, 960 | { 961 | "cell_type": "code", 962 | "execution_count": null, 963 | "metadata": {}, 964 | "outputs": [], 965 | "source": [ 966 | "# @code_llvm \n", 967 | "# @code_lowered \n", 968 | "# @code_native \n", 969 | "# @code_typed \n", 970 | "# @code_warntype\n", 971 | "\n", 972 | "function flipcoin(randval::Float64)\n", 973 | " if randval<0.5\n", 974 | " return \"H\"\n", 975 | " else\n", 976 | " return \"T\"\n", 977 | " end\n", 978 | "end" 979 | ] 980 | }, 981 | { 982 | "cell_type": "code", 983 | "execution_count": null, 984 | "metadata": {}, 985 | "outputs": [], 986 | "source": [ 987 | "@code_lowered flipcoin(rand()) # syntax tree" 988 | ] 989 | }, 990 | { 991 | "cell_type": "code", 992 | "execution_count": null, 993 | "metadata": {}, 994 | "outputs": [], 995 | "source": [ 996 | "@code_warntype flipcoin(rand()) # try @code_typed" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "code", 1001 | "execution_count": null, 1002 | "metadata": {}, 1003 | "outputs": [], 1004 | "source": [ 1005 | "@code_llvm flipcoin(rand()) # this and code_warntype are probably the most relevant" 1006 | ] 1007 | }, 1008 | { 1009 | "cell_type": "code", 1010 | "execution_count": null, 1011 | "metadata": {}, 1012 | "outputs": [], 1013 | "source": [ 1014 | "@code_native flipcoin(rand())" 1015 | ] 1016 | }, 1017 | { 1018 | "cell_type": "code", 1019 | "execution_count": null, 1020 | "metadata": {}, 1021 | "outputs": [], 1022 | "source": [] 1023 | } 1024 | ], 1025 | "metadata": { 1026 | "kernelspec": { 1027 | "display_name": "Julia 1.0.0", 1028 | "language": "julia", 1029 | "name": "julia-1.0" 1030 | }, 1031 | "language_info": { 1032 | "file_extension": ".jl", 1033 | "mimetype": "application/julia", 1034 | "name": "julia", 1035 | "version": "1.0.0" 1036 | } 1037 | }, 1038 | "nbformat": 4, 1039 | "nbformat_minor": 2 1040 | } 1041 | --------------------------------------------------------------------------------