%\documentstyle[11pt]{article}
%\input{title}

%\include{macros}
%\makeindex

%\begin{document}
%\coverpage{The module {\tt Equality}}{Cristina CORNES}

%\tableofcontents

\chapter[Tactics for inductive types and families]{Tactics for inductive types and families\label{Addoc-equality}}

This chapter details a few special tactics useful for inferring facts
from inductive hypotheses. They can be considered as tools that
macro-generate complicated uses of the basic elimination tactics for
inductive types.

Sections \ref{inversion_introduction} to \ref{inversion_using}  present
inversion tactics and Section~\ref{scheme} describes
a command {\tt Scheme} for automatic generation of induction schemes
for mutual inductive types.

%\end{document}
%\documentstyle[11pt]{article}
%\input{title}

%\begin{document}
%\coverpage{Module Inv: Inversion Tactics}{Cristina CORNES}

\section[Generalities about inversion]{Generalities about inversion\label{inversion_introduction}}
When working with (co)inductive predicates, we are very often faced to
some of these situations:
\begin{itemize}
\item we have an inconsistent instance of an inductive predicate in the
  local context of hypotheses. Thus, the current goal can be trivially
  proved by absurdity.

\item we have a hypothesis that is an instance of an inductive
  predicate, and the instance has some variables whose constraints we
  would like to derive.
\end{itemize}

The inversion tactics are very useful to simplify the work in these
cases. Inversion tools can be classified in three groups:
\begin{enumerate}
\item tactics for inverting an instance without stocking the inversion
  lemma in the context:
  (\texttt{Dependent})  \texttt{Inversion} and
 (\texttt{Dependent}) \texttt{Inversion\_clear}.
\item commands for generating and stocking in the context the inversion
  lemma corresponding to an instance: \texttt{Derive}
  (\texttt{Dependent}) \texttt{Inversion}, \texttt{Derive}
  (\texttt{Dependent}) \texttt{Inversion\_clear}.
\item tactics for inverting an instance using an already defined
  inversion lemma: \texttt{Inversion \ldots using}.
\end{enumerate}

These tactics work for inductive types of arity $(\vec{x}:\vec{T})s$
where $s \in \{Prop,Set,Type\}$. Sections \ref{inversion_primitive},
\ref{inversion_derivation} and \ref{inversion_using}
describe respectively each group of tools.

As inversion proofs may be large in size, we recommend the user to
stock the lemmas whenever the same instance needs to be inverted
several times.\\

Let's consider the relation \texttt{Le} over natural numbers and the
following variables:

\begin{coq_eval}
Restore State "Initial".
\end{coq_eval}

\begin{coq_example*}
Inductive Le : nat -> nat -> Set :=
  | LeO : forall n:nat, Le 0%N n
  | LeS : forall n m:nat, Le n m -> Le (S n) (S m).
Variable P : nat -> nat -> Prop.
Variable Q : forall n m:nat, Le n m -> Prop.
\end{coq_example*}

For example purposes we defined  \verb+Le: nat->nat->Set+
 but we may have defined
it \texttt{Le} of type \verb+nat->nat->Prop+ or \verb+nat->nat->Type+.

\section[Inverting an instance]{Inverting an instance\label{inversion_primitive}}
\subsection{The non dependent case}
\begin{itemize}

\item \texttt{Inversion\_clear} \ident~\\
\index{Inversion-clear@{\tt Inversion\_clear}}
  Let the type of \ident~ in the local context be $(I~\vec{t})$,
  where $I$ is a (co)inductive predicate. Then,
  \texttt{Inversion} applied to \ident~ derives for each possible
  constructor $c_i$ of $(I~\vec{t})$, {\bf all} the necessary
  conditions that should hold for the instance $(I~\vec{t})$ to be
  proved by $c_i$. Finally it erases \ident~ from the context.

For example, consider the goal:
\begin{coq_eval}
Lemma ex : forall n m:nat, Le (S n) m -> P n m.
intros.
\end{coq_eval}

\begin{coq_example}
Show.
\end{coq_example}

To prove the goal we may need to reason by cases on \texttt{H} and to
 derive that \texttt{m}  is necessarily of
the form $(S~m_0)$ for certain $m_0$ and that $(Le~n~m_0)$.
Deriving these conditions corresponds to prove that the
only possible constructor of \texttt{(Le (S n) m)}  is
\texttt{LeS} and that we can invert the
\texttt{->} in the type  of \texttt{LeS}.
This inversion is possible because \texttt{Le} is the smallest set closed by
the constructors \texttt{LeO} and \texttt{LeS}.

\begin{coq_example}
inversion_clear H.
\end{coq_example}

Note that \texttt{m} has been substituted in the goal for \texttt{(S m0)}
and that the hypothesis \texttt{(Le n m0)} has been added to the
context.

\item \texttt{Inversion} \ident~\\
\index{Inversion@{\tt Inversion}}
  This tactic differs from   {\tt Inversion\_clear} in the fact that
  it adds the equality constraints in the context and
  it does not erase  the hypothesis \ident.

In the previous example, {\tt Inversion\_clear}
has substituted \texttt{m} by \texttt{(S m0)}. Sometimes it is
interesting to have the equality \texttt{m=(S m0)} in the
context to use it after. In that case we can use  \texttt{Inversion} that
does not clear the equalities:

\begin{coq_example*}
Undo.
\end{coq_example*}
\begin{coq_example}
inversion H.
\end{coq_example}

\begin{coq_eval}
Undo.
\end{coq_eval}

Note that the hypothesis \texttt{(S m0)=m} has been deduced and
\texttt{H} has not been cleared from the context.

\end{itemize}

\begin{Variants}

\item \texttt{Inversion\_clear } \ident~ \texttt{in} \ident$_1$ \ldots
  \ident$_n$\\
\index{Inversion_clear...in@{\tt Inversion\_clear...in}}
  Let \ident$_1$ \ldots \ident$_n$, be identifiers in the local context. This
  tactic behaves as generalizing \ident$_1$ \ldots \ident$_n$, and then performing
  {\tt Inversion\_clear}.

\item \texttt{Inversion } \ident~ \texttt{in} \ident$_1$ \ldots \ident$_n$\\
\index{Inversion ... in@{\tt Inversion ... in}}
  Let \ident$_1$ \ldots \ident$_n$, be identifiers in the local context. This
  tactic behaves as generalizing \ident$_1$ \ldots \ident$_n$, and then performing
  \texttt{Inversion}.

\item \texttt{Simple Inversion} \ident~ \\
\index{Simple Inversion@{\tt Simple Inversion}}
  It is a very primitive inversion tactic that derives all the necessary
  equalities  but it does not simplify
  the  constraints as \texttt{Inversion} and
  {\tt Inversion\_clear} do.

\end{Variants}

\subsection{The dependent case}
\begin{itemize}
\item \texttt{Dependent Inversion\_clear} \ident~\\
\index{Dependent Inversion-clear@{\tt Dependent Inversion\_clear}}
  Let the type of \ident~ in the local context be $(I~\vec{t})$,
  where $I$ is a (co)inductive predicate, and let the goal  depend both on
  $\vec{t}$ and \ident. Then,
  \texttt{Dependent Inversion\_clear} applied to \ident~ derives
   for each possible constructor $c_i$ of $(I~\vec{t})$, {\bf all} the
  necessary conditions that should hold for the instance $(I~\vec{t})$ to be
  proved by $c_i$. It also substitutes  \ident~ for the corresponding
  term  in the goal and  it erases \ident~ from the context.

For example, consider the  goal:
\begin{coq_eval}
Lemma ex_dep : forall (n m:nat) (H:Le (S n) m), Q (S n) m H.
intros.
\end{coq_eval}

\begin{coq_example}
Show.
\end{coq_example}

As \texttt{H} occurs in the goal, we may want to reason by cases on its
structure and so, we would like  inversion tactics to
substitute \texttt{H} by the corresponding term in constructor form.
Neither \texttt{Inversion} nor  {\tt Inversion\_clear} make such a
substitution. To have such a behavior we use the dependent inversion tactics:

