# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .jl
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Julia 1.5.3
#     language: julia
#     name: julia-1.5
# ---

# # Recitation 1: a crash course in Julia and JuMP
#
# <a href="http://julialang.org"><img src="figures/julia.png" alt="Julia" style="width: 150px;"/></a>
# <a href="http://jump.dev"><img src="figures/JuMP-logo.png" alt="JuMP" style="width: 150px;"/></a>

# ## 1. Why Julia/JuMP?
#
# - Julia is a "high-level, high-performance dynamic programming language for technical computing." Think the linear algebra power of Matlab, with the speed of C and the readability of Python.
# - JuMP is a library that allows us to easily formulate optimization problems and solve them using a variety of solvers. It provides an easy interface to implement advanced optimization techniques.
# - Check out this [talk](https://github.com/johnfgibson/whyjulia/blob/master/1-whyjulia.ipynb]) for more details on why Julia is awesome.

# ## 2. Julia basics
#
# ### 2.1 Jupyter
#
# #### What is a Jupyter notebook?
#
# - Jupyter notebooks are **documents** (like a Word document) that can contain and run code.
# - They were originally created for Python as part of the IPython project, and adapted for Julia by the **IJulia** project.
# - They are very useful to **prototype**, draw **plots**, or even for teaching material like this one.
# - The document relies only on a modern browser for rendering, and can easily be **shared**.
#
# #### How do I even open this file?
#
# Once Julia is installed, start julia and just run the following commands to install the `IJulia` package.
# ```jl
# using Pkg
# Pkg.install("IJulia")
# ```
# This should work on its own. If there is any issue, check out the [IJulia website](https://github.com/JuliaLang/IJulia.jl).
#
# Once IJulia is installed, go to the directory containing the notebook file (`Recitation 1.ipynb`), start julia and run:
# ```jl
# using IJulia
# notebook()
# ```
# A webpage should open automatically, just click on the notebook to load it.

# #### Navigating the notebook
#
# - Click `Help -> User Interface Tour` for a guided tour of the notebook interface.
# - Each notebook is composed of **cells**, that either contain code or text (`Markdown`).
# - You can edit the content of a cell by double-clicking on it (_Edit Mode_).
#
# When you are not editing a cell, you are in _Command mode_ and can edit the structure of the notebook (cells, name, options...)
#
# - Create a cell by:
#     - Clicking `Insert -> Insert Cell`
#     - Pressing `a` or `b` in Command Mode
#     - Pressing `Alt+Enter` in Edit Mode
# - Delete a cell by:
#     - Clicking `Edit -> Delete Cell`
#     - Pressing `dd`
# - Execute a cell by:
#     - Clicking `Cell -> Run`
#     - Pressing `Ctrl+Enter`
#     - Pressing `Shift+Enter` (this will also move your focus to the next cell)
#     
# Other functions:
# - Undo last text edit with `Ctrl+z` in Edit Mode
# - Undo last cell manipulation with `z` in Command Mode
# - Save notebook with `Ctrl+s` in Edit Mode
# - Save notebook with `s` in Command Mode
#
# Though notebooks rely on your browser to work, they do not require an internet connection (except for math rendering).

# ### 2.2 How to Julia
#
# Julia, as a dynamic language, can simply be used as a calculator:

1+1

sin(exp(2*pi)+sqrt(3))

# The key building blocks of Julia code are variables:

a = 1
b = 2
# This is a comment 
c = a^2 + b^3 

# Julia supports the usual `if`, `while` and `for` structures:

if c >= 10
    print("Yes")
else
    print("No")
end

i = 1
while i <= 5
    println("Why, hello!") # Print with a new line
    i += 1
end

for i = 1:3
    print("$i banana") # '$' can be used to insert variables into text
    if i>1
        print("s")
    end
    println() # Just a new line
end

# **Do not worry about writing loops**: in Julia, they are as fast as writing vectorized code, and sometimes faster!

# **Arrays** (list of numbers) are at the core of research computing and Julia's arrays are extremely optimized.

myList = [6, 7, 8]

# Array indexing starts with 1 in Julia, and arrays are mutable.

@show myList[1]
myList[3] = 4
@show myList;

# A 2-dimensional array is a Matrix

# +
A = [1 2 3
     2 1 2
     3 2 1]

A = [1 2 3; 2 1 2; 3 2 1] #same thing
# -

# ## 2.3 Reading data - CSV and DataFrames

# You can install these packages with:

using Pkg
Pkg.add("CSV")
Pkg.add("DataFrames")

using DataFrames, CSV

# We're going to load the data for our optimization example, the transportation problem, where factories and markets are both located in the 2D plane.
# - `data/supply.csv` has one row per factory, with columns for the (x, y) coordinates, and a column for the capacity
# - `data/demand.csv` has one row per market, with columns for the (x, y) coordinates, and a column for the demand

supply = CSV.read("data/supply.csv", DataFrame)
demand = CSV.read("data/demand.csv", DataFrame);
first(demand, 5)

# ## 3. Basics of JuMP
#
# Now we will use this data to formulate and solve the transportation problem. First, we need to install a solver. A good choice is the Gurobi solver. You can follow [these instructions](https://github.com/jump-dev/Gurobi.jl) to install both Gurobi and its Julia wrapper `Gurobi.jl`.
#
# Then we can load JuMP and Gurobi.

using JuMP, Gurobi

# We're going to use JuMP to "translate" our transportation problem (see slides) into something that Gurobi can solve.

"Function to build the transportation model, returns model and decision variable handles"
function build_transportation_model(supply::DataFrame, demand::DataFrame)
    # initialize the model, and specify the solver
    model = Model(Gurobi.Optimizer)
    # Decision variables

    # Capacity constraint

    # Demand constraint

    # Objective

    return model, x
end

# We can now build the optimization model. Notice that Jupyter can display the model (but beware output overload for large models).

model, x = build_transportation_model(supply, demand)

model

x

# Now we can solve the model using the `optimize!` command. The `!` is a Julia convention that indicates that the function modifies its argument (in this case, by solving the optimization problem).

optimize!(model)

# Now we can extract the optimal objective:

objective_value(model)

# We can also obtain the optimal variable values:

value(x[1, 4])

[value(x[i, j]) for i=1:nrow(supply), j=1:nrow(demand)]



StarcoderdataJupyterScriptsDedupFiltered