#+TITLE: Wilcoxon test via GPC
#+Author: Brice Ozenne

#+BEGIN_SRC R :exports none :results output raw drawer :session *R* :cache no
library(BuyseTest)
library(asht, quiet = TRUE)
library(pbapply)
library(riskRegression)
#+END_SRC

#+RESULTS:
:results:
:end:

* Single Wilcoxon test

Generalized Pairwise comparisons include the Wilcoxon rank sum test as
a specific case. \newline Consider the following dataset (from the example
section of =stats::wilcox.test=):
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
x <- c(1.83,  0.50,  1.62,  2.48, 1.68, 1.88, 1.55, 3.06, 1.30)
y <- c(0.878, 0.647, 0.598, 2.05, 1.06, 1.29, 1.06, 3.14, 1.29)
df <- rbind(data.frame(value = x, group="x"),
            data.frame(value = y, group="y"))
#+END_SRC

#+RESULTS:

We can perform a Wilcoxon test using the =wilcox.test= function:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
wilcox.test(value ~ group, data = df)
#+END_SRC

#+RESULTS:
#+begin_example

	Wilcoxon rank sum test with continuity correction

data:  value by group
W = 58, p-value = 0.1329
alternative hypothesis: true location shift is not equal to 0

Warning message:
In wilcox.test.default(x = DATA[[1L]], y = DATA[[2L]], ...) :
  cannot compute exact p-value with ties
#+end_example

It unfortunately does not ouput any effect size (just the test
statistic and corresponding p-value). The package /asht/ contains an
alternative implementation:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
library(asht)
wmwTest(value ~ group, data = df, method = "asymptotic")
#+END_SRC

#+RESULTS:
#+begin_example

	Wilcoxon-Mann-Whitney test with continuity correction (confidence interval
	requires proportional odds assumption, but test does not)

data:  value by group
Mann-Whitney estimate = 0.28395, tie factor = 0.99794, p-value = 0.1329
alternative hypothesis: two distributions are not equal
95 percent confidence interval:
 0.1142978 0.5614097
sample estimates:
Mann-Whitney estimate 
            0.2839506
#+end_example

which does output an estimate[fn::Mann-Whitney parameter,
i.e. probability that a randomly chosen observation from one group has
higher value than a randomly chosen observation from the other
group]. It matches exactly the p.value and is based on an asymptotic
result. It is also possible to get an exact p-value [fn::this is only
feasible in small samples - otherwise the procedure becomes
computationnally challenging]:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
wmwTest(value ~ group, data = df, method = "exact.ce")
#+END_SRC

#+RESULTS:
#+begin_example

	exact Wilcoxon-Man-Whitney test (confidence interval requires proportional odds
	assumption, but test does not)

data:  value by group
Mann-Whitney estimate = 0.28395, p-value = 0.1299
alternative hypothesis: two distributions are not equal
95 percent confidence interval:
 0.09721823 0.56323417
sample estimates:
Mann-Whitney estimate 
            0.2839506
#+end_example

To match those results with GPC we can use a permutation test
(\Warning remember to add the argument =add.halfNeutral= to =TRUE= to
handle ties the same way as the previous tests):
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
eperm.BT <- BuyseTest(group ~ cont(value), data = df, add.halfNeutral = TRUE,
                      method.inference = "permutation", n.resampling = 10000,
                      trace = FALSE, seed = 10)
confint(eperm.BT, statistic = "favorable")
#+END_SRC

#+RESULTS:
:        estimate       se  lower.ci  upper.ci null   p.value
: value 0.2839506 0.140185 0.1050267 0.5725376  0.5 0.1242876
: Warning message:
: In .local(object, ...) :
:   Confidence intervals are computed under the null hypothesis and therefore may not be valid.

The estimate is precisely the same and the p-value approximately the
same. Instead of permutation, we could use the asymptotic theory to
obtain p-values and (valid) confidence intervals:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
BuyseTest.options(order.Hprojection=2)
eU.BT <- BuyseTest(group ~ cont(value), data = df,
                  method.inference = "u-statistic",
                  add.halfNeutral = TRUE, trace = FALSE)
confint(eU.BT, statistic = "favorable")
#+END_SRC