\begin{coq_example}
dependent inversion_clear H.
\end{coq_example}

Note that \texttt{H} has been substituted by \texttt{(LeS n m0 l)} and
\texttt{m} by \texttt{(S m0)}.

\end{itemize}

\begin{Variants}

\item \texttt{Dependent Inversion\_clear } \ident~ \texttt{ with } \term\\
\index{Dependent Inversion_clear...with@{\tt Dependent Inversion\_clear...with}}
 \noindent Behaves as \texttt{Dependent Inversion\_clear} but allows giving
  explicitly the good generalization of the goal. It is useful when
  the system fails to generalize the goal automatically. If
  \ident~ has type $(I~\vec{t})$ and $I$ has type
  $(\vec{x}:\vec{T})s$,   then \term~  must be of type
  $I:(\vec{x}:\vec{T})(I~\vec{x})\rightarrow s'$ where $s'$ is the
  type of the goal.

\item \texttt{Dependent Inversion} \ident~\\
\index{Dependent Inversion@{\tt Dependent Inversion}}
 This tactic differs from   \texttt{Dependent Inversion\_clear} in the fact that
  it also  adds the equality constraints in the context and
  it does not erase  the hypothesis \ident~.

\item \texttt{Dependent Inversion } \ident~ \texttt{ with } \term \\
\index{Dependent Inversion...with@{\tt Dependent Inversion...with}}
  Analogous to \texttt{Dependent Inversion\_clear .. with..} above.
\end{Variants}

\section[Deriving the inversion lemmas]{Deriving the inversion lemmas\label{inversion_derivation}}
\subsection{The non dependent case}

The tactics (\texttt{Dependent}) \texttt{Inversion} and (\texttt{Dependent})
{\tt Inversion\_clear} work on a
certain instance $(I~\vec{t})$ of an inductive predicate. At each
application, they inspect the given instance and derive the
corresponding inversion lemma.  If we have to invert the same
instance several times it is recommended to stock the lemma in the
context and to reuse it whenever we need it.

The families of commands \texttt{Derive Inversion}, \texttt{Derive
Dependent Inversion}, \texttt{Derive} \\ {\tt Inversion\_clear} and \texttt{Derive Dependent Inversion\_clear}
allow to generate inversion lemmas for given instances and sorts.  Next
section describes the tactic \texttt{Inversion}$\ldots$\texttt{using} that refines the
goal with a specified inversion lemma.

\begin{itemize}

\item \texttt{Derive Inversion\_clear} \ident~ \texttt{with}
  $(\vec{x}:\vec{T})(I~\vec{t})$ \texttt{Sort} \sort~ \\
\index{Derive Inversion_clear...with@{\tt Derive Inversion\_clear...with}}
  Let $I$ be an inductive predicate and $\vec{x}$ the variables
  occurring in $\vec{t}$. This command generates and stocks
  the inversion lemma for the sort  \sort~  corresponding to the instance
  $(\vec{x}:\vec{T})(I~\vec{t})$ with the name \ident~ in the {\bf
    global} environment. When applied it is equivalent to have
  inverted the instance with the tactic {\tt Inversion\_clear}.

  For example, to generate the inversion lemma for the instance
 \texttt{(Le (S n) m)} and the sort \texttt{Prop} we do:
\begin{coq_example}
Derive Inversion_clear leminv with (forall n m:nat, Le (S n) m) Sort
 Prop.
\end{coq_example}

Let us  inspect the type of the generated lemma:
\begin{coq_example}
Check leminv.
\end{coq_example}

\end{itemize}

%\variants
%\begin{enumerate}
%\item \verb+Derive Inversion_clear+  \ident$_1$ \ident$_2$ \\
%\index{Derive Inversion_clear@{\tt Derive Inversion\_clear}}
%  Let \ident$_1$ have type $(I~\vec{t})$ in the local context ($I$
%  an inductive predicate).  Then, this command has the same semantics
%  as \verb+Derive Inversion_clear+ \ident$_2$~ \verb+with+
%  $(\vec{x}:\vec{T})(I~\vec{t})$ \verb+Sort Prop+ where $\vec{x}$ are the free
%  variables of $(I~\vec{t})$ declared in the local context (variables
%  of the global context are considered as constants).
%\item \verb+Derive Inversion+ \ident$_1$~ \ident$_2$~\\
%\index{Derive Inversion@{\tt Derive Inversion}}
% Analogous to the previous command.
%\item \verb+Derive Inversion+ $num$ \ident~ \ident~ \\
%\index{Derive Inversion@{\tt Derive Inversion}}
%  This command behaves as \verb+Derive Inversion+ \ident~ {\it
%    namehyp} performed on the goal number $num$.
%
%\item \verb+Derive Inversion_clear+ $num$ \ident~ \ident~ \\
%\index{Derive Inversion_clear@{\tt Derive Inversion\_clear}}
%  This command behaves as \verb+Derive Inversion_clear+ \ident~
%  \ident~ performed on the goal number $num$.
%\end{enumerate}

A derived inversion lemma is  adequate for inverting the instance
with which it was generated,  \texttt{Derive} applied to
different instances yields different lemmas. In general, if we generate
the inversion lemma with
an instance $(\vec{x}:\vec{T})(I~\vec{t})$ and a sort $s$,  the inversion lemma will
expect a predicate of type $(\vec{x}:\vec{T})s$ as first argument. \\

\begin{Variant}
\item \texttt{Derive Inversion} \ident~ \texttt{with}
  $(\vec{x}:\vec{T})(I~\vec{t})$ \texttt{Sort} \sort\\
\index{Derive Inversion...with@{\tt Derive Inversion...with}}
     Analogous of \texttt{Derive Inversion\_clear .. with ..} but
 when applied it is equivalent to having
  inverted the instance with the tactic \texttt{Inversion}.
\end{Variant}

\subsection{The dependent case}
\begin{itemize}
\item \texttt{Derive Dependent Inversion\_clear} \ident~ \texttt{with}
  $(\vec{x}:\vec{T})(I~\vec{t})$ \texttt{Sort} \sort~ \\
\index{Derive Dependent Inversion\_clear...with@{\tt Derive Dependent Inversion\_clear...with}}
  Let $I$ be an inductive predicate. This command generates and stocks
  the dependent inversion lemma for the sort  \sort~  corresponding to the instance
  $(\vec{x}:\vec{T})(I~\vec{t})$ with the name \ident~ in the {\bf
    global} environment. When applied it is equivalent to having
  inverted the instance with the tactic \texttt{Dependent Inversion\_clear}.
\end{itemize}

\begin{coq_example}
Derive Dependent Inversion_clear leminv_dep with
 (forall n m:nat, Le (S n) m) Sort Prop.
\end{coq_example}

\begin{coq_example}
Check leminv_dep.
\end{coq_example}

\begin{Variants}
\item \texttt{Derive Dependent Inversion} \ident~ \texttt{with}
  $(\vec{x}:\vec{T})(I~\vec{t})$ \texttt{Sort} \sort~ \\
\index{Derive Dependent Inversion...with@{\tt Derive Dependent Inversion...with}}
  Analogous to \texttt{Derive Dependent Inversion\_clear}, but when
  applied  it is equivalent to having
  inverted the instance with the tactic \texttt{Dependent Inversion}.

\end{Variants}

\section[Using already defined inversion  lemmas]{Using already defined inversion  lemmas\label{inversion_using}}
\begin{itemize}
\item \texttt{Inversion} \ident \texttt{ using} \ident$'$ \\
\index{Inversion...using@{\tt Inversion...using}}
  Let \ident~ have type $(I~\vec{t})$ ($I$ an inductive
  predicate) in the local context, and \ident$'$ be a (dependent) inversion
  lemma. Then, this tactic refines the current goal with the specified
  lemma.

\begin{coq_eval}
Abort.
\end{coq_eval}

\begin{coq_example}
Show.
\end{coq_example}
\begin{coq_example}
inversion H using leminv.
\end{coq_example}

