Raghav K. Chhetri
09/18/2020

Running Julia 1.5.1 on 64-bit Windows 10

Contents

Installation

Handly resources:

  1. Computational Thinking, MIT 18.S191, Fall 2020
  2. Modern Numerical Computing, MIT 18.337/6.338
  3. Introduction to Computer Vision with Julia
  4. MATLAB-Python-Julia Cheatsheet

Julia terminal

After you double-click the Julia desktop icon, you are brought to a julia> prompt

This is the Julia terminal, which is also called a Julia REPL. This terminal allows you to run your Julia commands and programs.

Here are a few basic things you can try out on a Julia terminal:

    julia> 
    This is a Julia-specific terminal or Julia REPL

    julia> VERSION
    Returns Julia version installed

    julia> versioninfo()
    Returns Julia version and platform information

    julia> pwd()
    Present working directory

    julia> homedir()
    Go to home directory, which for me is "C:\\Users\Raghav"

    julia> cd ("D:\\")
    Go to D:\\ directory

    julia> cd()
    Go back to home directory

    julia> readdir()
    List directory contents

    julia> readdir(join=true)
    Lists directory contents with full paths

Package manager

Julia comes with a built-in package manager, which can be invoked by typing ] in the julia prompt.

    julia> ]        
    (@v1.5) pkg>

    Exit to the julia terminal with Ctrl+C

Let's install a few packages using the built-in package manager: Julia packages

    (@v1.5) pkg> add IJulia
    Julia kernel for Jupyter

    (@v1.5) pkg> add PyPlot
    Julia interface to a popular plotting library in Python

    (@v1.5) pkg> add DataFrames
    Tools to work with tabular data in Julia

    (@v1.5) pkg> add SymPy
    Python's Symbolic Mathematics library in Julia

    (@v1.5) pkg> add Images
    Image processing library in Julia

    (@v1.5) pkg> add ImageView
    Image Display GUI for Julia

    (@v1.5) pkg> add Interact
    Web-based widgets to make Julia code interactive

    (@v1.5) pkg> add FileIO
    Framework to detect file formats and dispatch to readers/writers

Invoke installed package into your Julia environment as:

julia> using <Name-of-package>

Shell Commands on Unix-like OS

On Unix-like OS (MacOS and Linux), Shell commands can also be executed directly from the Jupyter notebook using a semicolon before the command. These shell commands are then handled by the default system shell.

Eg., ; pwd to list present working directory

Note: doesn't work on Windows PC

Notebook

Pluto

Run a reactive Pluto notebook on a browser:

julia> using Pluto
julia> Pluto.run()

Jupyter

Run Julia as a notebook on a browser as follows:

julia> using IJulia
julia> notebook(dir= "D:\\Documents\\...\\", detached=true) 
Opens Jupyter notebook in directory 'dir' on a browser

Basic Jupyter notebook tips

Julia terminal can be accessed directly from the notebook too:

Let's check the current status of the packages that I've installed thus far:

Now finally let's try some Julia!

Basic operations

Conventions:

  1. Define variables in lower case
  2. When you need to separate words in variable name, do so using an underscore '_'
  3. Types and Modules in Julia start with a capital letter
  4. Functions that write to their arguments end in !... more on this later

Unicode symbols can be inserted in your code using \tab key after the LaTeX symbol. For instance: \alpha + Tab below:

Full list of Unicode symbols here

So, although 1 is an integer, and 1.0 is a float, numerically they are equal, and thus both == and isequal return true

== checks for numerical equality

=== evaluates to true only when two objects are programmatically indistinguishable and you cannot write code that demonstrates any difference between them. So, only true when both are not only numerically the same but also share the same memory locations. More here

Integer division

\div + Tab

Modulo operation

Power, logs and roots

Random numbers

More on random number genration here

Variables and Copies

Now, let's modify elements of x and see what happens to y

We see that the elements of y are also updated since both variables are bound to the same object and modifying that object's content impacts both variables

And, it works both ways i.e., modifying elements of y also updates the elements x is referencing to:

Next, let's see what happens when we assign an entirely new object to x. Does y follow?

In this case, we see that only x is updated since an entirely new object was assigned to x. In other words, x is now bound to this new object, whereas y still remains bound to the previous object

Now, if you wish to create a separate copy altogether, we need to use copy or deepcopy:

copy(x)

Create a shallow copy of x: the outer structure is copied, but not all internal values. For example, copying an array produces a new array with identically-same elements as the original.

deepcopy(x)

Create a deep copy of x: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling deepcopy on an object should generally have the same effect as serializing and then deserializing it.

Only a changed this time and the copies b and c were unaffected

Next, let's tinker with the content of the nested array at the 4th index of a and see what happens:

This time, change to the nested array in a carried over to the shallow copy b whereas the deep copy c remained unaffected

So, we see that the shallow copy b and the original a share their contents in the array at the 4th index as copy didn't recursively look inside the array at this index

Moreover, if we were to replace the 4th index of a entirely (not tinkering with the contents, a pure replacement), then it only affects a

Vectorized 'dot' operation

Every binary operation such as +, -, ^, *, / etc has a vectorized version in Julia, which performs element-by-element operation by default.

Btw, for multiplication * and full division/, both the dotted versions .* or ./ give the same result as the undotted versions * and / when an array is multiplied by a number. See Matrices below for a departure from this.

Multi-dimensional arrays

In this case, notice how the dotted multiplication .*also gave the same result as a regular Matrix multiplication. So, one might incorrectly conclude that .* is also performing Matrix multiplication. However, under the hood, the former is an element-by-element operation whereas the latter is doing a true Matrix multiplication.

During element-by-element multiplication, this is what happens:

x is broadcast across additional columns to form this 3x3 array:

1 1 1
8 8 8
7 7 7

and, y is broadcast across additional rows to form this 3x3 array:

7 6 5
7 6 5
7 6 5

Then, an element-by-element multiplication is performed, which outputs a 3x3 array.

The difference between the two operations becomes clear if we permute the order of multiplication:

Since the dotted multiplication is broadcasting first and doing an element-by-element multiplication, y .* x and x .* y give the same 3x3 array. However, x * y and y * x perform Matrix multiplication and thus the resulting matrices are of different sizes.

Function

Generate plots using PyPlot

PyCall

Using Python libraries from Julia

Using pylab interrupts the kernel >> "The kernel appears to have died. It will restart automatically"

However, if PyPlot is in the system, then that doesn't happen...

To be continued...