#+RESULTS:
:        estimate        se   lower.ci  upper.ci null   p.value
: value 0.2839506 0.1401461 0.09313769 0.6049215  0.5 0.1796262

Unsuprisingly, we get the same estimate. However the p-value seems
quite a bit different. This might be explained by the fact that this
approach does not assume iid[fn::iid=independent and identically
distributed] observations but only iid observations within each
group. A studentised permutation, which is exactly (instead of
asymptotically) valid under the same assumption, gives a somewhat
similar p-value:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
etperm.BT <- BuyseTest(group ~ cont(value), data = df, add.halfNeutral = TRUE,
                      method.inference = "studentized permutation", n.resampling = 10000,
                      trace = FALSE, seed = 10)
confint(etperm.BT, statistic = "favorable")
#+END_SRC

#+RESULTS:
:        estimate        se  lower.ci  upper.ci null p.value
: value 0.2839506 0.1401461 0.1006681 0.5809142  0.5   0.163
: Warning message:
: In .local(object, ...) :
:   Confidence intervals are computed under the null hypothesis and therefore may not be valid.

* Multiple Wilcoxon tests

Consider now the case where we would like to compare one reference
group (here strata =a=) to multiple treatment groups (here strata
=b,c,d,e=). We will consider the following dataset:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
set.seed(35)
dt <- simBuyseTest(n.T=25, n.strata = 5)
dt$id <- paste0("id",1:NROW(dt))
dt$strata <- as.character(dt$strata) 
head(dt)
#+END_SRC

#+RESULTS:
:    treatment  eventtime status toxicity      score strata  id
: 1:         C 0.03384999      1      yes  0.4777913      b id1
: 2:         C 0.65039474      0       no -1.1048190      d id2
: 3:         C 1.00647502      1       no -0.1407630      b id3
: 4:         C 0.01129603      1      yes -0.5512507      a id4
: 5:         C 0.22249748      1       no  1.0465250      d id5
: 6:         C 0.07400412      0       no -2.0053855      d id6

\clearpage

We can apply the GPC procedure to each pair of group:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
BuyseTest.options(order.Hprojection=1);BuyseTest.options(trace=0)

ls.BT <- list("b-a=0" = BuyseTest(strata ~ cont(score), add.halfNeutral = TRUE,
                                  data = dt[dt$strata %in% c("a","b"),],
                                  method.inference = "u-statistic"),
              "c-a=0" = BuyseTest(strata ~ cont(score), add.halfNeutral = TRUE,
                                  data = dt[dt$strata %in% c("a","c"),],
                                  method.inference = "u-statistic"),
              "d-a=0" = BuyseTest(strata ~ cont(score), add.halfNeutral = TRUE,
                                  data = dt[dt$strata %in% c("a","d"),],
                                  method.inference = "u-statistic"),
              "e-a=0" = BuyseTest(strata ~ cont(score), add.halfNeutral = TRUE,
                                  data = dt[dt$strata %in% c("a","e"),],
                                  method.inference = "u-statistic")
              )

M.confint <- do.call(rbind,lapply(ls.BT,confint, statistic = "favorable"))
cbind(M.confint,adj.p.value = p.adjust(M.confint[,"p.value"], method = "bonferroni"))
#+END_SRC

#+RESULTS:
:        estimate        se  lower.ci  upper.ci null    p.value adj.p.value
: b-a=0 0.4090909 0.1542200 0.1654639 0.7073759  0.5 0.56434599   1.0000000
: c-a=0 0.4375000 0.1465755 0.1948678 0.7142379  0.5 0.67306460   1.0000000
: d-a=0 0.2500000 0.1010153 0.1039078 0.4893302  0.5 0.04143057   0.1657223
: e-a=0 0.3333333 0.1360828 0.1308601 0.6241219  0.5 0.25767454   1.0000000


Because we compare the treatment groups to the same reference, the
test statistics are correlated and a Bonferroni adjustment would not
be optimal. A better (but still not optimal adjustment) is the
max-test adjustment which can be obtained via the =BuyseMultComp= function:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
e.mc <- BuyseMultComp(ls.BT, statistic = "favorable", cluster = "id", global = TRUE)
print(e.mc, cols = c("estimate","se","p.value","adj.p.value"))
#+END_SRC