\end{itemize}
\variant
\begin{enumerate}
\item \texttt{Inversion} \ident~ \texttt{using} \ident$'$ \texttt{in} \ident$_1$\ldots \ident$_n$\\
\index{Inversion...using...in@{\tt Inversion...using...in}}
This tactic behaves as generalizing  \ident$_1$\ldots \ident$_n$,
then doing \texttt{Use Inversion} \ident~\ident$'$.
\end{enumerate}

\section[\tt Scheme ...]{\tt Scheme ...\index{Scheme@{\tt Scheme}}\label{Scheme}
\label{scheme}}
The {\tt Scheme} command is a high-level tool for generating
automatically (possibly mutual) induction principles for given types
and sorts.  Its syntax follows the schema :

\noindent
{\tt Scheme {\ident$_1$} := Induction for \term$_1$ Sort {\sort$_1$} \\
  with\\
  \mbox{}\hspace{0.1cm} .. \\
        with {\ident$_m$} := Induction for {\term$_m$} Sort
        {\sort$_m$}}\\
\term$_1$ \ldots \term$_m$ are different inductive types belonging to
the same package of mutual inductive definitions. This command
generates {\ident$_1$}\ldots{\ident$_m$} to be mutually recursive
definitions. Each term {\ident$_i$} proves a general principle
of mutual induction for objects in type {\term$_i$}.

\Example
The definition of principle of mutual induction for {\tt tree} and
{\tt forest} over the sort {\tt Set} is defined by the command:
\begin{coq_eval}
Restore State "Initial".
Variables A B : Set.
Inductive tree : Set :=
    node : A -> forest -> tree
with forest : Set :=
  | leaf : B -> forest
  | cons : tree -> forest -> forest.
\end{coq_eval}
\begin{coq_example*}
Scheme tree_forest_rec := Induction for tree
  Sort Set
  with forest_tree_rec := Induction for forest Sort Set.
\end{coq_example*}
You may now look at the type of {\tt tree\_forest\_rec} :
\begin{coq_example}
Check tree_forest_rec.
\end{coq_example}
This principle involves two different predicates for {\tt trees} and
{\tt forests}; it also has three premises each one corresponding to a
constructor of one of the inductive definitions.

The principle {\tt tree\_forest\_rec} shares exactly the same
premises, only the conclusion now refers to the property of forests.
\begin{coq_example}
Check forest_tree_rec.
\end{coq_example}

\begin{Variant}
\item {\tt Scheme {\ident$_1$} := Minimality for \term$_1$ Sort {\sort$_1$} \\
  with\\
  \mbox{}\hspace{0.1cm} .. \\
        with {\ident$_m$} := Minimality for {\term$_m$} Sort
        {\sort$_m$}}\\
Same as before but defines a non-dependent elimination principle more
natural in case of inductively defined relations.
\end{Variant}

\Example
With the predicates {\tt odd} and {\tt even} inductively defined as:
% \begin{coq_eval}
% Restore State "Initial".
% \end{coq_eval}
\begin{coq_example*}
Inductive odd : nat -> Prop :=
    oddS : forall n:nat, even n -> odd (S n)
with even : nat -> Prop :=
  | evenO : even 0%N
  | evenS : forall n:nat, odd n -> even (S n).
\end{coq_example*}
The following command generates a powerful elimination
principle:
\begin{coq_example*}
Scheme odd_even := Minimality for   odd Sort Prop
  with even_odd := Minimality for even Sort Prop.
\end{coq_example*}
The type of {\tt odd\_even} for instance will be:
\begin{coq_example}
Check odd_even.
\end{coq_example}
The type of {\tt even\_odd} shares the same premises but the
conclusion is {\tt (n:nat)(even n)->(Q n)}.

\subsection[\tt Combined Scheme ...]{\tt Combined Scheme ...\index{CombinedScheme@{\tt Combined Scheme}}\label{CombinedScheme}
\label{combinedscheme}}
The {\tt Combined Scheme} command is a tool for combining
induction principles generated by the {\tt Scheme} command.
Its syntax follows the schema :

\noindent
{\tt Combined Scheme {\ident$_0$} from {\ident$_1$}, .., {\ident$_n$}}\\
\ident$_1$ \ldots \ident$_n$ are different inductive principles that must belong to
the same package of mutual inductive principle definitions. This command
generates {\ident$_0$} to be the conjunction of the principles: it is
build from the common premises of the principles and concluded by the
conjunction of their conclusions. For exemple, we can combine the
induction principles for trees and forests:

\begin{coq_example*}
Combined Scheme tree_forest_mutind from tree_ind, forest_ind.
Check tree_forest_mutind.
\end{coq_example*}

%\end{document}


\documentclass[11pt, a4]{article}
\usepackage{geometry}
\geometry{margin=1.25in}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{amsmath}
\usepackage{graphicx}
\graphicspath{ {./figures/} }
\usepackage{placeins}
\usepackage{booktabs}
\usepackage{listings}

\title{Seoul Bike Sharing Demand \\
		\large Supervised Machine Learning: Regression - Course Project}
\author{Caio Mescouto Terra de Souza}
\date{\today}

\begin{document}

\maketitle

\section*{Introduction and Main Objective}

Nowadays rental bikes are a reality in the many urban cities in the world. One of the biggest concerns is maintaining a reliable supply of bicycles to meet public demand regardless of time and weather. However, the demand is not constant. It has, at least, seasonal fluctuation depending where the city is in addition to hourly and weather fluctuations. The maintenance schedule and the logistics of distribution of bicycles between locations are very important due to the fluctuation on demand stated before.

Regarding the main concern presented, the data set I worked on contains the count of public bikes rented at each hour in the Seoul Bike sharing System, besides weather and holiday information. The main objective of this analysis is to build a model highly interpretative where it will be possible to isolate the attributes that are mostly responsible for the demand fluctuation. Even if the goal is interpretation, we would like to avoid underfitting by simplicity and, of course, overfitting by high complexity. I believe that a highly interpretive model is more actionable because it leads to more straight actions that can change certain variables or use this variable in favor of something. In this specific case, a highly interpretative model can lead to improvements on maintenance schedule, for example.

\section*{Data Set Description}

As presented before, the data set contains the count of public bikes rented at each hour in the Seoul Bike sharing System \cite{bike}. It has 14 attributes and 8760 observations. The data set contains one year of data from december, 2017 to november, 2018. The table below summarises the attributes (Table  \ref{table:1}).

\begin{table}[h!]
\centering
\begin{tabular}{l c c}
\toprule
\textbf{Column} & \textbf{Dtype} & \textbf{Unit} \\
\midrule
Date & Datetime & year-month-day\\
Hour & int64 & hour\\
Temperature & float64 & Celsius\\
Humidity & int64 & \% \\
Windspeed & float64 & m/s \\
Visibility & int64  & 10m\\
Dew point temperature & float64 & Celsius\\
Solar radiation & float64 & MJ/m2\\
Rainfall & float64 & mm\\
Snowfall & float64 & cm \\
Seasons & object & Winter, Spring, Summer, Autumn\\
Holiday & object & Holiday, No Holiday \\
Functional day & object & Non Functional Hours, Functional Hours\\
Rented Bike count & int64 & Count of bikes rented at each hour\\
\bottomrule
\end{tabular}
\caption{Data Set Attributes}
\label{table:1}
\end{table}

\section*{Exploratory Data Analysis (EDA)}

Considering the main objective, the data exploration had 5 steps. First, data cleaning; second, to split the data into train and test data; third, to understand the distribution of the numerical variables; fourth, to analyse the correlation between than and fifth, to understand how the number of rented bikes varies through season and holiday.

Before presenting the steps, some assumptions and limitations have already to be set. The data set is one year long, so, it’s not possible to analyze properly if the demand is increasing or not because the seasonal effect will affect this analysis. Finally, it is assumed the demand for rented bikes is always fully met by the supply, meaning that we don’t have a cut off by scarcity of bikes in any observation. This assumption is needed otherwise the model is biased.

\subsection*{Data Cleaning}

