Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

This repository contains the course materials from Math 157: Intro to Mathematical Software.

Creative Commons BY-SA 4.0 license.

Views: 3037
License: OTHER
Kernel: Julia

Math 157: Intro to Mathematical Software

UC San Diego, winter 2018

March 2, 2018: Julia (part 1 of 3)

This lecture was prepared in cooperation with Alyson Deines (Center for Communications Research), who will be giving the second part of this series on Monday, March 5.

Administrivia:

  • CAPE evaluations are available! They close Monday, March 19 at 8am. Since this course is highly experimental, your feedback will be very helpful for shaping future offerings.

  • HW5 has been returned.

Final project news:

  • After consulting with the TAs, I propose to change the due date to Sunday, March 18 at 8pm (for both parts).

  • If you are unable to be on campus during week 10 to meet with your group, please contact me immediately to set up a workaround.

  • For part 1, problem 4b, if you have trouble with the exhaustive search you may also do random sampling for this part. (This might be necessary to make 4c terminate.)

  • For part 2, you should proceed with your first choice provided that you fill out the [Google Form](https://docs.google.com/forms/d/e/1FAIpQLScw8RMWcCdWyzJK2xUgBNHoCgIkQcFmhw0_AYjZZu_j5KcKkg/viewform?usp=sf_linkGoogle Form) by 8pm tonight. Otherwise, you may be assigned a topic at random.

Advance notice for week 9:

  • No sections on Tuesday, March 6. However, during this time, you are welcome to use APM 6402 as a study room; we will also try to monitor the chat room.

  • Thomas's office hours (usually Tuesday 11am-12pm) are moved to Friday 11:30am-12:50pm.

  • Peter's office hours (usually Wednesday 3-5pm) are moved to Wednesday 5-7pm.

  • There will be an extra virtual office hour Thursday 6-7pm.

Advance notice for week 10:

  • No lectures on Monday, March 12 or Wednesday, March 14. You may wish to use this time to meet your assigned group for Part 2 of the final project.

  • There will be a lecture on Friday, March 16, on the topic of "Where to go from here?" This lecture will not be counted for course attendance; that is, the last lecture for which attendance counts is Friday, March 9.

  • My office hours on Thursday, March 15 are cancelled. All other sections and office hours meet as scheduled.

Comments on the homework

  • I will not collect this assignment before Saturday, 8pm.

  • General: if you are having trouble with your kernel crashing, you may wish to try:

  • restarting your project (click the wrench icon, then look under "Project control");

  • switching from "SageMath 8.1" to "Python 3 (Ubuntu Linux)".

  • Problem 1: The "Orange" dataset is not available via statsmodels. However, you can access it directly from R using the rpy2 module..

  • Problem 3a: The mpg dataset is in ggplot, not statsmodels: from ggplot import mpg

Pause for additional questions.

Julia: an overview

What is Julia?

  • Development on Julia was started in 2009

  • Goal: high-level + fast and geared toward numerical/technical computation

  • Officially launched in 2012

  • Currently on v0.6.2

  • MIT licensed, free and open source

Features

  • Multiple dispatch: providing the ability to define function behavior across many combinations of argument types

  • Dynamic type system: types for documentation, optimization, and dispatch

  • Good performance, approaching that of statically-compiled languages like C

  • Built-in package manager

  • Lisp-like macros and other metaprogramming facilities

  • Call Python functions: use the PyCall package

  • Call C functions directly: no wrappers or special APIs

  • Powerful shell-like capabilities for managing other processes

  • Designed for parallelism and distributed computation

  • Coroutines: lightweight “green” threading

  • User-defined types are as fast and compact as built-ins

  • Automatic generation of efficient, specialized code for different argument types

  • Elegant and extensible conversions and promotions for numeric and other types

  • Efficient support for Unicode, including but not limited to UTF-8

Competition

  • Python + Numpy/Scipy/Numba/Cython

  • Matlab

  • Octave

  • R

Why Julia when we already have good options?

https://julialang.org/blog/2012/02/why-we-created-julia

Short story: the creators wanted to start from scratch and build a high-level language specifically for scientific computing.

Reservations

Since Julia is so new, it suffers from some associated defects.

  • Still not stable (no 1.0 in sight)

  • Smaller ecosystem than the competition

This Worksheet: Basic Syntax

  1. Basic arithmetic

  2. Assign variables

  3. Comments

  4. Documentation

  5. Printing

  6. Strings

  7. Data structures

  8. Loops

  9. Array comprehensions

  10. Conditionals

  11. Functions

  12. Multiple dispatch

Make sure your kernel is set to "Julia" before proceeding.
# Add 2 + 2
4
# Subtract 3 - 1
2
# Multiply 2 * 3
6
# Divide 3/2
1.5
# Reverse divide!? 2\3
1.5
# Exponentiate 2^3
8
# Mod 12 % 7
5

Complex Numbers are also native:

(2 + 1im) * (2 - 1im)
5 + 0im
typeof(2+1im) # Gaussian integer!
Complex{Int64}
typeof((2 + 1im) * (2 - 1im))
Complex{Int64}

Rationals:

6//4
3//2

Floats:

float(6/4)
1.5
typeof(3/2)
Float64

Unlike in Python (or Sage), integers are not by default created to arbitrary precision; however, "big" integers are readily available.

typemax(Int64)
9223372036854775807
BigInt(typemax(Int64)) + 1001
9223372036854776808
typemax(Int64) + 1001
-9223372036854774808
BigInt(typemax(Int64))^2
85070591730234615847396907784232501249
typemax(Int64)^2
1

Assignment

x = 4 y = 5 x + y^2
29
typeof(x)
Int64

Unicode allowed:

😺 = "smiley cat!" typeof(😺)
String

Can reassign without worrying about types:

x = 😺 typeof(x)
String

Comments

# This is a single line comment
#= This is how we write multiple line comments. This gives us greater flexibility when commenting our code. =#

Documentation

To see the documentation for a function foo: ?foo

?typeof
search: typeof typejoin TypedSlot TypeError
typeof(x)

Get the concrete type of x.

?div
search: div divrem DivideError A_rdiv_Bt A_rdiv_Bc A_ldiv_Bt A_ldiv_Bc A_ldiv_B!
div(x, y) ÷(x, y)

The quotient from Euclidean division. Computes x/y, truncated to an integer.

julia> 9 ÷ 4 2 julia> -5 ÷ 3 -1
div(3, 2)
1

Tab-completion also works.

?divrem
search: divrem
divrem(x, y)

The quotient and remainder from Euclidean division. Equivalent to (div(x,y), rem(x,y)) or (x÷y, x%y).

julia> divrem(3,7) (0, 3) julia> divrem(7,3) (2, 1)

Print

?println
search: println print_with_color print print_shortest sprint @printf isprint
println(io::IO, xs...)

Print (using print) xs followed by a newline. If io is not supplied, prints to STDOUT.

print("bye bye") println("Hello World")
bye byeHello World
println(2 + 2)
4
x
"smiley cat!"
println("😺")
😺

Strings

Use " " or """ """ (if you want to use " in your string)

s1 = "This is a string" s2 = """This is a string with "used" as well """ println(s1) println(s2)
This is a string This is a string with "used" as well
typeof(s1)
String

Single quotes '' give a character. (This is different from Python.)

c = 'c' println(c)
c
typeof(c)
Char
'This gives an error'
syntax: invalid character literal Stacktrace: [1] include_string(::String, ::String) at ./loading.jl:522

String interpolation: a $ allows us to insert variables into a string.

number = 3 println("I have $number apples")
I have 3 apples

String concatenation:

s3 = " and this is a New string" println(string(s1, 7, s3))
This is a string7 and this is a New string

This tripped me up:

s1+s3
MethodError: no method matching +(::String, ::String) Closest candidates are: +(::Any, ::Any, ::Any, ::Any...) at operators.jl:424 Stacktrace: [1] include_string(::String, ::String) at ./loading.jl:522
s1*s3
"This is a string and this is a New string"

Data Structures

  • tuples

  • arrays

  • dictionaries

mytup = (1, 3, 'c')
(1, 3, 'c')

Yeah, yeah, indexing starts at 1 and not 0. Beware when switching back and forth between Julia and Python!

As in Python, tuples are immutable:

mytup[3] = 4
MethodError: no method matching setindex!(::Tuple{Int64,Int64,Char}, ::Int64, ::Int64) Stacktrace: [1] include_string(::String, ::String) at ./loading.jl:522

Arrays can be very Pythonesque:

myarray = [1, 2, 'c']
3-element Array{Any,1}: 1 2 'c'
myarray[2] = 4
4
myarray
3-element Array{Any,1}: 1 4 'c'

or more Matlabish:

a1 = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9
myarray[1]
1
a1[2, 3]
6

Array are mutable:

pop!(myarray)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
myarray
2-element Array{Any,1}: 1 4
push!(myarray,3)
3-element Array{Any,1}: 1 4 3

Arrays can have weird shapes.

a2 = [[1, 2, 3], [4, 5, 6, 7], [8, [9, 0]]]
3-element Array{Array{Any,1},1}: Any[1, 2, 3] Any[4, 5, 6, 7] Any[8, [9, 0]]

As with Python, be careful when assigning arrays!

newarray = myarray
3-element Array{Any,1}: 1 4 3
newarray[3] = 10
10
myarray
3-element Array{Any,1}: 1 4 10

Instead, make a copy.

myarray[3] = 3
3
newarray2 = copy(myarray)
3-element Array{Any,1}: 1 4 3
newarray2[3] = 11
11
myarray
3-element Array{Any,1}: 1 4 3
newarray
3-element Array{Any,1}: 1 4 3
newarray2
3-element Array{Any,1}: 1 4 11

Dictionaries! Different syntax than in Python.

D1 = Dict("apple" => 1.99, "pear" => 1.59, "orange" => 2.99)
Dict{String,Float64} with 3 entries: "pear" => 1.59 "orange" => 2.99 "apple" => 1.99
D1["apple"]
1.99

As with Python, dictionaries are not ordered.

D1[2]
KeyError: key 2 not found Stacktrace: [1] getindex(::Dict{String,Float64}, ::Int64) at ./dict.jl:474 [2] include_string(::String, ::String) at ./loading.jl:522

Loops

  • while loops

  • for loops

n = 0 while n < 10 n += 1 println(n) end
1 2 3 4 5 6 7 8 9 10

Note the end command to close the loop. That's needed because unlike in Python, whitespace in Julia is not syntactic.

n = 0 while n < 10 n += 1 println(n) end
1 2 3 4 5 6 7 8 9 10
n = 1 while n <= length(mytup) println(mytup[n]) n += 1 end
1 3 c

Note: starts at 1 and prints 10, inclusive. Again, this is a different convention than Python.

for n in 1:10 println(n) end
1 2 3 4 5 6 7 8 9 10

Can use to fill in arrays

rows, cols = 5, 6 a3 = fill(0, (rows, cols))
5×6 Array{Int64,2}: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
for i in 1:rows for j in 1:cols a3[i, j] = i + j end end println(a3)
[2 3 4 5 6 7; 3 4 5 6 7 8; 4 5 6 7 8 9; 5 6 7 8 9 10; 6 7 8 9 10 11]

Nested for loops:

a4 = fill(0, (rows, cols)) for i in 1:rows, j in 1:cols a4[i, j] = i + j end println(a4)
[2 3 4 5 6 7; 3 4 5 6 7 8; 4 5 6 7 8 9; 5 6 7 8 9 10; 6 7 8 9 10 11]

Array comprehensions

A more Julia way to do this is to use an array comprehension (analogous to a Python list comprehension).

a4 = [i + j for i in 1:rows, j in 1:cols] println(a4)
[2 3 4 5 6 7; 3 4 5 6 7 8; 4 5 6 7 8 9; 5 6 7 8 9 10; 6 7 8 9 10 11]

As in Python, array comprehensions allow conditionals:

[x^2 for x in 0:9 if x % 2 == 0]
5-element Array{Int64,1}: 0 4 16 36 64

Conditionals

N = 7 if N % 2 == 0 println("$N is even") elseif N %3 == 1 println("$N is congruent to 1 mod 3 but not even") else println("$N is neither") end
7 is congruent to 1 mod 3 but not even

Functions

Three ways to define a function:

function addtwo(x) x + 2 end
addtwo (generic function with 1 method)
addtwo(3)
addthree(x) = x + 3 addthree(5)
8
favfruit = fruit -> println("I like $fruit.") favfruit("apples")
I like apples.

Like Python, the functions work on whatever type makes sense...

favfruit(3)
I like 3.

but don't work when they don't make sense.

addthree("apples")
MethodError: no method matching +(::String, ::Int64) Closest candidates are: +(::Any, ::Any, ::Any, ::Any...) at operators.jl:424 +(::Complex{Bool}, ::Real) at complex.jl:247 +(::Char, ::Integer) at char.jl:40 ... Stacktrace: [1] addthree(::String) at ./In[94]:1 [2] include_string(::String, ::String) at ./loading.jl:522

Mutating vs Non-Mutating functions

Mutating functions alter the input to the function, non-mutating functions do not.

Non-mutating:

v = [3, 4, 1, 2] println(sort(v)) println(v)
[1, 2, 3, 4] [3, 4, 1, 2]

Mutating (use an !)

println(sort!(v))
[1, 2, 3, 4]
println(v)
[1, 2, 3, 4]

Functions as inputs

The Python map function has a Julia analogue:

map(addtwo, v)
4-element Array{Int64,1}: 3 4 5 6

You can also broadcast: f.(v) is the same as map(f, v). (The dot does not have its Python meaning because Julia does not have a class hierarchy.)

addthree.(v)
4-element Array{Int64,1}: 4 5 6 7

Multiple Dispatch

This does not have a Python analogue

You can define multiple functions of the same name, but declaring the input type. This gives you one generic function with multiple methods; Julia will decide at runtime which to use based on the input.

foo(x::String, y::String) = println("My inputs are both strings!") foo(x::Int, y::Int) = println("My inputs are both integers!")
foo (generic function with 2 methods)
foo("apple", "orange")
My inputs are both strings!
foo(1, 2)
My inputs are both integers!
methods(foo)

Which definition am I using?

@which foo(3, 4)
foo(3, 4.2)
foo(x::Number, y::Number) = println("My inputs are both numbers!") foo(3, 4.2)

And we can also make a fall-back method:

foo(x, y) = println("I don't care!") foo("apple", 3)