#+RESULTS:
:   - Multivariate test: p.value = 0.2645493 (df = 4)
:   - Univariate tests:
:        estimate        se    p.value adj.p.value
: b-a=0 0.4090909 0.1542200 0.56434599   0.9289219
: c-a=0 0.4375000 0.1465755 0.67306460   0.9752151
: d-a=0 0.2500000 0.1010153 0.04143057   0.1223430
: e-a=0 0.3333333 0.1360828 0.25767454   0.5831344


Here the smallest p-value has been multiplied by a factor 2.64 instead
of 4. This is thanks to the rather strong correlation between the test
statistics:
#+BEGIN_SRC R :exports both :results output :session *R* :cache no
M.cor <- cov2cor(crossprod(e.mc$iid))
dimnames(M.cor) <- list(names(ls.BT),names(ls.BT))
M.cor
#+END_SRC

#+RESULTS:
:           b-a=0     c-a=0     d-a=0     e-a=0
: b-a=0 1.0000000 0.6519486 0.5601058 0.7520401
: c-a=0 0.6519486 1.0000000 0.4240003 0.5439927
: d-a=0 0.5601058 0.4240003 1.0000000 0.5051815
: e-a=0 0.7520401 0.5439927 0.5051815 1.0000000


* CONFIG :noexport:
# #+LaTeX_HEADER:\affil{Department of Biostatistics, University of Copenhagen, Copenhagen, Denmark}
#+LANGUAGE:  en
#+LaTeX_CLASS: org-article
#+LaTeX_CLASS_OPTIONS: [12pt]
#+OPTIONS:   title:t author:t toc:nil todo:nil
#+OPTIONS:   H:3 num:t 
#+OPTIONS:   TeX:t LaTeX:t
** Display of the document
# ## space between lines
#+LATEX_HEADER: \RequirePackage{setspace} % to modify the space between lines - incompatible with footnote in beamer
#+LaTeX_HEADER:\renewcommand{\baselinestretch}{1.1}
# ## margins
#+LaTeX_HEADER: \geometry{a4paper, left=10mm, right=10mm, top=10mm}
# ## personalize the prefix in the name of the sections
#+LaTeX_HEADER: \usepackage{titlesec}
# ## fix bug in titlesec version
# ##  https://tex.stackexchange.com/questions/299969/titlesec-loss-of-section-numbering-with-the-new-update-2016-03-15
#+LaTeX_HEADER: \usepackage{etoolbox}
#+LaTeX_HEADER: 
#+LaTeX_HEADER: \makeatletter
#+LaTeX_HEADER: \patchcmd{\ttlh@hang}{\parindent\z@}{\parindent\z@\leavevmode}{}{}
#+LaTeX_HEADER: \patchcmd{\ttlh@hang}{\noindent}{}{}{}
#+LaTeX_HEADER: \makeatother
** Color
# ## define new colors
#+LATEX_HEADER: \RequirePackage{colortbl} % arrayrulecolor to mix colors
#+LaTeX_HEADER: \definecolor{myorange}{rgb}{1,0.2,0}
#+LaTeX_HEADER: \definecolor{mypurple}{rgb}{0.7,0,8}
#+LaTeX_HEADER: \definecolor{mycyan}{rgb}{0,0.6,0.6}
#+LaTeX_HEADER: \newcommand{\lightblue}{blue!50!white}
#+LaTeX_HEADER: \newcommand{\darkblue}{blue!80!black}
#+LaTeX_HEADER: \newcommand{\darkgreen}{green!50!black}
#+LaTeX_HEADER: \newcommand{\darkred}{red!50!black}
#+LaTeX_HEADER: \definecolor{gray}{gray}{0.5}
# ## change the color of the links
#+LaTeX_HEADER: \hypersetup{
#+LaTeX_HEADER:  citecolor=[rgb]{0,0.5,0},
#+LaTeX_HEADER:  urlcolor=[rgb]{0,0,0.5},
#+LaTeX_HEADER:  linkcolor=[rgb]{0,0,0.5},
#+LaTeX_HEADER: }
** Font
# https://tex.stackexchange.com/questions/25249/how-do-i-use-a-particular-font-for-a-small-section-of-text-in-my-document
#+LaTeX_HEADER: \newenvironment{note}{\small \color{gray}\fontfamily{lmtt}\selectfont}{\par}
#+LaTeX_HEADER: \newenvironment{activity}{\color{orange}\fontfamily{qzc}\selectfont}{\par}
** Symbols
# ## valid and cross symbols
#+LaTeX_HEADER: \RequirePackage{pifont}
#+LaTeX_HEADER: \RequirePackage{relsize}
#+LaTeX_HEADER: \newcommand{\Cross}{{\raisebox{-0.5ex}%
#+LaTeX_HEADER:		{\relsize{1.5}\ding{56}}}\hspace{1pt} }
#+LaTeX_HEADER: \newcommand{\Valid}{{\raisebox{-0.5ex}%
#+LaTeX_HEADER:		{\relsize{1.5}\ding{52}}}\hspace{1pt} }
#+LaTeX_HEADER: \newcommand{\CrossR}{ \textcolor{red}{\Cross} }
#+LaTeX_HEADER: \newcommand{\ValidV}{ \textcolor{green}{\Valid} }
# ## warning symbol
#+LaTeX_HEADER: \usepackage{stackengine}
#+LaTeX_HEADER: \usepackage{scalerel}
#+LaTeX_HEADER: \newcommand\Warning[1][3ex]{%
#+LaTeX_HEADER:   \renewcommand\stacktype{L}%
#+LaTeX_HEADER:   \scaleto{\stackon[1.3pt]{\color{red}$\triangle$}{\tiny\bfseries !}}{#1}%
#+LaTeX_HEADER:   \xspace
#+LaTeX_HEADER: }
# # R Software
#+LATEX_HEADER: \newcommand\Rlogo{\textbf{\textsf{R}}\xspace} % 
** Code
:PROPERTIES:
:ID:       2ec77c4b-f83d-4612-9a89-a96ba1b7bf70
:END:
# Documentation at https://org-babel.readthedocs.io/en/latest/header-args/#results
# :tangle (yes/no/filename) extract source code with org-babel-tangle-file, see http://orgmode.org/manual/Extracting-source-code.html 
# :cache (yes/no)
# :eval (yes/no/never)
# :results (value/output/silent/graphics/raw/latex)
# :export (code/results/none/both)
#+PROPERTY: header-args :session *R* :tangle yes :cache no ## extra argument need to be on the same line as :session *R*
# Code display:
#+LATEX_HEADER: \RequirePackage{fancyvrb}
#+LATEX_HEADER: \DefineVerbatimEnvironment{verbatim}{Verbatim}{fontsize=\small,formatcom = {\color[rgb]{0.5,0,0}}}
# ## change font size input (global change)
# ## doc: https://ctan.math.illinois.edu/macros/latex/contrib/listings/listings.pdf
# #+LATEX_HEADER: \newskip kipamount    kipamount =6pt plus 0pt minus 6pt
# #+LATEX_HEADER: \lstdefinestyle{code-tiny}{basicstyle=\ttfamily\tiny, aboveskip =  kipamount, belowskip =  kipamount}
# #+LATEX_HEADER: \lstset{style=code-tiny}
# ## change font size input (local change, put just before BEGIN_SRC)
# ## #+ATTR_LATEX: :options basicstyle=\ttfamily\scriptsize
# ## change font size output (global change)
# ## \RecustomVerbatimEnvironment{verbatim}{Verbatim}{fontsize=\tiny,formatcom = {\color[rgb]{0.5,0,0}}}
** Lists
#+LATEX_HEADER: \RequirePackage{enumitem} % better than enumerate
** Image and graphs
#+LATEX_HEADER: \RequirePackage{epstopdf} % to be able to convert .eps to .pdf image files
#+LATEX_HEADER: \RequirePackage{capt-of} % 
#+LATEX_HEADER: \RequirePackage{caption} % newlines in graphics
#+LaTeX_HEADER: \RequirePackage{tikz-cd} % graph
# ## https://tools.ietf.org/doc/texlive-doc/latex/tikz-cd/tikz-cd-doc.pdf
** Table
#+LATEX_HEADER: \RequirePackage{booktabs} % for nice lines in table (e.g. toprule, bottomrule, midrule, cmidrule)
** Inline latex
# @@latex:any arbitrary LaTeX code@@
** Algorithm
#+LATEX_HEADER: \RequirePackage{amsmath}
#+LATEX_HEADER: \RequirePackage{algorithm}
#+LATEX_HEADER: \RequirePackage[noend]{algpseudocode}
** Math
#+LATEX_HEADER: \RequirePackage{dsfont}
#+LATEX_HEADER: \RequirePackage{amsmath,stmaryrd,graphicx}
#+LATEX_HEADER: \RequirePackage{prodint} % product integral symbol (\PRODI)
# ## lemma
# #+LaTeX_HEADER: \RequirePackage{amsthm}
# #+LaTeX_HEADER: \newtheorem{theorem}{Theorem}
# #+LaTeX_HEADER: \newtheorem{lemma}[theorem]{Lemma}
*** Template for shortcut
#+LATEX_HEADER: \usepackage{ifthen}
#+LATEX_HEADER: \usepackage{xifthen}
#+LATEX_HEADER: \usepackage{xargs}
#+LATEX_HEADER: \usepackage{xspace}
#+LATEX_HEADER: \newcommand\defOperator[7]{%
#+LATEX_HEADER:	\ifthenelse{\isempty{#2}}{
#+LATEX_HEADER:		\ifthenelse{\isempty{#1}}{#7{#3}#4}{#7{#3}#4 \left#5 #1 \right#6}
#+LATEX_HEADER:	}{
#+LATEX_HEADER:	\ifthenelse{\isempty{#1}}{#7{#3}#4_{#2}}{#7{#3}#4_{#1}\left#5 #2 \right#6}
#+LATEX_HEADER: }
#+LATEX_HEADER: }
#+LATEX_HEADER: \newcommand\defUOperator[5]{%
#+LATEX_HEADER: \ifthenelse{\isempty{#1}}{
#+LATEX_HEADER:		#5\left#3 #2 \right#4
#+LATEX_HEADER: }{
#+LATEX_HEADER:	\ifthenelse{\isempty{#2}}{\underset{#1}{\operatornamewithlimits{#5}}}{
#+LATEX_HEADER:		\underset{#1}{\operatornamewithlimits{#5}}\left#3 #2 \right#4}
#+LATEX_HEADER: }
#+LATEX_HEADER: }
#+LATEX_HEADER: \newcommand{\defBoldVar}[2]{	
#+LATEX_HEADER:	\ifthenelse{\equal{#2}{T}}{\boldsymbol{#1}}{\mathbf{#1}}
#+LATEX_HEADER: }
**** Probability
#+LATEX_HEADER: \newcommandx\Esp[2][1=,2=]{\defOperator{#1}{#2}{E}{}{\lbrack}{\rbrack}{\mathbb}}
#+LATEX_HEADER: \newcommandx\Prob[2][1=,2=]{\defOperator{#1}{#2}{P}{}{\lbrack}{\rbrack}{\mathbb}}
#+LATEX_HEADER: \newcommandx\Qrob[2][1=,2=]{\defOperator{#1}{#2}{Q}{}{\lbrack}{\rbrack}{\mathbb}}
#+LATEX_HEADER: \newcommandx\Var[2][1=,2=]{\defOperator{#1}{#2}{V}{ar}{\lbrack}{\rbrack}{\mathbb}}
#+LATEX_HEADER: \newcommandx\Cov[2][1=,2=]{\defOperator{#1}{#2}{C}{ov}{\lbrack}{\rbrack}{\mathbb}}
#+LATEX_HEADER: \newcommandx\Binom[2][1=,2=]{\defOperator{#1}{#2}{B}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\Gaus[2][1=,2=]{\defOperator{#1}{#2}{N}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\Wishart[2][1=,2=]{\defOperator{#1}{#2}{W}{ishart}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\Likelihood[2][1=,2=]{\defOperator{#1}{#2}{L}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\logLikelihood[2][1=,2=]{\defOperator{#1}{#2}{\ell}{}{(}{)}{}}
#+LATEX_HEADER: \newcommandx\Information[2][1=,2=]{\defOperator{#1}{#2}{I}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\Score[2][1=,2=]{\defOperator{#1}{#2}{S}{}{(}{)}{\mathcal}}
**** Operators
#+LATEX_HEADER: \newcommandx\Vois[2][1=,2=]{\defOperator{#1}{#2}{V}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\IF[2][1=,2=]{\defOperator{#1}{#2}{IF}{}{(}{)}{\mathcal}}
#+LATEX_HEADER: \newcommandx\Ind[1][1=]{\defOperator{}{#1}{1}{}{(}{)}{\mathds}}
#+LATEX_HEADER: \newcommandx\Max[2][1=,2=]{\defUOperator{#1}{#2}{(}{)}{min}}
#+LATEX_HEADER: \newcommandx\Min[2][1=,2=]{\defUOperator{#1}{#2}{(}{)}{max}}
#+LATEX_HEADER: \newcommandx\argMax[2][1=,2=]{\defUOperator{#1}{#2}{(}{)}{argmax}}
#+LATEX_HEADER: \newcommandx\argMin[2][1=,2=]{\defUOperator{#1}{#2}{(}{)}{argmin}}
#+LATEX_HEADER: \newcommandx\cvD[2][1=D,2=n \rightarrow \infty]{\xrightarrow[#2]{#1}}
#+LATEX_HEADER: \newcommandx\Hypothesis[2][1=,2=]{
#+LATEX_HEADER:         \ifthenelse{\isempty{#1}}{
#+LATEX_HEADER:         \mathcal{H}
#+LATEX_HEADER:         }{
#+LATEX_HEADER: 	\ifthenelse{\isempty{#2}}{
#+LATEX_HEADER: 		\mathcal{H}_{#1}
#+LATEX_HEADER: 	}{
#+LATEX_HEADER: 	\mathcal{H}^{(#2)}_{#1}
#+LATEX_HEADER:         }
#+LATEX_HEADER:         }
#+LATEX_HEADER: }
#+LATEX_HEADER: \newcommandx\dpartial[4][1=,2=,3=,4=\partial]{
#+LATEX_HEADER: 	\ifthenelse{\isempty{#3}}{
#+LATEX_HEADER: 		\frac{#4 #1}{#4 #2}
#+LATEX_HEADER: 	}{
#+LATEX_HEADER: 	\left.\frac{#4 #1}{#4 #2}\right\rvert_{#3}
#+LATEX_HEADER: }
#+LATEX_HEADER: }
#+LATEX_HEADER: \newcommandx\dTpartial[3][1=,2=,3=]{\dpartial[#1][#2][#3][d]}
#+LATEX_HEADER: \newcommandx\ddpartial[3][1=,2=,3=]{
#+LATEX_HEADER: 	\ifthenelse{\isempty{#3}}{
#+LATEX_HEADER: 		\frac{\partial^{2} #1}{\partial #2^2}
#+LATEX_HEADER: 	}{
#+LATEX_HEADER: 	\frac{\partial^2 #1}{\partial #2\partial #3}
#+LATEX_HEADER: }
#+LATEX_HEADER: } 
**** General math
#+LATEX_HEADER: \newcommand\Real{\mathbb{R}}
#+LATEX_HEADER: \newcommand\Rational{\mathbb{Q}}
#+LATEX_HEADER: \newcommand\Natural{\mathbb{N}}
#+LATEX_HEADER: \newcommand\trans[1]{{#1}^\intercal}%\newcommand\trans[1]{{\vphantom{#1}}^\top{#1}}
#+LATEX_HEADER: \newcommand{\independent}{\mathrel{\text{\scalebox{1.5}{$\perp\mkern-10mu\perp$}}}}
#+LaTeX_HEADER: \newcommand\half{\frac{1}{2}}
#+LaTeX_HEADER: \newcommand\normMax[1]{\left|\left|#1\right|\right|_{max}}
#+LaTeX_HEADER: \newcommand\normTwo[1]{\left|\left|#1\right|\right|_{2}}
#+LATEX_HEADER: \newcommand\Veta{\boldsymbol{\eta}}
#+LATEX_HEADER: \newcommand\VX{\mathbf{X}}
** Notations