The data set is almost clean, no null, no outliers, no mismatching. The only point is that the variable \textit{Functional day} flags whether the service is operational or not and, as we are interested in the demand, we can drop all no operational observations ($295$ entries) that represent only $3\%$ of the data set.

\subsection*{Data Stratified Sampling}

To avoid hacking the model it is important to split the data between train and test data as early as possible. Just after the first view and the data cleaning, the data was split using a stratified split. The stratification followed the distribution of the target variable (\textit{Rented Bike Count}) whitin 5 bins and the test set was set in $20\%$ of the data. Below the \textit{Scikit-Learn} implementation applied.

\begin{lstlisting}
StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
\end{lstlisting}

\subsection*{Numerical Variables}

This subsection covers two steps of the EDA plan (third and forth). First the histograms of all numerical variables were plotted and two problems that can interfere in modeling were spotted. First, some variables are far away from normal distributions, second the scale is also different between them. The scaling was tackled during the data preparation process that precedes the modeling process. The distribution of the target value is presented below as well as the data treatment (Figure \ref{fig:hist_target}). After analyzing the skewness of all numerical variables (Table \ref{table:2}) A log transformation was applied whenever skewness was greater than $0.4$.

\begin{figure}[!h]
\includegraphics[]{hist_target}
\centering
\caption{Target Histograms}
\label{fig:hist_target}
\end{figure}

After those transformations, the correlation between all variables (including the transformations) was carried out. In general was observed a improvement in correlation comparing the orignal variables and the transformations.

\begin{table}[h!]
\centering
\begin{tabular}{l c c}
\toprule
\textbf{Column} & \textbf{Skewness} \\
\midrule
Hour & $-0.0025$\\
Temperature & $-0.1775$\\
Humidity & $0.0704$\\
Windspeed & $0.9126$\\
Visibility & $-0.6964$\\
Dew point temperature & $-0.3394$\\
Solar radiation & $1.5026$\\
Rainfall & $14.2689$\\
Snowfall & $7.8840$ \\
\bottomrule
\end{tabular}
\caption{Data Skewness}
\label{table:2}
\end{table}

Variables that are highly correlated with each other should be avoided due to collinearity issues. As we can observe in the heatmap below (Figure \ref{fig:heatmap}), all variable transformations have highly correlation with the original one, as the correlation with the target was improved through the transformations, we dropped all originals in favor of the transformation. Finally, \textit{Dew point temperature} has high correlation with \textit{Temperature}, as the last one is more correlated with the target, it will be keeped and the former one will be dropped.

\begin{figure}[!h]
\includegraphics[]{heatmap}
\centering
\caption{Heatmap of correlations}
\label{fig:heatmap}
\end{figure}

\subsection*{Categorical Variables}

The last phase of the EDA is to analyze the relationship between the target value and the categorical variables. According to the violin plot (Figure \ref{fig:violin}) below we can easily observe that \textit{Winter} is the season when the bikes are less rented and during this season, those who ride a bike do it more as means of transportation, because \textit{No Holiday} has higher demand than \textit{Holiday}. During the \textit{Spring} the demand, in general, is higher than during \textit{Winter}, but the same pattern is observed (\textit{No Holiday}$>$\textit{Holiday}). \textit{Autumn} and \textit{Summer} have the average greater than \textit{Winter} and \textit{Spring} and are quite similar between them both, with no strong pattern between \textit{Holiday} and \textit{No Holiday}. These patterns are expected due to the difference of temperature and rainfall/snowfall. But for me it was interesting to observe these differences between \textit{Holiday/No Holiday}.

\begin{figure}[!h]
\includegraphics[]{violin}
\centering
\caption{Bike Distribution per Season and Holiday}
\label{fig:violin}
\end{figure}

\section*{Data preparation and Feature Engineering}

Some of the features engineering applied were already covered in the previous section. This section presents only the step by step used to prepare the data for modeling.

\begin{enumerate}
\item Split the data into train and test data set;
\item Filter the data only where \textit{Functional day} is True;
\item Drop \textit{Functional day, Date, Dew point temperature};
\item Data log transformation in \textit{Windspeed, Solar radiation, visibility, rainfall, snowfall};
\item Divide data set into Features and Target;
\item Data Square root transformation in Target value;
\item Scale numerical variables with \textit{Scikit-Learn}
\begin{lstlisting}
StandardScale() ;
\end{lstlisting}
\item Encode categorical variables with \textit{Scikit-Learn}
\begin{lstlisting}
OneHotEncoder(drop='first') .
\end{lstlisting}
\end{enumerate}

\section*{Model Selection}

As stated in the first section, our main objective is to set up a model as simple as possible that fits the data, but where we can understand how the target is affected by the features. This model should avoid both under and overfit and have as few variables as possible. This problem is complicated because the number of variables is high related to under and overfitting. Therefore, first the $R^2$ was chosen as a parameter to compare models, as it is a measure of how well the model fits the data (or explains the phenomenon).
The last concern is to ensure generalization (which is an overfitting concern as well), so a cross-validation model for training models should also be adopted. the Below is presented the step by step of this selection and further explanations.

\subsection{Cross-Validation}

All simulation during the model selection used the same set up for cross-validation:

\begin{lstlisting}
GridSearchCV(<model>, n_jobs=-1, param_grid=<model parameters>,
scoring='r2', return_train_score=True)
\end{lstlisting}

\subsection{Models}

Four models were shortlisted as follow:

\begin{lstlisting}
LinearRegression()
Lasso(random_state=0, max_iter=10000)
ElasticNet(random_state=0, max_iter=10000)
OrthogonalMatchingPursuit()
\end{lstlisting}

The most simple is the \textit{Linear Regression} and it is likely to underfit the data. To avoid underfitting the data we first used this model to set the optimum degree for the polynomial features. As high polynomial degrees, on the other hand, tend to overfit the data, the cross validation was applied to avoid the other extreme as well. The \textit{Polynomial Features} was optimized as follow. It's also import to highlight that small degree is consistent with more interpretability.

\begin{lstlisting}
PolynomialFeatures(degree=3, include_bias=False)
\end{lstlisting}

After the optimization three other models were selected to improve the fitness through regularization. The \textit{Lasso} regression throughout $\ell_1$ penalization tends to force some coefficients to zero and this is more prominent with $\ell_1$ penalization than $\ell_2$ penalization (\textit{Ridge}). Despite the computational superiority of the \textit{Ridge regression}, the data set is relatively small and we are more interested in interpretability, so we picked \textit{Lasso}. However, as we are also interested in a goodfit, we also set up a \textit{ElasticNet} that combines both penalties ($\ell_1\: and\: \ell_2$) and we can weight these penalties. The last model is the \textit{Orthogonal Matching Pursuit (OMP)} implements the OMP algorithm for approximating the fit of a linear model with constraints imposed on the number of non-zero coefficients (ie. the $\ell_0$ pseudo-norm) \cite{OMP}. As we are interested in the fewest possible Features and this model is highly efficient in computational terms, it is a good candidate.

\subsection{Cross-validation results}

 \begin{table}[h!]
\centering
\begin{tabular}{l c c}
\toprule
\textbf{Best Estimator} & \textbf{$R^2$} \\
\midrule
LinearRegression(normalize=True) & $0.7943$\\
Lasso(alpha=0.0060, max\_iter=10000, random\_state=0) & $0.8153$\\
ElasticNet(alpha=0.0060, l1\_ratio=1.0, max\_iter=10000,
            random\_state=0) & $0.8153$\\
OrthogonalMatchingPursuit(n\_nonzero\_coefs=155) & $0.8144$\\
\bottomrule
\end{tabular}
\caption{Cross-Validation Results}
\label{table:3}
\end{table}

Following this result it is possible to infer that \textit{Lasso} fits better than \textit{Ridge} in this data set, as the best estimator with \textit{ElasticNet} is in reality the same of \textit{Lasso} ($\ell_1ratio=1$). In brief all estimators had achieved good scores. However, as we are interested in interpretability we dropped the linear regression and will further investigate \textit{Lasso} and \textit{OrthogonalMatchingPursuit}.

\section*{Model Interpretation and Key Findings}

Two simple ways to start analysing complexity is to understand the weights and the number of non-zero coefficients. In addition to the $R^2$, Lasso is a also more simple model than OrthogonalMatchingPursuit (Table \ref{table:4}).

 \begin{table}[h!]
\centering
\begin{tabular}{l c c c}
\toprule
\textbf{Model} & \textbf{Coefficients} & \textbf{$=0$} & \textbf{$\sum{|\text{coefficients}|}$} \\
\midrule
Lasso & $168$ & $28$& $126.0955$\\
OrthogonalMatchingPursuit & $168$ & $13$ & $154.2423$\\
\bottomrule
\end{tabular}
\caption{Models Coefficients}
\label{table:4}
\end{table}

Although these measures of complexity, interpretation means to understand which variables are more responsible and in which direction they affect the target value. Below (Table \ref{table:5}) are presented the 10 more important variables with their respective coefficients for each model and the key insights. For sanity it's not repeated log all the time but \textit{Rainfall and Solar Radiation} are in fact, log transformed.

 \begin{table}[h]
\centering
\begin{tabular}{l c |c c}
\toprule
\textbf{Lasso} & \textbf{Coef.} & \textbf{OrthogonalMatchingPursuit} & \textbf{Coef.} \\
\midrule
$hour^2\times solarRad$ & $10.5964$ & $rainfall$& $-12.4247$\\
$hour\times solarRad$  & $-10.3316$ & $hour^2\times solarRad$ & $11.1473$\\
$rainfall$ & $-10.2103$ & $hour\times solarRad$ & $-10.9250$ \\
$hour^2$ & $8.3205$ & $hour^2$ & $8.8413$ \\
$temperature$ & $6.8650$ & $temperature$ & $7.3074$ \\
$winter$ & $-6.2208$ & $winter$ & $-6.3295$\\
$solarRad^2$ & $-3.8585$ & $solarRad^2\times rainfall$ & $4.7297$ \\
$hour^3$ & $-3.6222$ & $solarRad^2$ & $-4.1108$ \\
$spring$ & $-3.4217$ & $hour^3$ & $-3.7492$ \\
$solarRad^2\times rainfall$ & $3.3945$ & $spring$ & $-3.6187$ \\
\bottomrule
\end{tabular}
\caption{Main Features}
\label{table:5}
\end{table}

\subsection*{Key Findings}

\begin{itemize}
\item First of all, It is interesting that all variables are the same, with differing intensities but Lasso always has smaller coefficients than OrthogonalMatchingPursuit, meaning that Lasso is probability more regularezed than  OrthogonalMatchingPursuit;
\item Almost half of the most important variables has degree equal 3, meaning that the polynomial transformation played a important role in fitting the model;
\item Only five of the eleven variables are listed in the top 10 (\textit{Hour, Solar Radiation, Precipitation, Temperature, Season});
\item \textit{Rainfall} has a negative effect on the target, but combined with the power of \textit{Solar Radiation}, this effect is positive. As the power itself has a negative effect, Usually  days with a little bit of rain but sunny are normal in the summer and the temperature is high.
\item \textit{Hour} has different effects on the target, below it is a plot of the mean demand per hour that can help understand this erratic behavior (Figure \ref{fig:rented}).
\end{itemize}

\begin{figure}[!h]
\includegraphics[]{rented}
\centering
\caption{Mean of Rented Bikes per hour}
\label{fig:rented}
\end{figure}

\subsection*{Test set}

The last phase before choosing a model and presenting the conclusion is that both models were tested against the test data set and the result is presented below (Table \ref{table:6}).

\begin{table}[h!]
\centering
\begin{tabular}{l c c c}
\toprule
\textbf{Model} & \textbf{$R^2$} \\
\midrule
Lasso & $0.8156$ \\
OrthogonalMatchingPursuit & $0.8118$\\
\bottomrule
\end{tabular}
\caption{Models performance}
\label{table:6}
\end{table}

\section*{Model selection}

Both models had performed as good as during the cross-validation, meaning that under and overfitting were both avoided. Finally, The \textit{Lasso} regression is suggested to be adopted. The performance is better and interpretation-wise there is no difference in terms of top 10 variables, but has small coefficients and more zero-coefficients.

\section*{Next steps and Improvements}

The main flaw of the model is the granularity of the data. It is not a microdata that has information like localization of the bike or the time spent in the ride. This information would be used to improve the model, for example, connecting the flux of bikes during the period of the day or, understanding if some bikes spots are overloaded. These data should have granularity about weather as well, for example sparsity of the rain or solar radiation in different locations.

\FloatBarrier

\begin{thebibliography}{9}

\bibitem{bike}
Seoul Bike Sharing Demand Data Set,
\\\texttt{https://archive.ics.uci.edu/ml/datasets/Seoul+Bike+Sharing+Demand}

\bibitem{OMP}
1.1.9. Orthogonal Matching Pursuit (OMP),
\\\texttt{https://scikit-learn.org/stable/modules/linear\_model.html\#omp}
\end{thebibliography}

\end{document}


\documentclass[a4paper, 12pt]{article}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{longtable}
\usepackage{pdflscape}
\usepackage{algorithm}
\usepackage{graphicx}
\usepackage[noend]{algpseudocode}
\usepackage{url}
\usepackage{tikz}

\newlength\tindent
\setlength{\tindent}{\parindent}
\setlength{\parindent}{0pt}
\renewcommand{\indent}{\hspace*{\tindent}}

\newtheorem{thm}{Theorem}
\newtheorem{cor}{Corollary}[thm]
\newtheorem{lemma}{Lemma}[thm]

\title{COMP 307 Assignment 1}
\author{Daniel Braithwaite}

\begin{document}
	\pagenumbering{gobble}
	\maketitle
	\newpage
  	\pagenumbering{arabic}

  	\section{Nearest Neighbor Method}
  		\subsection{Class Labels For Test Data}
			The K1 classifier has an accuracy of $90.7\%$ on the test data set. \textbf{See Appendix A for class label data}

  		\subsection{Comparing K1 And K3}
  			With this training and test data using both K1 and K3 classifiers I find that the K3 classifier yields slightly better results with a accuracy of $93\%$ compared to the K1 classifier that has $90.7\%$. This extra accuracy is at little cost to efficiency. One might argue that we are having to inspect more neighbors, increasing the time to compute the classification. But this extra time is negligible when comparing K1 and K3 as the algorithm for computing the neighbors is order $O(mnlog(n))$, where m is the number of test instances and n is the number of training instances. However with large amounts of training and testing data increasing K could have a noticeable effect on performance.

  			Inspecting where the classifier was failing identified some interesting features of the data. The classifier never wrongly classifiys an instance as 'Iris Setosa' nor does it ever assign an instance of 'Iris Setosa' the wrong class. It only mixes up the two classes 'Iris-versicolor' and 'Iris-virginica'. This indicates that the region containing all the instances belonging to 'Iris Setosa' is disjoint from the regions containing 'Iris-versicolor' and 'Iris-virginica'. Not only this but it also shows that the regions which contain instances of class 'Iris-versicolor' or 'Iris-virginica' intersect.

  		\subsection{Nearest Neighbor Classification Discussion}

  			\begin{enumerate}

				\item \textbf{(+) Simple:} The algorithm is very simple and is easy to implement

				\item \textbf{(+) Works On Nonlinear Data:} The data doesn't have to be linearly separable for this classification method to work.

  				\item \textbf{(-) Need To Find K:} We need to find for which value of K this classification method works optimally for a given problem.

  				\item \textbf{(-) Slow For Large Data:} The way the I implemented the algorithm for classifying test instances involves sorting all n elements of the training data, then taking the first k elements. This is to be repeated for each of the m instances to classify. We therefor get the order cost of this algorithm to be $O(m(nlog(n) + n)) = O(mnlog(n))$. If a KD-Tree was used to store the training data then we could reduce this cost to $O(m(log(n) + n) = O(mn)$ which is a considerable improvement but on large training and testing data is still costly. One side effect of using the KD-Tree is that it would take longer to train the classifier as the instances have to be inserted into the tree

  				\item \textbf{(-) The Data Can Be Skewed:} In your training data maybe there is 100 data points and we know that each can belong to one of three classes. If we had $95\%$ of the data points belonging to class 1 then our data would be skewed to be giving a classification of class 1.

  			\end{enumerate}

  		\subsection{K-Fold Cross Validation}
  			The general idea for K-fold cross validation is as follows

  			\begin{enumerate}
  				\item Split the input data into k equal chunks
  				\item For each chunk
  				\begin{enumerate}
  					\item Treat the current chunk as test data and the rest of the chunks as training data
  					\item Train the classifier with the training data and run it over the testing data
  				\end{enumerate}
  				\item Average the results from each run to produce an estimation of accuracy
  			\end{enumerate}

			So for the current example we would split our iris data into 5 equal chunks and for each chunk train our nearest neighbor classifier with the remaining data and test it on our current chunk. Lastly we would be able to average the accuracy from the 5 different runs to get our final estimation of how accurate the classifier is.

  		\subsection{Clustering Problem}
  			The clustering method to use would be K-Means Clustering. The algorithm for this is as follows
  			\begin{enumerate}
  				\item Place K random centroids.
  				\item For each data point assign it to the closest centroid
  				\item For each centroid set the new location to the mean location of all points assigned to it
  				\item Return to step 2 until convergence
  			\end{enumerate}

  			For when we are wanting to create 3 clusters, we set K = 3 i.e. creating 3 centroids.

  			Using this algorithm on the iris training data we get mostly inaccurate results. We would expect to get 3 groups of size 25 as this is how our data is split up, how ever with this method we rarely get close to that

  			Another possible method of choosing the initial centroid locations would be to randomly select 3 data points and use them. This alternative method while seeming to provided more consistently accurate results also sometimes provides poor groupings.

  	\section{Decision Tree Learning}
		\subsection{Decision Tree Results}
			\paragraph{Over full test data} the decision tree has an accuracy of $81\%$ which is slightly worse than the accuracy of the baseline classifier which has $85\%$ accuracy.

			Out of the 27 test instances there are 5 incorrectly classified. The miss classifications where evenly split so don't favor ether of the classes.

			\paragraph{Over split test data} The average accuracy over the 10 trials is $78\%$ giving us a $3\%$ difference from the accuracy over the full test data. Not enough to be significant.

  		\subsection{Pruning Discussion}
  			\subsubsection{Pruning Techniques}
  				\paragraph{Reduced error pruning} involves iterating through the tree (starting at the leaves) and replacing each node with the base classifier (most popular class). If the accuracy of the decision tree is unchanged then the modified tree is kept.

  			\subsubsection{Reducing Accuracy On Training Data}
  				When generating the decision tree the only information the algorithm has is that of the training data. Therefor the algorithm generates a tree that models the data used to train it. The process of pruning the tree is to make it more general and less specific to the training data which is why after pruning the tree could perform worse on the data used to train it.

  			\subsubsection{Improving Accuracy On Testing Data}
  				Before pruning the decision tree is tailored to the training data. By pruning and making the decision tree more general it might have a better chance of correctly classifying a problem instance it hasn't seen before.

  		\subsection{Impurity Measure Discussion}
			We have list of instances L (each instance has a class in the set $N_1,...,N_k$) and a function $f$ such that $f(L)$ gives us the impurity of the set L. For $f$ to be valid the following 3 conditions must be met

			\begin{enumerate}
				\item $f(L) = 0$ if and only if all instances belong to one class (i.e. L is pure)

				\item $f$ is at max if all instances equally distributed between $k$ classes

				\item $f$ must be continuous
			\end{enumerate}

			Define $f(L)$ as

			\begin{align*}
				f(L) = P(N_1) * ... * P(N_k)
			\end{align*}

			Assume that $k > 2$ then take the first condition. Assume for our list L there is some $i < k$ such that no instance in L has class $N_i$ and every other class has at least one instance belonging to it, then we have, where $n_j = $ number of instance belonging to $N_j$

			\begin{align*}
				\frac{n_1 * ... * n_i * ... * n_k}{(n_1 + ... + n_k)^k} = \frac{n_1 * ... * 0 * ... * n_k}{(n_1 + ... + n_k)^k} = \frac{0}{(n_1 + ... + n_k)^k} = 0
			\end{align*}
			So our function gives output 0 even though L isn't pure. So $f$ doesn't meet all the conditions set out above so isn't a good measure when $k > 2$.

  \section{Perceptron Learning}
  	\subsection{Perceptron Performance}
		The perceptron classifier converges on a solution in under 100 epochs with the number of features set to 75

  	\subsection{Data Discussion}
  		Using the training data to evaluate the peformance of the perceptron is not a great mesure because the peceptron could be trained to work perfectly on the the training data but when given examples it hasnt seen before it cant classify them correctly which we cant check for if we are using the training data to validate the peformance of the perceptron.

  		I created some extra data to test the peformance of the perceptron classifier the results of which where interesting. Overall the data contained 10 instances split evenly between positive and negative examples. The accuracy of the classifier on this data was $70\%$. Upon further inspection the classifier correctly identified all the positive examples and just had trouble with negative examples.

  		An explanation for why the classifier has trouble with negative examples is because the space of negative instances is much larger than the space of positive instances. And if the negative instances in the test data are very different from the ones used while testing then this could cause the inaccuracy.

	\newpage

	\section{Appendix A (Nearest Neighbor Output)}
		\begin{center}
		\footnotesize
		\setlength\LTleft{-20pt}
		\setlength\LTright{-30pt}
		\begin{longtable}{ l l l l l l }
			\hline
			Actual Class & Sepal Length & Sepal Width & Petal Length & Petal Width & Predicted Class\\
			\hline
			Iris-setosa & 5.0cm & 3.0cm & 1.6cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.0cm & 3.4cm & 1.6cm & 0.4cm & Iris-setosa\\
Iris-setosa & 5.2cm & 3.5cm & 1.5cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.2cm & 3.4cm & 1.4cm & 0.2cm & Iris-setosa\\
Iris-setosa & 4.7cm & 3.2cm & 1.6cm & 0.2cm & Iris-setosa\\
Iris-setosa & 4.8cm & 3.1cm & 1.6cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.4cm & 3.4cm & 1.5cm & 0.4cm & Iris-setosa\\
Iris-setosa & 5.2cm & 4.1cm & 1.5cm & 0.1cm & Iris-setosa\\
Iris-setosa & 5.5cm & 4.2cm & 1.4cm & 0.2cm & Iris-setosa\\
Iris-setosa & 4.9cm & 3.1cm & 1.5cm & 0.1cm & Iris-setosa\\
Iris-setosa & 5.0cm & 3.2cm & 1.2cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.5cm & 3.5cm & 1.3cm & 0.2cm & Iris-setosa\\
Iris-setosa & 4.9cm & 3.1cm & 1.5cm & 0.1cm & Iris-setosa\\
Iris-setosa & 4.4cm & 3.0cm & 1.3cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.1cm & 3.4cm & 1.5cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.0cm & 3.5cm & 1.3cm & 0.3cm & Iris-setosa\\
Iris-setosa & 4.5cm & 2.3cm & 1.3cm & 0.3cm & Iris-setosa\\
Iris-setosa & 4.4cm & 3.2cm & 1.3cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.0cm & 3.5cm & 1.6cm & 0.6cm & Iris-setosa\\
Iris-setosa & 5.1cm & 3.8cm & 1.9cm & 0.4cm & Iris-setosa\\
Iris-setosa & 4.8cm & 3.0cm & 1.4cm & 0.3cm & Iris-setosa\\
Iris-setosa & 5.1cm & 3.8cm & 1.6cm & 0.2cm & Iris-setosa\\
Iris-setosa & 4.6cm & 3.2cm & 1.4cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.3cm & 3.7cm & 1.5cm & 0.2cm & Iris-setosa\\
Iris-setosa & 5.0cm & 3.3cm & 1.4cm & 0.2cm & Iris-setosa\\
Iris-versicolor & 6.6cm & 3.0cm & 4.4cm & 1.4cm & Iris-versicolor\\
Iris-versicolor & 6.8cm & 2.8cm & 4.8cm & 1.4cm & Iris-versicolor\\
Iris-versicolor & 6.7cm & 3.0cm & 5.0cm & 1.7cm & \textbf{Iris-virginica}\\
Iris-versicolor & 6.0cm & 2.9cm & 4.5cm & 1.5cm & Iris-versicolor\\
Iris-versicolor & 5.7cm & 2.6cm & 3.5cm & 1.0cm & Iris-versicolor\\
Iris-versicolor & 5.5cm & 2.4cm & 3.8cm & 1.1cm & Iris-versicolor\\
Iris-versicolor & 5.5cm & 2.4cm & 3.7cm & 1.0cm & Iris-versicolor\\
Iris-versicolor & 5.8cm & 2.7cm & 3.9cm & 1.2cm & Iris-versicolor\\
Iris-versicolor & 6.0cm & 2.7cm & 5.1cm & 1.6cm & \textbf{Iris-virginica}\\
Iris-versicolor & 5.4cm & 3.0cm & 4.5cm & 1.5cm & Iris-versicolor\\
Iris-versicolor & 6.0cm & 3.4cm & 4.5cm & 1.6cm & Iris-versicolor\\
Iris-versicolor & 6.7cm & 3.1cm & 4.7cm & 1.5cm & Iris-versicolor\\
Iris-versicolor & 6.3cm & 2.3cm & 4.4cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 5.6cm & 3.0cm & 4.1cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 5.5cm & 2.5cm & 4.0cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 5.5cm & 2.6cm & 4.4cm & 1.2cm & Iris-versicolor\\
Iris-versicolor & 6.1cm & 3.0cm & 4.6cm & 1.4cm & Iris-versicolor\\
Iris-versicolor & 5.8cm & 2.6cm & 4.0cm & 1.2cm & Iris-versicolor\\
Iris-versicolor & 5.0cm & 2.3cm & 3.3cm & 1.0cm & Iris-versicolor\\
Iris-versicolor & 5.6cm & 2.7cm & 4.2cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 5.7cm & 3.0cm & 4.2cm & 1.2cm & Iris-versicolor\\
Iris-versicolor & 5.7cm & 2.9cm & 4.2cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 6.2cm & 2.9cm & 4.3cm & 1.3cm & Iris-versicolor\\
Iris-versicolor & 5.1cm & 2.5cm & 3.0cm & 1.1cm & Iris-versicolor\\
Iris-versicolor & 5.7cm & 2.8cm & 4.1cm & 1.3cm & Iris-versicolor\\
Iris-virginica & 7.2cm & 3.2cm & 6.0cm & 1.8cm & Iris-virginica\\
Iris-virginica & 6.2cm & 2.8cm & 4.8cm & 1.8cm & Iris-virginica\\
Iris-virginica & 6.1cm & 3.0cm & 4.9cm & 1.8cm & \textbf{Iris-versicolor}\\
Iris-virginica & 6.4cm & 2.8cm & 5.6cm & 2.1cm & Iris-virginica\\
Iris-virginica & 7.2cm & 3.0cm & 5.8cm & 1.6cm & Iris-virginica\\
Iris-virginica & 7.4cm & 2.8cm & 6.1cm & 1.9cm & Iris-virginica\\
Iris-virginica & 7.9cm & 3.8cm & 6.4cm & 2.0cm & Iris-virginica\\
Iris-virginica & 6.4cm & 2.8cm & 5.6cm & 2.2cm & Iris-virginica\\
Iris-virginica & 6.3cm & 2.8cm & 5.1cm & 1.5cm & \textbf{Iris-versicolor}\\
Iris-virginica & 6.1cm & 2.6cm & 5.6cm & 1.4cm & \textbf{Iris-versicolor}\\
Iris-virginica & 7.7cm & 3.0cm & 6.1cm & 2.3cm & Iris-virginica\\
Iris-virginica & 6.3cm & 3.4cm & 5.6cm & 2.4cm & Iris-virginica\\
Iris-virginica & 6.4cm & 3.1cm & 5.5cm & 1.8cm & Iris-virginica\\
Iris-virginica & 6.0cm & 3.0cm & 4.8cm & 1.8cm & \textbf{Iris-versicolor}\\
Iris-virginica & 6.9cm & 3.1cm & 5.4cm & 2.1cm & Iris-virginica\\
Iris-virginica & 6.7cm & 3.1cm & 5.6cm & 2.4cm & Iris-virginica\\
Iris-virginica & 6.9cm & 3.1cm & 5.1cm & 2.3cm & Iris-virginica\\
Iris-virginica & 5.8cm & 2.7cm & 5.1cm & 1.9cm & Iris-virginica\\
Iris-virginica & 6.8cm & 3.2cm & 5.9cm & 2.3cm & Iris-virginica\\
Iris-virginica & 6.7cm & 3.3cm & 5.7cm & 2.5cm & Iris-virginica\\
Iris-virginica & 6.7cm & 3.0cm & 5.2cm & 2.3cm & Iris-virginica\\
Iris-virginica & 6.3cm & 2.5cm & 5.0cm & 1.9cm & Iris-virginica\\
Iris-virginica & 6.5cm & 3.0cm & 5.2cm & 2.0cm & Iris-virginica\\
Iris-virginica & 6.2cm & 3.4cm & 5.4cm & 2.3cm & Iris-virginica\\
Iris-virginica & 5.9cm & 3.0cm & 5.1cm & 1.8cm & \textbf{Iris-versicolor}\\

		\end{longtable}
		\end{center}
\end{document}


\documentclass[10pt,letterpaper]{article}
\usepackage[dvipsnames]{xcolor}
\usepackage{outlines}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{hyperref}
\usepackage{enumitem}
\usepackage{cancel}
\usepackage{subcaption}
\DeclareCaptionOptionNoValue{centering}{\centering} % Make sure everything is centered in subs
\captionsetup[sub]{centering}

\usepackage{multirow}
\usepackage{cancel}
\usepackage{float}

\usepackage{parskip}

\usepackage{slantsc,lmodern}

\usepackage{pgfplotstable,booktabs}
\usepackage{framed}
\definecolor{shadecolor}{rgb}{0.9,0.9,0.9}

\usepackage{gensymb}

\usepackage{paralist}

\usepackage[paper=a4paper,margin=1in]{geometry}

\usepackage{etoolbox}

\newcommand{\volume}{{\ooalign{\hfil$V$\hfil\cr\kern0.08em--\hfil\cr}}}

\makeatletter
\g@addto@macro\@floatboxreset\centering
\makeatother

\author{Thaddeus Hughes \\ hughes.thad@gmail.com \\ thaddeus-maximus.github.io}
\date{\today}
\title{Simple Model of a Rocker Pod}

\begin{document}
	\maketitle

	\begin{abstract}
		\begin{figure}[H]
			\includegraphics[width=0.7\textwidth]{drivetrain_slide_rocker.png}
			\caption{Rocker pod with omnis for use in a slide drive.}
		\end{figure}
		Rocker pods are very interesting mechanisms as they allow for a dynamic suspension system without the need for extra actuators, creating an amount of normal or contact force that is proportional to the driving torque. This is due to their tendency for the wheels to dig into the surface they contact, creating additional force beyond the input torque. This makes them excellent in slide drive applications, but they need to be properly designed in order to function properly. While \href{https://johnvneun.com/blog/2019/1/3/x019-prototype}{\color{red}\underline{the Robowranglers (FRC Team 148) pioneered their use in slide (H) drives}}, rocker pods also have applications beyond drivetrains such as \href{https://www.youtube.com/watch?v=q8VA5kmzAPk}{\color{red}\underline{in intake systems}}.
	\end{abstract}

	\section*{System Definition}

	Consider half of a rocker pod (the other half is simply the same principle, but in the reverse direction).

\begin{figure}[H]
\begin{tikzpicture}
\draw[BrickRed,  ultra thick] (-2,-1) circle (1.5);
\draw[PineGreen, ultra thick] (0,0) circle(1);
\draw[PineGreen, ultra thick] (-2,-1) circle(1.2);
\draw[Sepia,     ultra thick] (-5,-2.5)--(3,-2.5);

\fill[black] ( 0, 0) circle (0.1);
\fill[black] (-2,-1) circle (0.1);

\draw[dashed] (-2,-1) -- (-3,1);
\draw[dashed] ( 0, 0) -- (-1,2);
\draw[<->, ultra thick] (-2.8, 0.6) -- (-0.8,1.6) node[pos=0.5,above]{$r_{p}$};
\draw[dashed] ( 0, 0) -- (1.5,0);
\draw[<->, ultra thick] (1.3,0)--(1.3,-2.5) node[pos=0.5, right]{$h$};

\draw[->, ultra thick] (-2,-1) -- (-3.35,-0.3) node[pos=1, left]{$r_{w}$};

\draw[dashed] (-2,-1) -- (-2,-3.5);
\draw[dashed] (0,0)   -- (0, -3.5);
\draw[<->, ultra thick] (-2, -3.3) -- (0, -3.3) node[pos=0.5, below]{$w$};

\end{tikzpicture}
\caption{Dimensions critical to rocker pod functionality. Gears in green, wheel in red.}
\end{figure}

By pythagorean theorem,

\begin{align}
	w = \sqrt{r_{p}^2 - (h - r_{w})^2}
\end{align}

\begin{figure}[H]
\begin{tikzpicture}
\draw[BrickRed,  ultra thick] (-2,-1) circle (1.5);
\draw[PineGreen, ultra thick] (0,0) circle(1);
\draw[PineGreen, ultra thick] (-2,-1) circle(1.2);

\fill[black] ( 0, 0) circle (0.1);
\fill[black] (-2,-1) circle (0.1);

\draw[->, ultra thick] (-2,-3.6)--(-2,-2.6) node [pos=0.5,right]{$N$};
\draw[->, ultra thick] (-3.5,-2.5)--(-2.5,-2.5) node [pos=0.5,below]{$F$};

\draw[->, ultra thick] (0.6,0) arc (0:240:0.6) node [pos=1,right]{$T_{in}$};

\end{tikzpicture}
\qquad
\qquad
\qquad
\begin{tikzpicture}
\draw[BrickRed,  ultra thick] (-2,-1) circle (1.5);
\draw[PineGreen, ultra thick] (-2,-1) circle(1.2);

\fill[black] (-2,-1) circle (0.1);

\draw[->, ultra thick] (-2,-3.6)--(-2,-2.6) node [pos=0.5,right]{$N$};
\draw[->, ultra thick] (-3.5,-2.5)--(-2.5,-2.5) node [pos=0.5,below]{$F$};

\draw[<-, ultra thick] (-1.4,-1) arc (0:240:0.6) node [pos=1,right]{$T_{wheel}$};

\end{tikzpicture}
\caption{Left: free-body diagram of a half rocker pod. Right: free-body diagram of its wheel.}
\end{figure}

\section*{Physics Principles}

Applying conservation of angular momentum to the rocker pod yields

\begin{align}
	\cancelto{\mbox{0 (lightweight system)}}{\frac{d}{dt} L_{sys}} = \sum_{about\ pivot} \vec{r} \times \vec{F} + \cancelto{\mbox{0 (no mass transfer)}}{\sum_{+in} \dot{m} [...]} \nonumber \\
	h F - w N + T_{in} = 0 .
\end{align}

Applying conservation of angular momentum to the wheel yields

\begin{align}
	\cancelto{\mbox{0 (lightweight system)}}{\frac{d}{dt} L_{sys}} = \sum_{about\ axle} \vec{r} \times \vec{F} + \cancelto{\mbox{0 (no mass transfer)}}{\sum_{+in} \dot{m} [...]} \nonumber \\
	r_{w} F - T_{wheel} = 0 .
\end{align}

The wheel torque is related to the input torque by module gear ratio $G$.

\begin{align}
	T_{wheel} = G \ T_{in}
\end{align}

A negative $G$ could be input to simulate a module that did not reverse the input and output directions.

The wheel's force should be friction-limited. We'll use a simple static friction model with $\mu$ as the coefficient of friction.

\begin{align}
	F \leq \mu N
\end{align}

\section*{Solution}

The various constraints can be solved, yielding

\begin{align}
	F &= \frac{G}{r_{w}} T_{in} \\
	N &= \frac{1 + G \frac{h}{r_{w}}}{\sqrt{r_{p}^2 - (h - r_{w})^2}} T_{in}
\end{align}

The ratio of propulsive force to normal force can also be solved for, which would be the effective frictional coefficient of the module.

\begin{align}
	F/N = \mu_{effective} = \frac{\frac{G}{r_{wheel}}}{ 1 + G \frac{h}{r_{wheel}} } \sqrt{r_{p}^2 - (h - r_{w})^2}
\end{align}

This ratio should be kept beneath the coefficient of friction, otherwise the module would slip. It also should not be kept too low, otherwise the normal force will be large even at small amounts of propulsion.

My \href{https://thaddeus-maximus.github.io/swissarmyengineer/rockerpod}{\color{red}\underline{EveryCalc Tool}} contains a rocker pod analyzer that can be used to perform these calculations.

\end{document}


\documentclass[12pt,a4paper]{book}
\usepackage[margin=2cm]{geometry}
\usepackage{amsmath,amsthm,amsfonts}
\usepackage{algorithm,algpseudocode}
\usepackage{answers}
\usepackage{kbordermatrix}
\usepackage{tikz}
\usepackage{epstopdf}
\usepackage[euler-digits]{eulervm}
\usepackage{hyperref}
\usepackage[capitalize]{cleveref}

\title{Numerical Methods for \\
Partial Differential Equations}
\author{William McLean}
\date{\today}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newtheorem{theorem}{Theorem}[chapter]
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{corollary}[theorem]{Corollary}
\newtheorem{example}[theorem]{Example}
\newtheorem{definition}[theorem]{Definition}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcounter{exno}[chapter]
\renewcommand{\theexno}{\thechapter.\arabic{exno}}
\newcommand{\exercise}{\refstepcounter{exno}\paragraph{\theexno.}}
\Newassociation{ans}{answer}{ansfile}
\newenvironment{Exercises}{\section{Exercises}\leavevmode
\Writetofile{ansfile}{\protect\section*{Chapter \thechapter}}}{\relax}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\brak}[1]{^{\langle#1\rangle}}
\newcommand{\swap}{\leftrightarrow}
\newcommand{\free}{^{\mathrm{free}}}
\newcommand{\fix}{^{\mathrm{fix}}}
\newcommand{\iprod}[1]{\langle#1\rangle}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\include{which_chapters}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\maketitle
\tableofcontents
\Opensolutionfile{ansfile}
\include{chap1}
\include{chap2}
\include{chap3}
\include{chap4}
\include{chap5}
\include{chap6}
\appendix
\include{appendixA}
\Closesolutionfile{ansfile}
\chapter{Answers to selected exercises}
\Readsolutionfile{ansfile}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}


\section{Unit testing} % (fold)
\begin{questions}
\label{sec:unit_testing}

    \titledquestion{Factorial} % (fold)
    \label{sub:factorial}
        Write unit tests for the factorial function.

    % titledquestion factorial (end)

    \titledquestion{Prime numbers} % (fold)
    \label{sub:prime_numbers}

        Write a program \texttt{primes.py} that takes two command line arguments,
        $a < b$, and returns all prime numbers between $a$ and $b$ (inclusive).
        Write a seperate test script \texttt{primestest.py} that contains
        unittests for all functions in your script.

    % titledquestion prime_numbers (end)

    \titledquestion{Sorting} % (fold)
    \label{sub:quicksort}
        Write unit tests for a sorting algorithm.
        Test whether your implementation of \texttt{quicksort} passes the tests.

    % titledquestion quicksort (end)
\end{questions}
% section unit_testing (end)