\documentclass[11pt,oneside]{article}    %use"amsart"insteadof"article"forAMSLaTeXformat
\usepackage{geometry}        %Seegeometry.pdftolearnthelayoutoptions.Therearelots.
\geometry{letterpaper}        %...ora4paperora5paperor...
%\geometry{landscape}        %Activateforforrotatedpagegeometry
%\usepackage[parfill]{parskip}        %Activatetobeginparagraphswithanemptylineratherthananindent
\usepackage{graphicx}                %Usepdf,png,jpg,orepsßwithpdflatex;useepsinDVImode
                                %TeXwillautomaticallyconverteps-->pdfinpdflatex
\usepackage{amssymb}
\usepackage[colorlinks]{hyperref}
\usepackage{algorithm}
\usepackage{algpseudocode}

%----macros begin---------------------------------------------------------------
\usepackage{color}
\usepackage{amsmath}
\usepackage{amsthm}
\newtheorem{theorem}{Theorem}

\def\conv{\mbox{\textrm{conv}\,}}
\def\aff{\mbox{\textrm{aff}\,}}
\def\N{\mathbb{N}}
\def\E{\mathbb{E}}
\def\R{\mathbb{R}}
\def\Z{\mathbb{Z}}
\def\tex{\TeX}
\def\latex{\LaTeX}
\def\v#1{{\bf #1}}
\def\p#1{{\bf #1}}
\def\T#1{{\bf #1}}

\def\vet#1{{\left(\begin{array}{cccccccccccccccccccc}#1\end{array}\right)}}
\def\mat#1{{\left(\begin{array}{cccccccccccccccccccc}#1\end{array}\right)}}

\def\lin{\mbox{\rm lin}\,}
\def\aff{\mbox{\rm aff}\,}
\def\pos{\mbox{\rm pos}\,}
\def\cone{\mbox{\rm cone}\,}
\def\conv{\mbox{\rm conv}\,}
\newcommand{\homog}[0]{\mbox{\rm homog}\,}
\newcommand{\relint}[0]{\mbox{\rm relint}\,}

%----macros end-----------------------------------------------------------------

\title{Boundary operators on LAR
\footnote{This document is part of the \emph{Linear Algebraic Representation with CoChains} (LAR-CC) framework~\cite{cclar-proj:2013:00}. \today}
}
\author{Alberto Paoluzzi}
%\date{}                            %Activatetodisplayagivendateornodate

\begin{document}
\maketitle
\nonstopmode

\begin{abstract}
The various versions of boundary operators on Linear Algebraic Representation of cellular complexes are  developed in this module, in order to maintain under focus their proper development, including the possible special cases.
\end{abstract}

\tableofcontents
\newpage

\section{Introduction}

In the current \texttt{LarLib} implementation, we have to distinguish between between dimension-independent, dimension-dependent, oriented and non-oriented operators.
Therefore a code refactoring of \texttt{LarLib}---related to boundary/coboundary operators---started here, with the aim of both providing a precise mathematical definition within the LAR framework, and to simplify and generalise the implemented algorithms.

\section{Implementation}

We start this section by making a distinction between the (matrices of) boundary operators for the linear spaces $C_k$ of chains over the field $\Z_2 = \{0,1\}$ and over the field $\Z$ of integer numbers.
We call either \emph{non-oriented} or \emph{oriented} the corresponding boundary operators, respectively, since the matrix elements take values within the sets $\{-1,0,+1\}$ or $\{0,1\}$, correspondingly.
Of course, the associated matrices of \emph{coboundary} operators are their transpose matrices.

\subsection{Non-oriented operators}

For several computations, the knowledge of the matrices of non-oriented boundary operators is sufficient.
Therefore we will use such tool wherever possible, since its computation is much faster in term of computing time.

In the following we provide be binary operator matrices provided by two implementations,
respectively named \texttt{boundary} and \texttt{larUnsignedBoundary2}. The first one works correctly only with convex cells; the second one works also with non-convex but path-connected cells.

\subsubsection{Dimension-independence}

As we show in the following, in order to compute the non-oriented boundary operator $\partial_d$, it it sufficient to have knowledge of the $M_d$ and $M_{d-1}$ characteristic matrices of $d$-cells and their $(d-1)$-facets, at least in the case of cellular complexes with convex cells. Conversely, for more general non-convex but simply-connected cells, also the $M_{d-2}$ matrix is needed.

\paragraph{Convex-cells}

The algorithm used is pretty easy to present. The compressed characteristic matrices of $d$-cells and $(d-1)$-cells, denoted as \texttt{cells} and \texttt{facets}, respectively, are first put in \texttt{csr} format as \texttt{csrCV} and \texttt{csrFV}. Then the incidence matrix \texttt{csrFC} in compressed sparse row format is computed by matrix product of the compressed characteristic matrices.

The element $(i,j)$ of this matrix provides the number of vertices in the intersection of \emph{facet} $i$ and \emph{cell} $j$, whereas the number of non-zero elements in each \texttt{csrFV} \emph{row} gives the number of vertices of the facet represented by the row, and is stored in \texttt{facetLengths}.

The \texttt{boundary} function---to be used only with dimension-independent LAR convex cells---is written efficiently in the following script, by using only the standard functions and attributes of the \texttt{scipy.sparse} module.

The variable \texttt{facetCoboundary} stores in a list, for every facet (\texttt{for h in range(m)})
the list of cells in its \emph{coboundary}, to be stored in the output \texttt{csr\_matrix} boundary matrix as column indices of elements with non-zero (i.e.~$1$) value.

Notice that both the computation of \texttt{facetCoboundary} contents, and the output of the compressed boundary matrix, are performed in the most efficient way---according to the internal design of the scipy's \texttt{csr} sparse data structure.

%-------------------------------------------------------------------------------
@D convex-cells boundary operator
@{""" convex-cells boundary operator --- best implementation """
def larBoundary(cells,facets):
    lenV = max(max(CAT(cells)),max(CAT(facets)))+1
    csrCV = csrCreate(cells,lenV)
    csrFV = csrCreate(facets,lenV)
    csrFC = csrFV * csrCV.T
    facetLengths = [csrFacet.getnnz() for csrFacet in csrFV]
    m,n = csrFC.shape
    facetCoboundary = [[csrFC.indices[csrFC.indptr[h]+k]
        for k,v in enumerate(csrFC.data[csrFC.indptr[h]:csrFC.indptr[h+1]])
            if v==facetLengths[h]] for h in range(m)]
    indptr = [0]+list(cumsum(AA(len)(facetCoboundary)))
    indices = CAT(facetCoboundary)
    data = [1]*len(indices)
    return csr_matrix((data,indices,indptr),shape=(m,n),dtype='b')
@}
%-------------------------------------------------------------------------------

\subsection{Non-convex LAR cells}

A more general \texttt{larUnsignedBoundary2} operator is given in the following, aiming at compute the boundary matrix for general non-convex cellular decompositions, including \emph{multiply connected} LAR models.
Notice that in this case an input triple made by \texttt{CV}, \texttt{FV}, and \texttt{EV} is needed,
where---more in general embedded in $\mathbf{E}^d$---they stand for the (binary compressed) characteristic matrices $M_d$, $M_{d-1}$, and $M_{d-2}$.

\paragraph{Boundary operator from 3-chains to 2-chains}

%-------------------------------------------------------------------------------
@D path-connected-cells boundary operator
@{""" path-connected-cells boundary operator """
def larUnsignedBoundary2(CV,FV,EV):
    out = larBoundary(CV,FV)
    def csrRowSum(h):
        return sum(out.data[out.indptr[h]:out.indptr[h+1]])
    unreliable = [h for h in range(len(FV)) if csrRowSum(h) > 2]
    if unreliable != []:
        csrBBMat = larBoundary(FV,EV) * larBoundary(CV,FV)
        lenV = max(max(CAT(CV)),max(CAT(FV)),max(CAT(EV)))+1
        FE = larcc.crossRelation0(lenV,FV,EV)
        out = csrBoundaryFilter2(unreliable,out,csrBBMat,CV,FE)
    return out

def boundary3(CV,FV,EV):
    out = larUnsignedBoundary2(CV,FV,EV)
    lenV = max(max(CAT(CV)),max(CAT(FV)),max(CAT(EV)))+1
    VV = AA(LIST)(range(lenV))
    csrBBMat = scipy.sparse.csc_matrix(larBoundary(FV,EV) * larUnsignedBoundary2(CV,FV,EV))
    def csrColCheck(h):
        return any([val for val in csrBBMat.data[csrBBMat.indptr[h]:csrBBMat.indptr[h+1]] if val>2])
    unreliable = [h for h in range(len(CV)) if csrColCheck(h)]
    if unreliable != []:
        FE = larcc.crossRelation0(lenV,FV,EV)
        out = csrBoundaryFilter3(unreliable,out,csrBBMat,CV,FE)
    return out
@}
%-------------------------------------------------------------------------------

\paragraph{Boundary operator from 2-chains to 1-chains}

First the \texttt{boundary} operator for the convex case is computed within the \texttt{out} variable of \texttt{csr\_matrix} type. Then every \texttt{out} row (i.e.~every $(d-1)$-facet of the $d$-complex) is tested for \emph{reliability}, since every $(d-1)$-face can be shared by \emph{at most two} $d$-cells in a $d$-complex . When this condition is not satisfied, deeper tests are needed to understand what row elements must be forced to value 1, since the $(d-1)$-face itself is a subset, but not actually a facet, of the corresponding $d$-cell.

In presence of some ``unreliable'' facets, the matrix \texttt{csrBBMat} of the operator $\partial_{d-1}\circ\partial_d$ and the relation \texttt{FE} between faces of dimensions $d-1$ and $d-2$ are computed. Now, let us notice that the columns of \texttt{csrBBMat} report the number of incidences of the $d-2$ faces (as belonging to $(d-1)$-facets embedded on the boundary) and $d$-cells (that are associated to such matrix columns). Hence, in a regular (convex) $d$-complex, such numbers are always even, and in $\Z_2$ arithmetic are reduced to zero, in order to satisfy the fundaments equation $\partial\partial=0$.

Conversely, with non-convex LAR cells, some incidence numbers may get odd values, due to the non-strict coincidence between cell facets and vertex subsets.
Therefore, for ``unreliable'' $h$ rows (facets) the \texttt{csrBBMat} columns tracked by ones in $[\partial_d]$ are checked, looking for elements of $(h,k)$ indices with value greater that 2.

%-------------------------------------------------------------------------------
@D path-connected-cells boundary operator
@{""" path-connected-cells boundary operator """
import larlib
import larcc
from larcc import *

def csrBoundaryFilter2(unreliable,out,csrBBMat,cells,FE):
    for row in unreliable:
        for j in range(len(cells)):
            if out[row,j] == 1:
                cooCE = csrBBMat.T[j].tocoo()
                flawedCells = [cooCE.col[k] for k,datum in enumerate(cooCE.data)
                    if datum>2]
                if all([facet in flawedCells  for facet in FE[row]]):
                    out[row,j]=0
    return out

def csrBoundaryFilter3(unreliable,out,csrBBMat,cells,FE):
    for col in unreliable:
        cooCE = csrBBMat.T[col].tocoo()
        flawedCells = [cooCE.col[k] for k,datum in enumerate(cooCE.data)
                    if datum>2]
        for j in range(out.shape[0]):
            if out[j,col] == 1:
                if all([facet in flawedCells  for facet in FE[j]]):
                    out[j,col]=0
    return out
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-02}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-03}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-04}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-05}
   \caption{Non-convex LAR 2-complex with (two) 1-cells that are subsets of 2-cells without being their facets. Correctly disentangled by the \texttt{larUnsignedBoundary2()} function: (a) Indexing of 0-, 1-, and 2-cells; (b) exploded 2-cells; (c) triangulated and exploded 2-cells; (d) boundary of the 2-chain \texttt{[1,1,1,1,1,0]}.}
   \label{fig:example}
\end{figure}

%-------------------------------------------------------------------------------
@D From cells and facets to boundary cells
@{def totalChain(cells):
    return csr_matrix(len(cells)*[[1]])

def boundaryCells(cells,facets):
    csrBoundaryMat = larBoundary(cells,facets)
    csrChain = csr_matrix(totalChain(cells))
    csrBoundaryChain = csrBoundaryMat * csrChain
    out = [k for k,val in enumerate(csrBoundaryChain.data.tolist()) if val == 1]
    return out

def boundary2Cells(cells,facets,faces):
    csrBoundaryMat = larUnsignedBoundary2(cells,facets,faces)
    csrChain = csr_matrix(totalChain(cells))
    csrBoundaryChain = csrBoundaryMat * csrChain
    out = [k for k,val in enumerate(csrBoundaryChain.data.tolist()) if val == 1]
    return out

def boundary3Cells(cells,facets,faces):
    csrBoundaryMat = boundary3(cells,facets,faces)
    csrChain = csr_matrix(totalChain(cells))
    csrBoundaryChain = csrBoundaryMat * csrChain
    out = [k for k,val in enumerate(csrBoundaryChain.data.tolist()) if val == 1]
    return out
@}
%-------------------------------------------------------------------------------

\subsection{Correctness proof}

Our goal is to get a constructive and, of course, correct representation of the matrix $[\partial_3]$ starting only from $M_1$, $M_2$, and $M_3$.

We have sufficient evidence here to support the correctness of our identification of the matrices of boundary operators as discussed in the previous section. Remember that $M_1$, $M_2$, and $M_3$ are the characteristic matrices of 1-cells, 2-cells and 3-cells as subsets of vertices, and that $C_0, C_1, C_2, C_3$ are the linear spaces of 0-, 1-, 2-, and 3-chains, with coefficients in the field $\Z_2=\{0,1\}$.

In the following we give a dimension-independent proof, even our implementation is currently restricted to $d\in\{1,2,3\}$.

\paragraph{Preamble}
It is well known that a linear transformation $T: V\to W$ between two linear spaces, with fixed bases  of dimension $n$ and $m$ respectively, is represented uniquely by a matrix $A\in \R^{m\times n}$, that by columns contains the coordinate representations in $W$ of the basis vectors of $V$.

\begin{theorem}
Consider the linear transformation $\partial_d: C_d \to C_{d-1}$. Having fixed the bases, made by singleton cells in $C_d$ and $C_{d-1}$, the transformation $\partial_d$ can be represented as a matrix product ${c} \mapsto [\partial_d]\, {c}$, where ${c}\in C_d$ is the coordinate representation of a d-chain, and $[\partial_d]$ is the $m\times n$ binary matrix having \emph{by columns} the coordinate representation in $C_{d-1}$ of the boundary $(d-1)$-chains of cells in $C_{d}$.
\end{theorem}

\begin{proof}
The computation of the boundary operator matrix $A_d = [\partial_d] \in\Z_2^{m\times n}$, where $m$ and $n$ are the dimensions of the linear spaces $C_d$ and $C_{d-1}$, respectively, is made in two steps, in the general case.

\paragraph{First step}
Consider the characteristic matrices $M_d\in\Z_2^{m\times q}$ and $M_{d-1}\in\Z_2^{n\times q}$ having as rows the images of characteristic functions of bases elements as subsets of vertices, where $q$ is the number of vertices.

Then consider the product matrix $M=M_{d-1}M_{d}^t=(m_{ij})$, with values in the set $\N$ of non-negative integers. Clearly $m_{ij}$ will coincide with the number of vertices shared by cells $c_i\in C_{d-1}$ and $c_j\in C_d$, i.e. with the cardinality of their intersection as discrete sets of vertices. The predicate
\begin{equation}
m_{ij} \equiv |c_i|
\label{eq:intersection}
\end{equation}
is a \emph{necessary} condition for $c_i$ to be a \emph{facet} of $c_j$. Using the Iverson bracket notation, where $[P]$ returns either 1 or 0 depending on the truth of predicate $P$, we can  assign (to) the $(i,j)$ element of our (tentative) boundary matrix the corresponding value:
\begin{equation}
A_d(i,j) := [m_{ij} \equiv |c_i|], \qquad 1\leq i\leq m,\, 1\leq j\leq n.
\label{eq:iverson}
\end{equation}
Unfortunately, condition~(\ref{eq:intersection}) is also \emph{sufficient} for $c_i$ being a facet of $c_j$ only when both are convex cells. In other words, Equation~(\ref{eq:iverson}) with $A_d=[\partial_d]$ holds in full generality if and only if the cellular complex under consideration is made only by convex cells. With more general cells, the column $j$ of the $\partial_d$ matrix contains the coordinate representation in $C_{d-1}$ of a possibly proper \emph{superset}  of $\partial_d(c_j)$.

\paragraph{Second step}
In order to reduce the columns of the approximate boundary matrix $A_d$ to their exact value in $\Z_2^m$, with $m=\dim C_{d-1}$, we may compute an (approximate) matrix $B\in\N^{p\times n}$ of the operator $\partial_{d-1}\circ\partial_d: C_d \to C_{d-2}$, with $p=\dim C_{d-2}$, by using the approximate representation $A_d$ of the matrix $[\partial_d]$. Let us remark that the exact value of the latter is yet unknown at this point.

According to what asserted in the preamble, every column of this matrix should contain the coordinate representation (in $C_{d-2}$) of the boundary of the boundary of a basis element in $C_d$, i.e.~of a singleton $d$-chain.

Therefore, we will enforce the validity of the constraints $\partial\partial=0$, by checking
the values of columns in the product matrix $B_d = A_{d-1} A_d \in \N^{p\times n}$. In particular, ~every unit vector $e_j$, \emph{i.e.},~the coordinate representation of a singleton chain $c_j\in C_d$, should be mapped by $B_d$ to the zero vector in $\Z_2^p$:
\begin{equation}
e_j \mapsto B_d\, e_j = 0^{p} \in \Z_2^p, \qquad c_j\in C_d.
\label{eq:boundaryofboundary}
\end{equation}

Now, let consider the cells of LAR both as subsets of vertices and as cells of a cellular complex.
Actually, in the LAR general case, there may be some $(d-1)$-facets of some $d$-cell that are subsets of other $d$-cells of which they are not faces. It is not difficult to provide some examples of this fact (see Figure~\ref{fig:}).

When considering each column of $B$ as the coordinate representation of the boundary $(d-2)$-chain of a $d$-cell, and noting that every $d$-cell must be \emph{orientable}, and hence separating an interior space from an exterior space, we conclude that the number of occurrencies of each $(d-2)$-cell in a $B$ column must be necessarily even. In particular, it must be either equal to 2 if the column (the $d$-cell) is locally manifold, or equal to some even number $>2$ if the $d$-cell is locally non-manifold. But \emph{odd incidencies} of $(d-2)$-cells along the $d$-cell boundary \emph{are not allowed}.

Therefore, for each column $B_j$ ($1\leq j\leq n$) we look for the subset of rows (i.e.~boundary $(d-2)$-faces of $c_j$) of odd value. If there are none, the column $A_j$, associated to $c_j$, is a correct representation of $[\partial_d]_j$. Otherways, we must look for the subsets of $(d-1)$-cells \emph{incorrectly} considered facets of $c_j$.

Let us call $R_j$ the subset of row indices corresponding to odd values in column $B_j$, and consider the subset of $A_j$ rows with value $a_{ij}=1$, i.e.~the superset $S_j$ of $(d-1)$-cells including the boundary $(d-1)$-chain of $c_j$. The redundant vertex subsets that are not boundary facets of $c_j$  are easily discovered by looking at the $(d-2)$-boundary of each $s\in S_j$.

In particular, the $(d-1)$-cell $s\in S_j$ is \emph{redundant} or \emph{extraneous} with respect to the $c_j$ boundary if and only if $\partial_{d-1}(s) \subseteq R_j$, because that property has certainly introduced a spurious increment for each $(d-2)$-facet in the count of incidences of boundary facets.

At this point, we can finally compute the actual boundary matrix $\partial_d$ for a \emph{general} LAR cellular complex, using again the Iverson brackets:
\begin{align*}
[\partial_d]_{ij} = [(a_{ij}=1) \wedge ((R_j=\emptyset) \vee (R_j \not\supseteq \partial_{d-1}(s_i)))]\qquad 1\leq i\leq m,\, 1\leq j\leq n
\end{align*}
In words it sounds that \emph{the element $(i,j)$ of the boundary matrix $[\partial]_d$ equals that of the ``approximate'' matrix $A_d$ if and only if either the redundant set $R_j$ is empty, or if it does not contain the $(d-1)$-boundary chain of the $i$-th $(d-1)$-cell.}

Just remember that the redundant set $R_j$ contains the $(d-2)$-faces with odd incidencies on $c_j\in C_d$, computed via the ``approximate'' matrix $B_d = A_{d-1}\circ A_d$.

\end{proof}

\subsection{Oriented operators}

\subsubsection{Oriented simplicial complexes}

\subsubsection{Oriented LAR complexes}

\section{From relations to operators}
%===============================================================================

The LAR approach to topology, implemented in the \texttt{LarLib} modules, allows the user to consider the topological relations of incidence and adjacency between faces of a cellular complex as \emph{linear operators} between chains of cells of various dimensions.

The previous approach was to consider the incidence and adjaceny as set-theoretical relations, to be solved by using typical database tools. Conversely, according to the novel IT evolution towards big data and cloud-based storage, even for geometrical data, \texttt{LarLib}  takes advantage of a conceptual framework based on linear-algebra and sparse matrices.

\subsection{Classification of operators}

In the standard solid modeling approach, mainly based on boundary representations, the standard topological operations concern the answers to queries, by reporting the subsets of boundary elements which are incident (different dimension) or adjacent (equal dimension) to assigned boundary elements. Boundary elements stand there for three type of boundary cells: aka \emph{faces} $F$, \emph{edges} $E$, and \emph{vertices} $V$. Nine binary relations may be considered, that are summarized in Table~\ref{tab:one}.
\begin{table}[htbp]
\caption{Binary topological relations between boundary elements in boundary representations of solid models}
\begin{center}
\begin{tabular}{|c|ccc|}
\hline
  & F & E & V \\
\hline
F & FF & FE & FV \\
E & EF & EE & EV \\
V & VF & VE & VV \\
\hline
\end{tabular}
\end{center}
\label{tab:one}
\end{table}%

Conversely, LAR  models are normally based on cellular 3-complexes, so using four sets of cells, namely \emph{3-cells} $C$, \emph{2-cells} $F$, \emph{1-cells} $E$, and \emph{0-cells} $V$. The resulting tables of topological relations, and the associated linear operators, are shown in Tables~\ref{tab:two}a and \ref{tab:two}b, respectively.
\begin{table}[htbp]
\caption{Binary topological relations between cells of LAR decompositions of  solid models and corresponding topological operators on $\partial_\circ$ chains.}
\vspace{3mm}
\begin{minipage}[c]{0.5\linewidth}\centering
\begin{tabular}{|c|cccc|}
\hline
  & C & F & E & V \\
\hline
C & CC & \fbox{CF} & \fbox{CE} & CV \\
F & \fbox{FC} & FF & \fbox{FE} & FV \\
E & \fbox{EC} & \fbox{EF} & EE & EV \\
V & VC & VF & VE & VV \\
\hline
\end{tabular}
\end{minipage}
\begin{minipage}[c]{0.5\linewidth}\centering
\begin{tabular}{|c|cccc|}
\hline
  & C & F & E & V \\
\hline
C & $\v{1}_C^\top\circ\v{1}_C$ & {$\partial_3$} & {$\partial_2\circ\partial_3$} & $\v{1}_C$ \\
F & {$\delta_2$} & $\v{1}_F^\top\circ\v{1}_F$ & {$\partial_2$} & $\v{1}_F$ \\
E & {$\delta_2\circ\delta_1$} & {$\delta_1$} & $\v{1}_E^\top\circ\v{1}_E$ & $\v{1}_E$ \\
V & $\v{1}_C^\top$ & $\v{1}_F^\top$ & $\v{1}_E^\top$ & $\v{1}_V$ \\
\hline
\end{tabular}
\end{minipage}
\label{tab:two}
\end{table}%

\subsection{Topological relations}
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

\subsubsection{Adjacency relations}

%-------------------------------------------------------------------------------
@D kfaces-to-kfaces relation
@{""" kfaces-to-kfaces relation """
eeOp = larEdges2Edges(EV,VV)
EE = [eeOp([k]) for k in range(len(EV))]

ffOp = larFaces2Faces(FV,EV)
FF = [ffOp([k]) for k in range(len(FV))]

ccOp = larCells2Cells(CV,FV,EV)
CC = [ccOp([k]) for k in range(len(CV))]

@}
%-------------------------------------------------------------------------------

\paragraph{Adjacency relations examples}
%-------------------------------------------------------------------------------
@O test/py/boundary/test09.py
@{""" Adjacency relations examples """
from larlib import *

sys.path.insert(0, 'test/py/boundary/')
from test07 import *

@< kfaces-to-kfaces relation @>
print "\nCC =",CC
print "\nFF =",FF
print "\nEE =",EE,"\n"

V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([1,0])
VIEW(STRUCT(MKTRIANGLES((V,[FV[h] for h in FF[-1]],EV),color=True)))
VIEW(STRUCT(MKPOLS((V,[EV[h] for h in EE[-1]]))+[COLOR(RED)(MKPOLS((V,[EV[-1]]))[0])]))
@}
%-------------------------------------------------------------------------------

\subsubsection{Incidence relations}

%-------------------------------------------------------------------------------
@D mfaces-to-nfaces relations
@{""" mfaces-to-nfaces relations """
fcOp = larCells2Faces(CV,FV,EV)
CF = [fcOp([k]) for k in range(len(CV))]
FC = invertRelation(CF)

ecOp = larCells2Edges(CV,FV,EV)
CE = [ecOp([k]) for k in range(len(CV))]
EC = invertRelation(CE)

efOp = larFaces2Edges(FV,EV)
FE = [efOp([k]) for k in range(len(FV))]
EF = invertRelation(FE)
@}
%-------------------------------------------------------------------------------

\paragraph{Incidence relations examples}
%-------------------------------------------------------------------------------
@O test/py/boundary/test10.py
@{""" Incidence relations examples """
from larlib import *

sys.path.insert(0, 'test/py/boundary/')
from test08 import *

@< mfaces-to-nfaces relations @>
print "\nFC =",FC
print "\nEC =",EC
print "\nEF =",EF,"\n"
@}
%-------------------------------------------------------------------------------

\subsection{Querying}
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The more important topological operations in a geometric system concern the answer to queries of the type: ``what is the $h$-chain whose cells are $(k-h)$-incident to a given $h$-chain''?

An efficient answer is given by the three higher-level functions in this section, respectively denoted as \texttt{larCells2Faces}, \texttt{larCells2Edges}, and \texttt{larFaces2Edges}.
Their first application, over the two or three necessary (compressed) characteristic matrices, returns the \texttt{csr\_matrix} of the topological operator, that can be so cached by the calling code.
The second application, over the list of $h$-chain indices, returns the list of $k$-chain indices of the cells that share with them a $(k-h)$-face.

\subsubsection{Topological incidences}

\paragraph{Query from 3-chain to incident 2-chain}
%-------------------------------------------------------------------------------
@D Query from 3-chain to incident 2-chain
@{""" Query from 3-chain to incident 2-chain """
def larCells2Faces(CV,FV,EV):
    csrFC = boundary3(CV,FV,EV)
    def larCells2Faces0(chain):
        chainCoords = csc_matrix((csrFC.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrFC * chainCoords
        return out.tocoo().row.tolist()
    return larCells2Faces0
@}
%-------------------------------------------------------------------------------

\paragraph{Query from 3-chain to incident 1-chain}
%-------------------------------------------------------------------------------
@D Query from 3-chain to incident 1-chain
@{""" Query from 3-chain to incident 1-chain """
def larCells2Edges(CV,FV,EV):
    lenV = max(CAT(CV))+1
    VV = AA(LIST)(range(lenV))
    csrEC = larUnsignedBoundary2(FV,EV,VV) * boundary3(CV,FV,EV)
    def larCells2Faces0(chain):
        chainCoords = csc_matrix((csrEC.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrEC * chainCoords
        return out.tocoo().row.tolist()
    return larCells2Faces0
@}
%-------------------------------------------------------------------------------

\paragraph{Compute the signed 2-boundary matrix}
Compute the signed 2-boundary matrix. The second definition extends the first one by considering LAR faces including holes. For this purpose the signed areas of all loops inside each lar face in FV are taken into account, and only the greates positive area and all the negative areas (exept the most negative one) are considered.
%-------------------------------------------------------------------------------
@D Compute the signed 2-boundary matrix
@{""" Compute the signed 2-boundary matrix """
import triangulation,integr

def larSignedBoundary2(V,FV,EV):
    efOp = larFaces2Edges(V,FV,EV)
    FE = [efOp([k]) for k in range(len(FV))]
    data,row,col = [],[],[]
    for f in range(len(FE)):

        Vcycles,Ecycles = triangulation.makeCycles((V,[EV[e] for e in FE[f]]))
        Ecycles = [[FE[f][e] for e in cycle] for cycle in Ecycles]
        #areas = integr.signedSurfIntegration((V,Vcycles,EV),signed=True)
        areas = integr.signedSurfIntegration((V, Vcycles, EV), False)
        sortedAreas = sorted((area,k) for k,area in enumerate(areas))
        innerLoops = [zip(Vcycles[k],Ecycles[k]) for area,k in sortedAreas[1:] if area<0]
        outerLoop = [zip(Vcycles[sortedAreas[-1][1]],Ecycles[sortedAreas[-1][1]])]
        orientedFaceLoops = CAT(outerLoop+innerLoops)
        coefficients = [1 if v==EV[e][0] else -1 for v,e in orientedFaceLoops]

        ecycle = [e for v,e in orientedFaceLoops]
        data += coefficients
        row += ecycle
        col += [f]*len(ecycle)
        #print f,len(data),len(row),len(col)
    signedBoundary2 = coo_matrix((data,(row,col)), shape=(len(EV),len(FV)),dtype='b')
    return csr_matrix(signedBoundary2)
@}
%-------------------------------------------------------------------------------

\paragraph{Compute any signed 1-boundary chain}
The script below computes the signed boundary 1-cycle of any 2-chain in a 2-complex.
The script returns the pair of arrays \texttt{orientations,boundaryCells}, providing the signs of 1-cells in the extracted 1-cycle and their edge indices, respectively.
%-------------------------------------------------------------------------------
@D Compute any signed 1-boundary chain
@{""" Compute any signed 1-boundary chain """
def larSignedBoundary2Cells(V,FV,EV):
	def larSignedBoundary2Cells0(chain):
		boundaryMat = larSignedBoundary2(V,FV,EV)
		chainCoords = csc_matrix((len(FV), 1))
		for cell in chain: chainCoords[cell,0] = 1
		boundaryCells = list((boundaryMat * chainCoords).tocoo().row)
		orientations = list((boundaryMat * chainCoords).tocoo().data)
		return orientations,boundaryCells
	return larSignedBoundary2Cells0
@}
%-------------------------------------------------------------------------------

\paragraph{Testing the extraction of a boundary chain}
An example for testing the extraction of the boundary 1-cycle of a 2-chain $[f_1,f_2]$ is given below.
The images generated by the script are displayed in Figure~\ref{fig:signedBoundary2}.
%-------------------------------------------------------------------------------
@O test/py/boundary/test14.py
@{""" Testing the extraction of a boundary chain """
from larlib import *

lines = svg2lines("test/svg2lines/test.svg")
V,FV,EV,polygons = larFromLines(lines,True)
VIEW(STRUCT(MKTRIANGLES((V,FV,EV),color=True)))
submodel = mkSignedEdges((V,EV))
VV = AA(LIST)(range(len(V)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.25))

orientations,boundaryCells = larSignedBoundary2Cells(V,FV,EV)([1,2])
orientedBoundaryCells = [EV[e] if sign==1 else REVERSE(EV[e])
						for sign,e in zip(orientations,boundaryCells)]

VIEW(STRUCT(MKTRIANGLES((V,FV[1:3],EV),color=True)))
VIEW(mkSignedEdges((V,orientedBoundaryCells)))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.27\linewidth,width=0.495\linewidth]{images/larSignedBoundary2a}
   \includegraphics[height=0.27\linewidth,width=0.495\linewidth]{images/larSignedBoundary2b}

   \includegraphics[height=0.27\linewidth,width=0.495\linewidth]{images/larSignedBoundary2c}
   \includegraphics[height=0.27\linewidth,width=0.495\linewidth]{images/larSignedBoundary2d}
   \caption{Example  of \emph{signed} boundary operator: (a) 2-complex with non-compressible cells; (b) oriented 1-cells; (c) drawing of the 2-chain $[f_1,f_2]$; (d) oriented boundary 1-chain of 2-chain $[f_1,f_2]$.}
   \label{fig:signedBoundary2}
\end{figure}

\paragraph{Query from 2-chain to incident 1-chain}
%-------------------------------------------------------------------------------
@D Query from 2-chain to incident 1-chain
@{""" Query from 2-chain to incident 1-chain """
def larFaces2Edges(V,FV,EV):
    VV = AA(LIST)(range(len(V)))
    csrEF = larUnsignedBoundary2(FV,EV,VV)
    def larCells2Faces0(chain):
        chainCoords = csc_matrix((csrEF.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrEF * chainCoords
        return out.tocoo().row.tolist()
    return larCells2Faces0
@}
%-------------------------------------------------------------------------------

\subsubsection{Topological adjacencies}

\paragraph{kfaces-to-kfaces relations}
%-------------------------------------------------------------------------------
@D kfaces-to-kfaces relations
@{""" kfaces-to-kfaces relations """

def larCells2Cells(CV,FV,EV):
    csrMat = boundary3(CV,FV,EV)
    csrCC = csrMat.T * csrMat
    def larCells2Cells0(chain):
        chainCoords = csc_matrix((csrCC.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrCC * chainCoords
        return out.tocoo().row.tolist()
    return larCells2Cells0

def larFaces2Faces(FV,EV):
    lenV = max(CAT(FV)) + 1
    VV = AA(LIST)(range(lenV))
    csrMat = larUnsignedBoundary2(FV,EV,VV)
    csrFF = csrMat.T * csrMat
    def larFaces2Faces0(chain):
        chainCoords = csc_matrix((csrFF.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrFF * chainCoords
        return out.tocoo().row.tolist()
    return larFaces2Faces0

def larEdges2Edges(EV,VV):
    lenV = len(VV)
    csrMat = larBoundary(EV,VV)
    csrEE = csrMat.T * csrMat
    def larFaces2Faces0(chain):
        chainCoords = csc_matrix((csrEE.shape[1],1),dtype='b')
        for k in chain: chainCoords[k,0] = 1
        out = csrEE * chainCoords
        return out.tocoo().row.tolist()
    return larFaces2Faces0
@}
%-------------------------------------------------------------------------------

\subsection{Oriented operators}

\subsubsection{Signed 2-boundary}

\paragraph{Testing signed 2-boundary}
%-------------------------------------------------------------------------------
@O test/py/boundary/test11.py
@{""" Testing signed 2-boundary """
from larlib import *

sys.path.insert(0, 'test/py/boundary/')
from test10 import *

@< mfaces-to-nfaces relations @>

signedBoundary2 = larSignedBoundary2(FV,EV)
@}
%-------------------------------------------------------------------------------

\paragraph{Testing signed 2-boundary}
%-------------------------------------------------------------------------------
@O test/py/boundary/test13.py
@{""" Testing signed 2-boundary """
from larlib import *

lines = svg2lines("test/svg2lines/test.svg")
V,FV,EV,polygons = larFromLines(lines,True)
VIEW(STRUCT(MKTRIANGLES((V,FV,EV),color=True)))
submodel = mkSignedEdges((V,EV))
VV = AA(LIST)(range(len(V)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.25))

B = larSignedBoundary2(V,FV,EV)
for k in range(B.shape[0]):
    print k,B.todense()[k]

VIEW(STRUCT(MKTRIANGLES((V,FV[1:3],EV),color=True)))
@}
%-------------------------------------------------------------------------------

\paragraph{Example 2-bondary matrix}
The example in file \texttt{test13.py}, corresponding to Figure~\ref{fig:signedBoundary2} produces the following two-dimensional LAR model:
{\scriptsize
\begin{verbatim}
V = [[0.8627, 0.263], [0.7223, 0.263], [0.7223, 0.1857], [0.8627, 0.1857], [0.5422, 0.0489], [0.3613,
0.0238], [0.0, 0.2296], [0.6044, 0.4933], [1.0, 0.382], [0.1896, 0.0], [0.5037, 0.1896], [0.9614,
0.1522], [0.9207, 0.318], [0.7457, 0.3241], [0.7457, 0.3942], [0.6583, 0.3942], [0.6583, 0.3241],
[0.3718, 0.157], [0.1704, 0.1259], [0.3541, 0.3141], [0.1748, 0.2296]]
EV = [[0, 1], [2, 1], [3, 2], [0, 3], [4, 5], [6, 7], [7, 8], [9, 10], [4, 10], [11, 12], [6, 9],
[4, 11], [12, 8], [9, 5], [4, 7], [13, 14], [15, 14], [16, 15], [13, 16], [17, 18], [17, 19],
[20, 18], [19, 20]]
\end{verbatim}}
and the following boundary operator matrix:
\[
\partial_2 =
\mat{
 0 & 0 &-1 & 0 & 1 & 0 \\
 0 & 0 & 1 & 0 &-1 & 0 \\
 0 & 0 & 1 & 0 &-1 & 0 \\
 0 & 0 & 1 & 0 &-1 & 0 \\
-1 & 0 & 0 & 0 & 0 & 0 \\
 0 &-1 & 0 & 0 & 0 & 0 \\
 0 & 0 &-1 & 0 & 0 & 0 \\
-1 & 1 & 0 & 0 & 0 & 0 \\
 1 &-1 & 0 & 0 & 0 & 0 \\
 0 & 0 & 1 & 0 & 0 & 0 \\
 0 & 1 & 0 & 0 & 0 & 0 \\
 0 & 0 & 1 & 0 & 0 & 0 \\
 0 & 0 & 1 & 0 & 0 & 0 \\
 1 & 0 & 0 & 0 & 0 & 0 \\
 0 & 1 &-1 & 0 & 0 & 0 \\
 0 & 0 &-1 & 1 & 0 & 0 \\
 0 & 0 & 1 &-1 & 0 & 0 \\
 0 & 0 & 1 &-1 & 0 & 0 \\
 0 & 0 & 1 &-1 & 0 & 0 \\
 0 & 1 & 0 & 0 & 0 &-1 \\
 0 &-1 & 0 & 0 & 0 & 1 \\
 0 &-1 & 0 & 0 & 0 & 1 \\
 0 &-1 & 0 & 0 & 0 & 1 \\
 }
\]

\paragraph{Transformation from chain coordinates to explicit chain data}
%-------------------------------------------------------------------------------
@D Transformation from chain coordinates to explicit chain data
@{""" Transformation from chain coordinates to explicit chain data """
def coords2chain(chainCoords):
    coo = coo_matrix(chainCoords)
    return [(e,val) for e,val in zip(coo.row,coo.data)]
@}
%-------------------------------------------------------------------------------

\subsection{Offset of 2-faces of a 2D complex}
In some applications it is necessary to compute the offset of faces of a 2D complex. This may happen for example in architectural applications, where the walls of building layout must be computed from its wire-frame design. Another important application aims to make more numerically robust the point-in-polygon containment test. In this case the test is driven against a slightly ``grown'' version of the polygon.
The problem solved by the \texttt{larOffset2D (model)} function given below is to "enlarge" each 2-face of a 2-complex in 2D of a (generally small) constant offset.
For this purpose, the \texttt{larOffset2D} function operates as follows:

\begin{enumerate}
\item translate every 1-face towards its cobounday exterior (see Figure 1);
\item compute the parametric line equation for the translated pairs of edge vertices;
\item compute the intersection points between of adjacent pairs of such lines:
    \begin{enumerate}
    \item solving for both parameters;
    \item using the computed parameter value to get the intersection point.
    \end{enumerate}
\end{enumerate}

\paragraph{Offset of 2-faces of a 2D complex}
The coding below is using the Cramer's formula for the the solution of the intersection of two 2D lines via their parametric equation, according to page 50-51 of the formulation given in \href{http://www.ti.inf.ethz.ch/ew/lehre/CG09/materials/v9.pdf}{http://www.ti.inf.ethz.ch/ew/lehre/CG09/materials/v9.pdf}.
The implementation is  simple and very general---e.g.˜it does not require conditional constructs---so that it may be useful to avoid, for future GPGPU implementations.
%-------------------------------------------------------------------------------
@D Offset of 2-faces of a 2D complex
@{""" Offset of 2-faces of a 2D complex """
from scipy.linalg.basic import det

def larOffset2D (model,offset=0.001):
    V,FV,EV = model
    newVertices,lines = [],[]

    for f in range(len(FV)):
        # pair of arrays (signs, edges) of f face
        orientations,boundaryCells = larSignedBoundary2Cells(V,FV,EV)([f])
        # array of pairs (sign, edge) of f face
        edges = zip(orientations,boundaryCells)

        # array of pairs (begin_vertex, end_vertex) of oriented edges of f face
        orientedEdges = [tuple(EV[e]) if sign==1 else tuple(REVERSE(EV[e]))
            for sign,e in edges]
        # array of unit tangentVectors of  f face
        tangentVectors = [UNITVECT(VECTDIFF([ V[edge[1]],V[edge[0]] ]))
            for edge in orientedEdges]
        # array of unit normalVectors of   f face
        normalVectors = [ SCALARVECTPROD([ offset,[vect[1],-vect[0]] ])
            for vect in tangentVectors]
        # array of pairs of moved vertices  of oriented edges of f face
        movedEdgesOffLine = [[VECTSUM([V[v],n]) for v in orientedEdges[k]]
            for k,n in enumerate(normalVectors)]
        # successor map ( succ[first] := second ) for verts of oriented edges of $f$
        succ = dict(orientedEdges)
        # dictionary of numerals of oriented edges of $f$ (key = pair of vertices)
        edgeDict = dict([(edge,k) for k,edge in enumerate(orientedEdges)])
        # array of pairs of numerals of intersecting edges
        intersections = [[ edgeDict[(u,v)], edgeDict[(v,succ[v])] ]
            for k,(u,v) in enumerate(orientedEdges)]
        # coupling of data points of intersecting pairs
        linepairs = [[movedEdgesOffLine[l1],movedEdgesOffLine[l2]]
            for l1,l2 in intersections]
        # prepare data for line pairs
        linedata = [[ax,ay,bx,by,cx,cy,dx,dy]
            for [[(ax,ay),(bx,by)],[(cx,cy),(dx,dy)]] in linepairs]
        # assemble intersection determinants
        determinants = [ det(mat([[ax-bx,dx-cx], [ay-by,dy-cy]]))
            for [ax,ay,bx,by,cx,cy,dx,dy] in linedata]
        # parameter pairs by Cramer's rule (for oriented edges of f face)
        alpha = [det(mat([[dx-bx,dx-cx],[dy-by,dy-cy]]))/D  if abs(D)>.00001 else 0
            for D,(ax,ay,bx,by,cx,cy,dx,dy) in zip(determinants,linedata)]
        # intersection points
        newvert = [ (a*mat(p1)+(1-a)*mat(p2)).tolist()[0]
            for a,[[p1,p2],[q1,q2]] in zip(alpha,linepairs)]
        newedges = [[newvert[u],newvert[v]] for u,v in intersections]

        newVertices += [newvert]
        lines += newedges
    return lines

@}
%-------------------------------------------------------------------------------

\paragraph{Example of Offset generation for the 2-faces of a 2D complex}
The result of execution of the test program below is given in Figure˜\ref{fig:offset}
%-------------------------------------------------------------------------------
@O test/py/boundary/test15.py
@{""" Example of Offset generation for the 2-faces of a 2D complex """
from larlib import *
lines = svg2lines("test/svg2lines/test.svg")
V,FV,EV,polygons = larFromLines(lines,True)
VIEW(STRUCT(MKTRIANGLES((V,FV,EV),color=True)))

submodel = mkSignedEdges((V,EV))
VV = AA(LIST)(range(len(V)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.25))

newEdges = larOffset2D((V,FV,EV),offset=0.01)
VIEW(STRUCT(MKPOLS((V,EV)) + AA(COLOR(YELLOW))(AA(POLYLINE)(newEdges))))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[width=0.49\linewidth]{images/offset1}
   \includegraphics[width=0.49\linewidth]{images/offset2}
   \caption{(a) the input 2-complex with general LAR cells; (b) drawing of the offset edges (in yellow) generated by \texttt{larOffset2D}.}
   \label{fig:offset}
\end{figure}

\subsection{Extraction of 3-cells from a 2-skeleton embedded in 3D}
Need to characterize the two vertices of zero edge as "last" of previous edge in the chain,
and "first" of following edge in the chain. Therefore the zero edge is oriented as from "last" to "first" and consequently, is "positive" iff  "first" $>$ "last".

It is sufficient to characterize the "first" vertex of the edge following the zero edge. This one is the "last" of zero edge. the other vertex of zero edge is its "first". Zero edge is "positive" iff last(zero) $>$ first(zero).

\paragraph{Choose the next face on ordered coboundary of edge}
Choose the "next" face $g_i$  on "ordered" coboundary of edge

%-------------------------------------------------------------------------------
@D Choose the next face on ordered coboundary of edge
@{""" Choose the next face on ordered coboundary of edge """
def adjFace(boundaryOperator,EV,EF_angle,faceChainOrientation):
    def adjFace0(edge,orientation):
        if orientation > 0:  edgeLoop = REVERSE(EF_angle[edge])
        elif orientation < 0:  edgeLoop = EF_angle[edge]
        edgeLoop = edgeLoop + [edgeLoop[0]]  # all positive indices

        candidates = set([f for f,_ in faceChainOrientation]).intersection(edgeLoop)
        if candidates != set([]):
            pivotFace = candidates.pop()
            if pivotFace in edgeLoop:
                pivotIndex = edgeLoop.index(pivotFace)
            else:
                pivotIndex = edgeLoop.index(-pivotFace)
            adjacentFace = edgeLoop[pivotIndex+1]
        else: return None

        theSign = boundaryOperator[edge,adjacentFace]
        return adjacentFace, -(theSign*orientation)
    return adjFace0
@}
%-------------------------------------------------------------------------------

\paragraph{Choose the start facet in extracting the facet representation of a cell}
%-------------------------------------------------------------------------------
@D Choose the start facet in extracting the facet representation of a cell
@{""" Choose the start facet in extracting the facet representation of a cell """

def chooseStartFace(FV,faceCounter):
    if faceCounter[0,0]==0: return (0,1)
    for f in range(len(FV)):
        if faceCounter[f,0]==1 and faceCounter[f,1]==0: return (f,-1)
        elif faceCounter[f,0]==0 and faceCounter[f,1]==1: return (f,1)
    for f in range(len(FV)):
        if faceCounter[f,0]==0 and faceCounter[f,1]==0: return (f,1)
    if sum(array(faceCounter))==2*len(FV): return (-1,999)
    else: print "ERROR: chooseStartFace"

def chooseStartFace(FV,faceCounter):
    for f in range(len(FV)):
        if faceCounter[f,0]==1 and faceCounter[f,1]==0: return (f,-1)
        elif faceCounter[f,0]==0 and faceCounter[f,1]==1: return (f,1)
    for f in range(len(FV)):
        if faceCounter[f,0]==0 and faceCounter[f,1]==0: return (f,1)
    if sum(array(faceCounter))==2*len(FV): return (-1,999)
    else: return (0,1)
@}
%-------------------------------------------------------------------------------

\paragraph{Extract the signed representation of a basis element}
%-------------------------------------------------------------------------------
@D Extract the signed representation of a basis element
@{""" Extract the signed representation of a basis element """
def signedBasis(boundaryOperator):
    facesByEdges = csc_matrix(boundaryOperator)
    m,n = facesByEdges.shape
    edges,signs = [],[]
    for i in range(n):
        edges += [facesByEdges.indices[facesByEdges.indptr[
                              i]:facesByEdges.indptr[i+1]].tolist()]
        signs += [facesByEdges.data[facesByEdges.indptr[
                              i]:facesByEdges.indptr[i+1]].tolist()]
    return zip(edges,signs)
@}
%-------------------------------------------------------------------------------

\paragraph{Algoritm}
The algorithm to compute the signed boundary matrix of a 3-complex is given below in pseudocode.

%-------------------------------------------------------------------------------
\begin{algorithm}
\caption{Compute the signed $\partial_3$ matrix of a 3-complex, from 2-skeleton}
\begin{algorithmic}[1]
\Function {larSignedBoundary3}{LarModel}
    \State {$V,FV,EV \leftarrow {}$LarModel}
    \State {$[\partial_2]\equiv[\delta_1]^t  \leftarrow {}$\textsc{larSignedBoundary2}(LarModel)}
    \State {$sort: EV\to FV\to \R^*: e\mapsto \delta_1(e)$ (ordered loops of signed 2-faces)}
    \State {$[\partial_3]\equiv[\delta_2]^t \leftarrow []$  (boundary 2-faces of 3-cells by row)}
    \State {$S = {}$indices\ of\ 2-faces}
    \While {$S \not= \emptyset$ (set of non-traversed 2-faces) }
        \State {$f \leftarrow \textsc{choose}(S)$ (first 2-face, reversing previous sign)}
        \State $F \leftarrow \{f\}$ (singleton 2-chain)
        \While {$\partial_2(F) \not= \emptyset$} ($F$ non closed)
            \State $E \leftarrow \partial_2(F) $ (1-cycle of signed edges)
            \While {$E \not= \emptyset$}
                \For {each $e \in E$}
                    \State {$f_i \leftarrow next(f)(sort(\delta_1(e)))$}
                    \State {$F \leftarrow F \cup \{f_i\}$}
                    \State {$S \leftarrow S - \{f_i\}$ (non-traversed 2-faces)}
                    \State {$E \leftarrow E - \{e\}$}
                \EndFor
                \State {$E \leftarrow \partial_2(F) $ (new oriented 1-cycle)}
            \EndWhile
        \EndWhile
        \State {$[\partial_3] \leftarrow [\partial_3]+[F]$ (put F in new $[\partial_3]$ column, i.e.~new $[\delta_2]$ row)}
    \EndWhile
    \State \Return {$[\partial_3]$ (operator's matrix)}
    \EndFunction
\end{algorithmic}
\end{algorithm}
%-------------------------------------------------------------------------------

\paragraph{Return the signed boundary matrix of a 3-complex}
%-------------------------------------------------------------------------------
@D Return the signed boundary matrix of a 3-complex
@{""" Return the signed boundary matrix of a 3-complex """
import boolean
def larSignedBoundary3((V,FV,EV)):
    model = V,FV,EV
    faceCounter = zeros((len(FV),2),dtype='b')
    CF,m = [],len(FV)
    efOp = larFaces2Edges(V,FV,EV)
    FE = [efOp([k]) for k in range(len(FV))]
    EF_angle, _,_,_ = boolean.faceSlopeOrdering(model,FE)
    nonWorkedFaces,coboundary_2,cellNumber = set(range(m)),[],0
    boundaryOperator = larSignedBoundary2(V,FV,EV)
    FEbasis = signedBasis(boundaryOperator)
    row,col,data = [],[],[]
    longestrow,longestcol,longestdata,longestLength = [],[],[],0
    while True:
        startFace,orientation = chooseStartFace(FV,faceCounter)
        if startFace == -1: break
        nonWorkedFaces = nonWorkedFaces.difference({startFace})
        faceChainOrientation = {(startFace,orientation)}
        vect = csc_matrix((m,1),dtype='b')
        for face,orientation in faceChainOrientation:
            vect[face] = orientation
        edgeCycleCoords = boundaryOperator * vect
        edgeCycle = coords2chain(edgeCycleCoords)
        while edgeCycle != []:
            look4face = adjFace(boundaryOperator,EV,EF_angle,faceChainOrientation)
            for edge,orientation in edgeCycle:
                outPair = look4face(edge,orientation)
                if outPair != None:
                    adjacentFace,orientation = outPair
                    faceChainOrientation = faceChainOrientation.union(
                        [(adjacentFace,orientation)])
                    nonWorkedFaces = nonWorkedFaces.difference([adjacentFace])
            vect = csc_matrix((m,1),dtype='b')
            for face,orientation in faceChainOrientation:
                vect[face] = orientation
            edgeCycleCoords = boundaryOperator * vect
            edgeCycle = coords2chain(edgeCycleCoords)
            #if edgeCycle!=[]: VIEW(STRUCT(MKPOLS((V,[EV[e] for e in TRANS(edgeCycle)[0]]))))
        for face,orientation in faceChainOrientation:
            if orientation == 1: faceCounter[face,0]+=1
            elif orientation == -1: faceCounter[face,1]+=1
        #VIEW(STRUCT(MKPOLS((V,[FV[f] for f in TRANS(faceChainOrientation)[0]]))))

        lastrow = [face for face,_ in faceChainOrientation]
        lastcol = [cellNumber for face,orientation in faceChainOrientation]
        lastdata = [orientation for _,orientation in faceChainOrientation]
        lastlength = len(lastrow)

        if lastlength >= longestLength:
            lastrow,longestrow = longestrow,lastrow
            lastcol,longestcol = longestcol,lastcol
            lastdata,longestdata = longestdata,lastdata
            lastlength,longestLength = longestLength,lastlength
        if lastlength != 0:
            row += lastrow
            col += lastcol
            data += lastdata
            CF += [lastrow]
            cellNumber += 1
        print "\nfaceCounter =",faceCounter
    outMatrix = coo_matrix((data, (row,col)), shape=(m,cellNumber),dtype='b')
    signedBoundary = zip(longestrow,longestdata)
    return csr_matrix(outMatrix),CF,signedBoundary
@}
%-------------------------------------------------------------------------------

\paragraph{Return the signed boundary matrix of a 3-complex}
%-------------------------------------------------------------------------------
@D Return the signed boundary matrix of a 3-complex
@{""" Return the signed boundary matrix of a 3-complex """
import boolean
def larSignedBoundary3((V,FV,EV)):
    model = V,FV,EV
    faceCounter = zeros((len(FV),2),dtype='b')
    CF,m = [],len(FV)
    efOp = larFaces2Edges(V,FV,EV)
    FE = [efOp([k]) for k in range(len(FV))]
    EF_angle, _,_,_ = boolean.faceSlopeOrdering(model,FE)
    nonWorkedFaces,coboundary_2,cellNumber = set(range(m)),[],0
    boundaryOperator = larSignedBoundary2(V,FV,EV)
    FEbasis = signedBasis(boundaryOperator)
    row,col,data = [],[],[]
    while True:
        startFace,orientation = chooseStartFace(FV,faceCounter)
        if startFace == -1: break
        nonWorkedFaces = nonWorkedFaces.difference({startFace})
        faceChainOrientation = {(startFace,orientation)}
        vect = csc_matrix((m,1),dtype='b')
        for face,orientation in faceChainOrientation:
            vect[face] = orientation
        edgeCycleCoords = boundaryOperator * vect
        edgeCycle = coords2chain(edgeCycleCoords)
        while edgeCycle != []:
            look4face = adjFace(boundaryOperator,EV,EF_angle,faceChainOrientation)
            for edge,orientation in edgeCycle:
                outPair = look4face(edge,orientation)
                if outPair != None:
                    adjacentFace,orientation = outPair
                    faceChainOrientation = faceChainOrientation.union(
                        [(adjacentFace,orientation)])
                    nonWorkedFaces = nonWorkedFaces.difference([adjacentFace])
            vect = csc_matrix((m,1),dtype='b')
            for face,orientation in faceChainOrientation:
                vect[face] = orientation
            edgeCycleCoords = boundaryOperator * vect
            edgeCycle = coords2chain(edgeCycleCoords)
            #if edgeCycle!=[]: VIEW(STRUCT(MKPOLS((V,[EV[e] for e in TRANS(edgeCycle)[0]]))))
        row += [face for face,_ in faceChainOrientation]
        col += [cellNumber for face,orientation in faceChainOrientation]
        data += [orientation for _,orientation in faceChainOrientation]
        cellNumber += 1

        for face,orientation in faceChainOrientation:
          if orientation == 1: faceCounter[face,0]+=1
          elif orientation == -1: faceCounter[face,1]+=1
        print "faceChainOrientation =",faceChainOrientation
        print "faceCounter =",faceCounter

        CF += [[face for face,_ in faceChainOrientation]]
        print "CF =",CF
        print "\nfaceCounter =",faceCounter
    outMatrix = coo_matrix((data, (row,col)), shape=(m,cellNumber),dtype='b')
    return csr_matrix(outMatrix),CF,faceCounter
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[width=0.295\linewidth]{images/signbound-0}
   %\includegraphics[width=0.245\linewidth]{images/signbound-2}
   \includegraphics[width=0.385\linewidth]{images/signbound-3}
   \includegraphics[width=0.30\linewidth]{images/signbound-4}
   \caption{Arrangment of 3-complexes: (a) 1-skeleton of the fragmented (union) 3-complex; (b) view from the interior of the boundary 2-complex; (c) view from the exterior of the 3-complex.
   Notice that the colour patches correspond to the chain of 2-faces of the boundary of 3-complex.
   }
   \label{fig:signbound}
\end{figure}

\paragraph{Test the signed boundary matrix of a 3-complex}
%-------------------------------------------------------------------------------
@D Test the signed boundary matrix of a 3-complex
@{""" Test the signed boundary matrix of a 3-complex """
if __name__=="__main__":

    V,[VV,EV,FV,CV] = larCuboids([2,2,1],True)
    cubeGrid = Struct([(V,FV,EV)],"cubeGrid")
    cubeGrids = Struct(2*[cubeGrid,t(.5,.5,.5),r(0,0,PI/6)])

    V,FV,EV = struct2Marshal(cubeGrids)
    VIEW(EXPLODE(1.2,1.2,1.2)(BREP((V,FV,EV),color=False) ))
@}
%-------------------------------------------------------------------------------

\subsection{Examples}

\paragraph{A 3-cell with several holes}
%-------------------------------------------------------------------------------
@O test/py/boundary/test12.py
@{""" testing boundary operators (correct result) """
from larlib import *

V,[VV,EV,FV,CV] = larCuboids([1,1,1],True)
cell = (V,FV,EV)
cubeGrid =  Struct([Struct([ s(10,10,1),cell ])] + 3*[t(0,2,0), Struct(3*[ t(1.5,0,0), cell] )] ,"cubeGrid")
VIEW(STRUCT(MKPOLS(struct2lar(cubeGrid))))

V,FV,EV = struct2Marshal(cubeGrid)
csrmat,CF,faceCounter = larSignedBoundary3((V,FV,EV))
print csrmat.todense()
@}
%-------------------------------------------------------------------------------

\section{Exporting}
%===============================================================================

%-------------------------------------------------------------------------------
@O larlib/larlib/boundary.py
@{""" boundary operators """
from larlib import *
@< convex-cells boundary operator @>
@< path-connected-cells boundary operator @>
@< From cells and facets to boundary cells @>
@< Marshalling a structure to a LAR cellular model @>
@< Compute the signed 2-boundary matrix @>
@< Compute any signed 1-boundary chain @>
@< Offset of 2-faces of a 2D complex @>
@< Boundary of a 3-complex @>
@< Query from 3-chain to incident 2-chain @>
@< Query from 3-chain to incident 1-chain @>
@< Query from 2-chain to incident 1-chain @>
@< kfaces-to-kfaces relations @>
@< Transformation from chain coordinates to explicit chain data @>
@< Choose the next face on ordered coboundary of edge @>
@< Choose the start facet in extracting the facet representation of a cell @>
@< Extract the signed representation of a basis element @>
@< Return the signed boundary matrix of a 3-complex @>
@< Test the signed boundary matrix of a 3-complex @>
@}
%-------------------------------------------------------------------------------

\section{Testing}

\subsection{Non-oriented operators}

\paragraph{Correct boundary extraction example}

The \texttt{larBoundary()} operator is applied here to a cellular 2-complex of convex cells, producing correct result. It is worth noting that the operator is dimension-independent, and must be appliad to the \emph{pair} of compressed characteristic matrices $M_d$ and $M_{d-1}$, that --- in list format --- we call either \texttt{CV,FV} or  \texttt{FV,EV}, depending on the dimension (either 3 or 2) of the embedding space.

%-------------------------------------------------------------------------------
@O test/py/boundary/test01.py
@{""" testing boundary operators (correct result) """
from larlib import *

filename = "test/svg/inters/boundarytest0.svg"
lines = svg2lines(filename)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,FV,EV,polygons = larFromLines(lines)
VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.2))
VIEW(EXPLODE(1.2,1.2,1.2)(MKPOLS((V,[EV[e] for e in boundaryCells(FV,EV)],))))
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,FV,EV))))

boundaryOp = larUnsignedBoundary2(FV,EV,VV)

for k in range(1,len(FV)+1):
    faceChain = k*[1]
    BF = chain2BoundaryChain(boundaryOp)(faceChain)
    VIEW(STRUCT(MKPOLS((V,[EV[e] for e in BF]))))
@}
%-------------------------------------------------------------------------------

\paragraph{Wrong boundary extraction example}

The \texttt{larBoundary()} operator, applied  to a cellular 2-complex wih some non-convex cells, produces incorrect results. In such cases a correct result may be produced only by chance (sometimes this happens). So, be careful to use it only when the precondition (of cell convexity) is everywhere verified. In order to get always a correct result, use the \texttt{larUnsignedBoundary2} operator.

%-------------------------------------------------------------------------------
@O test/py/boundary/test02.py
@{""" testing boundary operators (wrong result) """
from larlib import *

filename = "test/svg/inters/boundarytest3.svg" # KO (MKTRIANGLES) with boundarytest3 !!!
#filename = "test/svg/inters/boundarytest4.svg"
lines = svg2lines(filename)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,FV,EV,polygons = larFromLines(lines)
VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.2))

boundaryOp = larUnsignedBoundary2(FV,EV,VV)  # <<======  NB
#boundaryOp = larBoundary(FV,EV)  # <<======  NB
BF = chain2BoundaryChain(boundaryOp)([1]*len(FV))

VIEW(EXPLODE(1.2,1.2,1.2)(MKPOLS((V,[EV[e] for e in BF]))))
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,FV,EV),color=True)))
VIEW(SKEL_1(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,FV,EV)))))
"""
for k in range(1,len(FV)+1):
    faceChain = k*[1]
    boundaryChain = chain2BoundaryChain(boundaryOp)(faceChain)
    VIEW(STRUCT(MKPOLS((V,[EV[e] for e in boundaryChain]))))
"""
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-2}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-3}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-4}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-5}

   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-6}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-7}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-8}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test01-9}
   \caption{Convex-cell 2-complex. (a) Indexing of 0-,1-,and 2-cells; (b) exploded 2-boundary cells; (c) exploded 2-cells; (d) boundary of a singleton 2-chain; (e--h) boundaries of some 2-chains.}
   \label{fig:example}
\end{figure}

\paragraph{Example}
Comparison of two implementations of the $\partial$ operator. Notice the difference between the penultimate rows. In particular, the penultimate row of the matrix generated by \texttt{larBoundary(FV,EV)} is plain wrong. It means that the edge $e_{10}$ is shared by all the (three) 2-cells of the complex. Conversely, it is well known that, for a solid complex, i.e.~a $d$-complex embedded in $\mathbb{E}^d$, every $(d-1)$-facet may be shared by no more than 2 $d$-cells. The resulting boundary of the total chain $[f_0, f_1, f_2]$ codified in coordinates as $[1,1,1]$, and shown in Figure~\ref{fig:boundary-test02}d, is sonsequently incorrect.
\\[3mm]

%-------------------------------------------------------------------------------
{\scriptsize
\begin{minipage}[c]{0.5\linewidth}
\centering
\begin{verbatim}
In [1]: larBoundary(FV,EV).todense()
Out[1]:
matrix([[0, 1, 0],
        [0, 0, 1],
        [1, 0, 1],
        [1, 0, 1],
        [0, 1, 1],
        [0, 1, 0],
        [1, 0, 1],
        [0, 0, 1],
        [0, 0, 1],
        [0, 1, 0],
        [1, 1, 1],
        [0, 1, 1]])
\end{verbatim}
\end{minipage}
\begin{minipage}[c]{0.5\linewidth}
\centering
\begin{verbatim}
In [2]: larUnsignedBoundary2(FV,EV,VV).todense()
Out[2]:
matrix([[0, 1, 0],
        [0, 0, 1],
        [1, 0, 1],
        [1, 0, 1],
        [0, 1, 1],
        [0, 1, 0],
        [1, 0, 1],
        [0, 0, 1],
        [0, 0, 1],
        [0, 1, 0],
        [1, 1, 0],
        [0, 1, 1]])
\end{verbatim}
\end{minipage}}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-1}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-2}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-3}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-4}

   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-1}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-2}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-3}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test02-5}
   \caption{Non-working (i.e.~\emph{wrong}) example with \texttt{boundary}. (a) Indexing of 0-,1-,and 2-cells; (b) boundary of a singleton 2-chain; (c) exploded 2-cells; (d) boundary of a singleton 2-chain. Working (i.e.~\emph{exact}) example using \texttt{larUnsignedBoundary2}: (e--h) as above.}
   \label{fig:boundary-test02}
\end{figure}

\paragraph{3D non-convex LAR cells}
In this example and in the next one we show the boundary computation of LAR models with non-contractible 3- and 2-cells.

%-------------------------------------------------------------------------------
@O test/py/boundary/test03.py
@{""" 3D non-convex LAR cells """
from larlib import *

V = [[0.25,0.25,0.0],[0.25,0.75,0.0],[0.75,0.75,0.0],[0.75,0.25,0.0],[1.0, 0.0,0.0],
[0.0,0.0,0.0],[1.0,1.0,0.0],[0.0,1.0,0.0],[0.25,0.25,1.0],[0.25, 0.25,2.0],[0.25,0.75,
2.0],[0.25,0.75,1.0],[0.25,0.75,-1.0],[0.25,0.25, -1.0],[0.75,0.75,-1.0],[0.75,0.25,
-1.0],[0.75,0.25,1.0],[0.75,0.75,1.0], [1.0,0.0,1.0],[0.0,0.0,1.0],[1.0,1.0,1.0],
[0.0,1.0,1.0],[0.75,0.75,2.0],[0.75,0.25,2.0]]

CV = [(0,1,2,3,4,5,6,7,8,11,16,17,18,19,20,21), (0,1,2,3,8,11,16,17),
(0,1,2,3,12,13,14,15), (8,9,10,11,16,17,22,23)]

FV = [(2,3,16,17),(6,7,20,21),(12,13,14,15),(0,1,8,11),(1,2,11,17),(0,1,12,13),
(4,6,18,20),(5,7,19,21),(0,3,13,15),(0,3,8,16),(0,1,2,3),
(10,11,17,22),(2,3,14,15),(8,9,16,23),(8,11,16,17),
(1,2,12,14),(16,17,22,23),(4,5,18,19),(8,9,10,11),(
9,10,22,23),(0,1,2,3,4,5,6,7),(8, 11,16,17,18,19,20,21)]

EV =[(3,15),(7,21),(10,11),(4,18),(12,13),(5,19),(8,9),(18,19),(22,23),(0,3),(1,11),
(16,17),(0,8),(6,7),(20,21),(3,16),(10,22),(18,20),(19,21),(1,2),(12,14),(4,5),(
8,11),(13,15),(16,23),(14,15),(11,17),(17,22),(2,14),(2,17),(0,1),(9,10),(8,16),
(4,6),(1,12),(5,7),(0,13),( 9,23),(6,20),(2,3)]

VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV,CV],hpc,0.6))

BF = boundary3Cells(CV,FV,EV)
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,[FV[f] for f in BF],EV),color=True)))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.495\linewidth,width=0.495\linewidth]{images/boundary-test03-1}
   \includegraphics[height=0.495\linewidth,width=0.495\linewidth]{images/boundary-test03-2}
   \caption{Non-convex 3-complex. (a) Indexing of 0-,1-,2- and 3-cells; (b) exploded 2-boundary cells.
   Notice that two faces are multiply-connected.}
   \label{fig:boundary-test03}
\end{figure}

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test04-1}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test04-2}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test03-4}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/boundary-test03-5}
   \caption{Non-convex 3-complex. (a) Indexing of 0-,1-,2- and 3-cells; (b) exploded 2-boundary cells ---notice a drawing error on the back of the model---conversely, the data structures involved are correct, as shown by the two following pictures;
   (c) solid drawing of the 2-chain \texttt{[FV[29],FV[30]]}; (d) triangulation of the same 2-chain.}
   \label{fig:boundary-test04}
\end{figure}

\paragraph{3D non-convex LAR cells}
In this example the 3D model is constructed partly in automated way, partly by hand.
In particular, first we generate a structure of cuboidal complexes, then we transform it is a single complex using part of the computational pipeline being developed for the Boolean arrangments of complexes, so that all the included cells are mutually fragmented. Then the 3-cells are assembed as sets of 2-faces, giving the \texttt{CF} (cells-by-faces) variable. Finally this one is transformed automatically into \texttt{CV} (cells-by-vertices).

%-------------------------------------------------------------------------------
@O test/py/boundary/test04.py
@{""" 3D non-convex LAR cells """
from larlib import *
@< Input of a cellular 3-complex @>
@< Visualization of a 2-chain of a 3-complex @>
@< Visualization of a 3-chain of a 3-complex @>
@}
%-------------------------------------------------------------------------------

\paragraph{Input of a cellular 3-complex}
%-------------------------------------------------------------------------------
@D Input of a cellular 3-complex
@{""" Input of a cellular 3-complex """
V,[VV,EV,FV,CV] = larCuboids([2,1,1],True)
struct = Struct([(V,FV,EV),t(.25,.25,0),s(.25,.5,2),(V,FV,EV)])

V,FV,EV = struct2Marshal(struct)
CF = AA(sorted)([[20,12,21,5,19,6],[27,1,5,28,13,23],[12,14,25,17,10,4],
[1,7,17,24,11,18],[30,29,26,16,8,22,10,11,4,18,24,25],[2,3,8,9,0,15]])
CV = [list(set(CAT([FV[f]  for f in faces]))) for faces in CF]

VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV,CV],hpc,0.6))
@}
%-------------------------------------------------------------------------------

\paragraph{Visualization of a 2-chain of a 3-complex}
%-------------------------------------------------------------------------------
@D Visualization of a 2-chain of a 3-complex
@{""" Visualization of the boundary 2-chain of a 3-complex """

"""
V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)(len(CV)*[1])
VIEW(STRUCT(MKTRIANGLES((V,BF,EV),color=True)))
VIEW(SKEL_1(STRUCT(MKTRIANGLES((V,BF,EV)) )))

boundaryEdges = chain2BoundaryChain(larUnsignedBoundary2(FV,EV,VV))
edgeChain = boundaryEdges(29*[0]+[1]+[1])
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,FV[29:31],[EV[e] for e in edgeChain]),color=True)))
VIEW(SKEL_1(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,FV[29:31],[EV[e] for e in edgeChain])))))
"""
@}
%-------------------------------------------------------------------------------

\paragraph{Visualization of a 3-chain of a 3-complex}
%-------------------------------------------------------------------------------
@D Visualization of a 3-chain of a 3-complex
@{""" Visualization of a 3-chain of a 3-complex """

print "\n****** ECCOMI"
V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([0,0,0,0,1,1])
VIEW(STRUCT(MKTRIANGLES((V,BF,BE))))
VIEW(SKEL_1(STRUCT(MKTRIANGLES((V,BF,BE)) )))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/boundary/test05.py
@{""" Boundary of a 3-complex """
from larlib import *

V,[VV,EV,FV,CV] = larCuboids([1,1,1],True)
cube = Struct([ (V,FV,EV) ])
assembly = Struct([ cube, Struct([t(0,.5,0), r(PI/4,0,0), s(.5,.5,.5),cube]) ])

V,FV,EV = struct2Marshal(assembly)
VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],hpc,0.6))

CF = [[1,2,3,4,6,7],[0,1,2,3,4,5,6,7,8,9,10,11]]
CV = [list(set(CAT([FV[f]  for f in faces]))) for faces in CF]

V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([0,1])
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,BE),color=True)))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/boundary/test06.py
@{""" Boundary of a 3-complex """
from larlib import *

V,[VV,EV,FV,CV] = larCuboids([1,1,1],True)
cube = Struct([ (V,FV,EV) ])
hole = Struct([t(0,.5,0), r(PI/4,0,0), s(.5,.5,.5),cube])
assembly = Struct([ cube, hole, t(0,0,SQRT(0.5)), hole ])

V,FV,EV = struct2Marshal(assembly) # WRONG:  TODO: check ...
VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[[],[],FV],hpc,0.6))

CF = [[4,5,7,16,17,19,20],[3,8,6,12,11,13],[0,1,10,20],[]]
CV = [list(set(CAT([FV[f]  for f in faces]))) for faces in CF]

V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([0,1,1,0])
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,BE)))) # ERROR in MKTRIANGLES with non-manifold face
VIEW(EXPLODE(1.2,1.2,1.2)(MKFACES((V,BF,EV))))
VIEW(SKEL_1(EXPLODE(1.2,1.2,1.2)(MKFACES((V,BF,EV)))))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/boundary/test07.py
@{""" Boundary of a 3-complex """
from larlib import *

V,[VV,EV,FV,CV] = larCuboids([1,1,1],True)
cube = Struct([ (V,FV,EV) ])
hole = Struct([t(0,.5,0), r(PI/4,0,0), s(1,.5/SQRT(2),.5/SQRT(2)),cube])
assembly = Struct([ cube, hole ])

V,FV,EV = struct2Marshal(assembly) # WRONG:  TODO: check ...
VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],hpc,0.6))

CF = [[1,3,6,7,12,11],[0,2,4,5,9,8]]
CV = [list(set(CAT([FV[f]  for f in faces]))) for faces in CF]

V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([1,0])
VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,EV),color=True)))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/boundary/test08.py
@{""" Boundary of a 3-complex """
from larlib import *

V,[VV,EV,FV,CV] = larCuboids([1,1,1],True)
cube = Struct([ (V,FV,EV) ])
hole = Struct([t(0,.5,0), r(PI/4,0,0), s(1,.5/SQRT(2),.5/SQRT(2)),cube])
assembly = Struct([ cube, hole ])
assembly2 = Struct([ assembly, t(0,0,.5), s(0.5,1,1), hole ])

V,FV,EV = struct2Marshal(assembly2)
VV = AA(LIST)(range(len(V)))
hpc = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],hpc,0.7))

#CF = [[1,3,6,14,17,18,19, 0,4,9,11,15,16, 2,5,7,8,10,13],[0,4,9,11,15,16],[2,5,7,8,10,13]]
CF = [[16,9,11,0,15,4],[10,12,7,2,17,15,9,5,18,8,16,3,6,14,19,4,1],[5,13,7,10,8,2]]
CV = [list(set(CAT([FV[f]  for f in faces]))) for faces in CF]

n = len(CV)
for k in range(n):
    V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)(IDNT(n)[k])
    VIEW(STRUCT(MKTRIANGLES((V,BF,BE),color=True)))
    VIEW(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,BE),color=True)))
    VIEW(SKEL_1(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,BE)))))
V,BF,BE = larUnsignedBoundary3(V,CV,FV,EV)([1,1,1])
VIEW(SKEL_1(EXPLODE(1.2,1.2,1.2)(MKTRIANGLES((V,BF,BE)))))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/topos1}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/topos2}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/topos3}
   \includegraphics[height=0.245\linewidth,width=0.245\linewidth]{images/topos4}
   \caption{Decomposition of the unit 3-cube in a cellular 3-complex with three 3-cells. Two 3-cells are homeomorphic to the 3-ball, while the remaining one is homeomorphic to the 3-torus.
Notice that one of 2-cells (as well one of 3-cells) are non-contractible and non-manifold, as well as non-convex:
   (a) Indexing of 2-faces of the 3-complex; (b) drawing of the (boundary of) non-convex 3-cell;
   (c) exploded drawing of the (boundary of) non-convex 3-cell; (d) triangulation of its 2-faces.
   The triangulation of LAR 2-faces is needed in order to draw them solidly.}
   \label{fig:boundary-test04}
\end{figure}

\appendix
\section{Utilities}

\paragraph{Marshalling a structure to a LAR cellular model}
The function \texttt{struct2Marshal} transforms a \texttt{Struct} object, often used to
define some assembly of simpler models, to a correctly defined LAR cellular model, i.e.~to
a cellular partition of the space, in other words a quasi-disjoint partition of the object into well-glued cells of suitable dimensions.

%-------------------------------------------------------------------------------
@D Marshalling a structure to a LAR cellular model
@{""" Marshalling a structure to a LAR cellular model """
import boolean,inters

def struct2Marshal(struct):
    W,FW,EW = struct2lar(struct)
    quadArray = [[W[v] for v in face] for face in FW]
    parts = boolean.boxBuckets3d(boolean.containmentBoxes(quadArray))
    Z,FZ,EZ = boolean.spacePartition(W,FW,EW, parts)
    V,FV,EV = inters.larSimplify((Z,FZ,EZ),radius=0.001)
    return V,FV,EV
@}
%-------------------------------------------------------------------------------

\paragraph{Boundary of a 3-complex}
%-------------------------------------------------------------------------------
@D Boundary of a 3-complex
@{""" Boundary of a 3-complex """
import larcc
"""  WHY wrong ????  TOCHECK !!
def larUnsignedBoundary3(V,CV,FV,EV):
    VV = AA(LIST)(range(len(V)))
    operator3 = larcc.chain2BoundaryChain(boundary3(CV,FV,EV))
    operator2 = larcc.chain2BoundaryChain(larUnsignedBoundary2(FV,EV,VV))
    def larUnsignedBoundary30(chain):
        BF = operator3(chain)
        faceCoords = len(FV)*[0]
        for f in BF: faceCoords[f] = 1
        BE = operator2(faceCoords)
        return V,[FV[f] for f in BF],[EV[e] for e in BE]
    return larUnsignedBoundary30
"""
def larUnsignedBoundary3(V,CV,FV,EV):
    VV = AA(LIST)(range(len(V)))
    operator3 = larcc.chain2BoundaryChain(boundary3(CV,FV,EV))
    operator2 = larcc.chain2BoundaryChain(larUnsignedBoundary2(FV,EV,VV))
    def larUnsignedBoundary30(chain):
        BF = operator3(chain)
        BE = set()
        for f in BF:
            faceCoords = len(FV)*[0]
            faceCoords[f] = 1
            BE = BE.union(operator2(faceCoords))
        return V,[FV[f] for f in BF],[EV[e] for e in BE]
    return larUnsignedBoundary30
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[width=0.5\linewidth]{images/edgecycle}
   \caption{The oriented boundary 1-cycle of a partial 3-cell extraction from a 2-complex in 3D.}
   \label{fig:edgecycle}
\end{figure}

\bibliographystyle{amsalpha}
\bibliography{boundary}

\end{document}


\documentclass{article}
\usepackage{graphicx}
\usepackage{amsmath}
%\usepackage[scientific-notation=true]{siunitx}
\usepackage{tabularx}
\newcommand{\D}{\displaystyle}
\begin{document}

\title{Inferring Characteristics of Interaction Matrices in an Ecological Context{}}
\author{Naika Dorilas\\\\{Santa Fe Institute}}

\maketitle

\begin{abstract}
In ecology, an interaction matrix describes how species in an ecosystem interact with one another and affect each others growth in a given model of population growth. In an attempt to find a method for inferring species interactions, many ecologists have tried to go from time series data on the populations of species to inferring the entire interaction matrix. In this paper, the objective is to infer parameters of the interaction matrix, given a set of data, so instead of inferring the entire matrix, we just want 3 key statistical properties about how the entries are drawn, the mean $\mu$, variance $\sigma$ and average diagonal elements d. So based on a specified ecosystem we are trying to find a method of inferring the statistical properties of the interaction matrix between different species based on a simple model of population fluctuation. We will use maximum likelihood, to predict the probability of observing our data, x given $\mu, \sigma, d$. So what we expect from this maximization are the $\mu,\sigma,d$ that make the data, or fluctuations in population sizes of the species the most likely. The implications of this are that assuming this method is successful, any randomly generated matrix with the given statistical properties found could be used to describe how species in the data set used interact.
\end{abstract}

\section{Background}

\subsection{What is random matrix theory?}
\hfill\break
Random Matrix Theory is a combination of statistics and traditional matrix theory. In this field, many tools from statitistics are used to describe matrices with random elements instead of relying on those individual elements. It allows us to generalize about certain characteristics of mtrices with similar statistical properties. Many problems in physical systems modeling and biological systems modeling involve matrices with random entries. \hfill\break

Random matrix theory has some great uses for the context of this project. Traditionally in one-dimensional models of population growth, specifically Lotka Volterra there are birth rates $r_b$, death rates $r_d$, and a carrying capacity, K.  \hfill\break
\hfill\break
$$
N(t+\Delta t)=N(t)+\Delta t (r_b-r_d)N(t)(1-\dfrac{N(t)}{K})
$$
\hfill\break \hfill\break
Although, if we want to include the effects of other species on a single species, in ecological models of population growth across species we need to include something called an interaction matrix. It describes the way that different species interact with each other and effect eachothers survivial whether it be positively, negatively or with no effect at all. If we look at the equilibrium solutions-which tells us about stability of systems-and take them in smal perturbations, we get this linearized model of population dynamics \hfill\break
\hfill\break
\begin{equation}
y_i(t+\Delta t)=y_i(t) + \Delta t(A_{ij}y_i +\xi_i)
\end{equation}

\hfill\break
where $y_i(t)$ is the population of species i at time t, $\xi_i$ is random noise that might affect a species growth, and $A_{ij}$ is the matrix that describes the interactions between the species.
\hfill\break
If we subtract both sides by $y_i(t)$, divide by $\Delta t$ then allow $\Delta t \rightarrow 0$ then we obtain \hfill\break
$$\dfrac{\partial y_i}{\partial t}=A_{ij}y_i$$
we also dropped the random noise variable in order to illustrate species interactions simply.
\subsection{Examples of Interaction Matrices}

An example interaction matrix is illustrated below.

$$
\begin{bmatrix}
x_{11}&x_{12} \\
x_{21}&x_{22}
\end{bmatrix}
$$
\hfill\break \hfill\break
Here we have a small ecosystem of just 2 species for simplicity. In this case the model for population size of species i can be expanded to,
\hfill\break
\hfill\break
\begin{equation}
\begin{cases}
\dfrac{dy_1}{dt}=x_{11}y_1+x_{12}y_2\\\\
\dfrac{dy_2}{dt}=x_{21}y_1+x_{22}y_2\\\\
\end{cases}
\end{equation}
\hfill\break
\hfill\break
Now we will explore a couple of different cases of what could happen when two species interact with eachother and what this looks like in terms of the interaction matrix and the model.
\hfill\break
\hfill\break
\textbf{Example 1:}\hfill\break
\hfill\break
We could have a situation where the interaction matrix looks as such \hfill\break
$$
\begin{bmatrix}
x_{11}&0 \\
0&x_{22}
\end{bmatrix}
$$
In this case, the off diagonal elements are equal to 0, if we expand model (1) for this interaction matrix we get:
\begin{equation}
\begin{cases}
\dfrac{dy_1}{dt}=x_{11}y_1\\\\
\dfrac{dy_2}{dt}=x_{22}y_2\\\\
\end{cases}
\end{equation}
Now we can see that the population of species 2 does not appear in the dynamics for species one and vice versa meaning the species are not interacting at all.\hfill\break\hfill\break\hfill\break
\textbf{Example 2:} \hfill\break\hfill\break
We could also have a case where the interaction matrix looks like this:
$$
\begin{bmatrix}
x_{11}&0 \\
x_{21}&x_{22}
\end{bmatrix}
$$
In this case if we exapand the equations in model (1) we would get something like this:
\begin{equation}
\begin{cases}
\dfrac{dy_1}{dt}=x_{11}y_1\\\\
\dfrac{dy_2}{dt}=x_{21}y1+x_{22}y_2\\\\
\end{cases}
\end{equation}
meaning that species 2 has no effect on the population dynamics for species 1 but species 1 is postively benifiting the populaiton of species 2. This could happen in a case of commensalism where species 1 is not being harmed or helped by species 2 but species 2 is gaining something from interacting with species 1.
\hfill\break\hfill\break\hfill\break

\textbf{Example 3:} \hfill\break\hfill\break
In this case we have an interaction matrix that looks like this

$$
\begin{bmatrix}
x_{11}&-x_{12} \\
x_{21}&x_{22}
\end{bmatrix}
$$
\hfill\break
and if we expand model (1) we have something that looks like this:
\begin{equation}
\begin{cases}
\dfrac{dy_1}{dt}=x_{11}y_1\\\\
\dfrac{dy_2}{dt}=x_{21}y_1+x_{22}y_2\\\\
\end{cases}
\end{equation}
This shows us that species 2 is having a negative effect on the dynamics of species one and that species one is having a positive effect on the dynamics of species 2. An instance where this could happen is if there is a parasitic relationship between the two species or predation.
\hfill\break
\subsection{The Need For Larger Matrices}
\hfill\break
Now this is what happens in a two-dimensional case, if we make the interaction matrix larger, the same kinds of patterns for different entries follow.\hfill\break
$$
\begin{bmatrix}
   x_{11} & x_{12} & x_{13} & \dots &x_{1, 100}&\dots & x_{1n} \\
    x_{21} & x_{22} & x_{23} & \dots &x_{2,100}&\dots & x_{2n} \\
    \vdots & \vdots & \vdots & \ddots & \vdots &\vdots&\vdots \\
x_{100,1}&x_{100,2}&x_{100,3} &\dots & x_{100,100}&\dots& x_{100,n}\\
\vdots & \vdots& \vdots& \vdots& \vdots &\ddots&\vdots \\
    x_{n1} & x_{n2} & x_{n3} & \dots &x_{n,100}&\dots & x_{nn}
\end{bmatrix}
$$\hfill\break
In biological systems many aspects of the environment and growth process are random, large and can vary over space and time. For higher dimension interaction cases, the exact entries of the matrix matter less than certain aspects about the distribution of their entries such as the mean $\mu$, variance $\sigma$ and diagonal elements d. Random Matrix Theory(RMT) allows us to understand the stability of an ecosystem through looking at large scale properties of the matrix which we often refer to as an interaction matrix A. We can determine when a system will be stable based on these properties because we have results from RMT that for instance tell us about the distribution of eigenvalues for random matrices with similar statistical properties. Eigenvalues, tell us about the stability of our equilibrium solutions: whether or not starting close to that equilibrium will result in staying close to that equlibrium or diverging. In Ecology that tells us about a species survival. It would give researchers alot of insight if they were able to get basic aspects of matrices that allow for a stable ecosystem in a given population.   \hfill\break

In this project we start with a stable symmetrical matrix for which there are many useful properties from Random Matrix Theory. Given a set of data and our simple population model (1), our goal was to infer paramaters:$\mu,\sigma,d$ of a random interaction matrix A that would best fit the data. What this means is that based on an arbitrary real world data set of populations of different species across time, we hoped to infer the statistics of how the species in that data set interact with eachother.

\section{Methods}
\subsection{Maximum Likelihood}
\hfill\break
So again, given time series data on poulation fluctuaton for S different species and our simple population model (1), our goal was to infer paramaters:$\mu,\sigma,d$ of a random interaction matrix A that would best fit the data. to do that we needed to maximize $P(x|\mu,\sigma,d)$ where x represents discrete data points for each species, particularly N of them. Given a statistical model-$f(x)$ and parameters-$p_i:p_1,p_2,...,p_n$,  $P(x|\mu,\sigma,d)$ is the likelihood of observing the model input x given the parameters p1:pn. Then we maximize this likelihood so our output from maximum likelihood becomes the parameter values:$p_i$ that make the x, the most probable. In the context of this project, x is the data of population dynamics of S different speices. We also have paramteres $p_i={\mu,\sigma,d}$ which describe the statistical properties of a random interaction matrix, and the output from maximum likelihood gives us the $p_i$ which makes the population fluctuations most likely to happen. So it optimizes $p_i$ by finding the parameters $p_i$ of a random interaction matrix which make those interactions the most likely to produce the fluctuations at each time step for S species: $x^a$, where a is the index for the number of data points drawn from each species.
\hfill\break\hfill\break
In this paper we assume that each discrete data point, $x^a$ from the an arbitrary time series are independent. Therefore the average probability of observing the data points for one species ,$x^a$ given our parameters, $p_i$ for each species 1:S is just the multiplication of these probabilities \hfill\break\hfill\break $P(x_i^1|p_i)\times P(x_i^2|p_i) \times \dots \times P(x^a|p_i)\times \dots \times P(x_i^N|p_i)$
\begin{equation}
P(x|\mu,\sigma,d)=\int dA \prod_{a=1}^N P(x_i^a|A)\times P(A|\mu,\sigma,d)
\end{equation}
\hfill\break where N is the number of data points we collect for each species.
\hfill\break\hfill\break Then we assume 3 things
\hfill\break\hfill\break
1). $A_{ij}=\dfrac{\mu}{S} + B_{ij}, B_{ij}~N(0,\dfrac{\sigma^2}{S}\leftarrow A_{ij}~N(\dfrac{\mu}{S},\dfrac{\sigma^2}{S})$ \hfill\break
2). $A_{ii}=-d+\dfrac{\mu}{S}$ \hfill\break
3). $\dfrac{1}{S}\overline{logD}=\dfrac{1}{S}(log(d+\mu)+(S-1)\int d\lambda \dfrac{\sqrt{4\sigma^2-(\lambda+d)^2}}{2\pi\sigma}\times log\lambda$ \hfill\break\hfill\break
So that the parameters $\mu, \sigma, d$ can be solved for, we one assume that the off diagonal elements of A are drawn from a normal distribution of mean $\mu$ and variance $\sigma^2$, both sized down by S, and two assume that the diagonal elements of A are $-d+\dfrac{\mu}{S}$\hfill\break
We will justify why we do this below, but the determinants for large matrices are very similar, so to simplify our calculation we take the average determinant of A. The determinant of a matrix is given by the multiplication of eigenvalues. So the third assumption comes from the semircular law in Random Matrix Theory by physicicst Eugene Wigner in 1955. The distribution of eigenvalues for a symmetric matrix A whose entries were generated randomly and independently by a given distribution with mean:$ \mu$, variance: $\sigma$ and average diagonal elements: d, lie on a semicircle centered at d with diameter $2\sigma$. The distribution of eigenvalues therefore comes from the formula \hfill\break
$$
\dfrac{\sqrt{4\sigma^2-(\lambda+d)^2}}{2\pi\sigma}
$$
\hfill\break
\includegraphics[scale=0.5]{Picture2} \cite{one}

\hfill\break\hfill\break

Now based on some of these assumptions
$$
P(x|A)=\dfrac{(det(A))^{1/2}}{(2\pi)^{S/2}} exp(\dfrac{1}{2}\sum_{a=1}^N\sum_{ij}^S x_i^aA_{ij}x_j^a)
$$

We can then expand the likelihood equation to be
$$
P(x|\mu,\sigma,d)=\int \prod_{i<j}^N(dA_{ij})\dfrac{(det(A))^{1/2}}{(2\pi)^{S/2}} exp(\dfrac{1}{2}\sum_{a=1}^N\sum_{ij}^S x_i^aA_{ij}x_j^a)\times P(A|\mu,\sigma,d)
$$
Since A is a symmetric $S\times S$ matrix for our purposes, then we only need to integrate over the upper right half of A. Then we just needed to multiply the $P(x|\mu,\sigma,d)$ for each $a \in$ [1,N]. \hfill\break \hfill\break So then after including our assumptions, since we are taking the average determinant of A we replace that term with D
\hfill\break
\begin{equation}
\dfrac{2}{N}logP=logD-\dfrac{d}{N}\sum_{a}\sum_i (x_i^a)^2 +\dfrac{1}{SN}\sum_{a}(\sum_i x_i^a)^2+\dfrac{1}{2SN}\sum_{ab}(\sum_i x_i^a x_i^b)^2
\end{equation}
gives us the simplified version of our log likelihood equations.
\hfill\break
Then we had to maximize this likelihood to obtain parameters $\mu,\sigma,d$. So we took the partial derivates with respect to each variable of the log likelihood and set them equal to 0.
\hfill\break\hfill\break
$\dfrac{\partial logP}{\partial \mu}=0$,
$\dfrac{\partial logP}{\partial \sigma}=0$,
$\dfrac{\partial logP}{\partial d}=0$
\hfill\break
These equations based on the log likelihood can be written in the following form:
\begin{equation}
\begin{cases}
\dfrac{\partial D}{\partial \mu} \dfrac{1}{D}=-\dfrac{1}{SN}\sum_{a}(\sum_i x_i^a)^2 \\\\
\dfrac{\partial D}{\partial \sigma^2} \dfrac{1}{D}=-\dfrac{1}{2SN}\sum_{ab}(\sum_i x_i^a x_i^b)^2 \\\\
\dfrac{\partial D}{\partial d} \dfrac{1}{D}=\dfrac{1}{N}\sum_{a}\sum_i (x_i^a)^2 \\\\
\end{cases}
\end{equation}
Solving these systems of equations for $\mu,\sigma, d$ is the last step in completing this method.
\subsection{Simulating Data}\hfill\break
To ensure that our calculations were correct and that this method was valid we generated data from a multivariate normal distribution,
$$P(x_i^a| A)=\dfrac{\sqrt{det(A)}^{N/2}}{2\pi^{NS/2}} exp(\dfrac{1}{2}\sum_{a=1}^N\sum_{ij}^S x_i^aA_{ij}x_j^a)$$ \hfill\break
Doing this, we assume X comes from discrete data points from each of S species. To make sure this method for inferring parameters is valid, we wanted to make sure it produces similar predictions for $\mu,\sigma,d$, as the $\mu,\sigma,d$ we gave to the simulation and used to generate the data. Given that our assumption of X is that it will come from this exact kind of distribution, our predicted values should closely match the actual values given to the simulation. An example of the time series data that we might take from each species is given in Figure 1. Where instead of taking all the data, we look at discrete time steps.
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\begin{figure}
\includegraphics[scale=0.6]{Popf}
\end{figure}
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\hfill\break
\section{Results}
\subsection{Validation of Methods}
To make sure his method was valid and can be applied to other uncorrelated data, we graphed the simulated log determinants vs the analytical log determinants , the Rhs vs Lhs of the maximization equations and the output our optimization function for different $\mu,\sigma,d$. What we wanted is \hfill\break\hfill\break 1) That the average log determinants of matrices made from different $\mu,\sigma,d$, to be close to the log determinants calculated from the semicircular law for those same $\mu,\sigma,d$. \hfill\break\hfill\break 2). We wanted the Lhs of the optimization equations that depend on $\mu,\sigma,d$ and the Rhs that depend on the data X, for different parameters that generate both sides to also be very close so that
$\dfrac{\partial logP}{\partial \mu,\sigma,d}=Lhs-Rhs$=0. This is neccessary to be able to optimize for our parameters. \hfill\break\hfill\break 3). We wanted to see that the output for $\dfrac{\partial logP}{\partial\mu,\sigma,d}$ was equal to 0 at some point or else there would be no root and therefore no optimal $\mu,\sigma,d$. \hfill\break\hfill\break According to the following figures, 1), 2)., 3). were achieved.
\hfill\break
\hfill\break
1)\hfill\break
\includegraphics[scale=0.4]{LD}\hfill\break
2)\hfill\break
\includegraphics[scale=0.4]{rlmu}
\includegraphics[scale=0.4]{rld}
\includegraphics[scale=0.4]{rlsigma} \hfill\break
3)\hfill\break
\includegraphics[scale=0.4]{OPmu}
\includegraphics[scale=0.4]{OPsigma}
\includegraphics[scale=0.4]{OPd}

\subsection{Predicted output parameters vs actual parameters}\hfill\break
\hfill\break
As a result of technical difficulties for this project in terms of gaining valus for our estimations, we only plot The predicted values we obtained for d in comparison to the actual values for a number of iterations.
\hfill\break
\includegraphics[scale=0.5]{Picture1}
%\begin{equation}
%\begin{cases}
%\dfrac{dT}{dt}=-\beta V T\\\\
%\dfrac{dI_1}{dt}=\beta V T- kI_1\\\\
%\dfrac{dI_2}{dt}= kI_1- \delta I_2\\\\
%\dfrac{dV}{dt}=\pi I_2- c V\\\\
%\end{cases}
%\end{equation}
%\hfill\break
\hfill\break
%\hfill\break
%\begin{table}
%\caption{Predicted Values of $\mu,\sigma,d$ in Comparison to the Actual Values of $\mu,\sigma,d$}
%\centering
%\begin{tabular}{lll}
%\hline
%Variable  & Predicted Value &Actual Value\\ [0.5ex]
%\hline
%\\
%&  &  $\D\frac{\mbox{}}{}$ \\ [0.5ex]
%&  &  $\D\frac{\mbox{}}{}$ \\ [0.5ex]
%& &$\D\frac{\mbox{}}{}$ \\[0.5ex]
%& &  $\D\frac{\mbox{}}{}$  \\ [0.5ex]
%
%\hline
%\end{tabular}
%\label{table:variables}
%\end{table}
%\hfill\break

\section{Discussion}
The impact of doing this method successfully is that hopefully we will be able to determine the key aspects of interaction given a specific data set and not have to infer an exact matrix. So we would be able to say that any random interaction matrix with those parameters $\mu, \sigma$ and d would be able to describe how the species in that given data set interact. I would soon like to see that this method still holds for $\mu, \sigma$ since d was the only estimation that currently works. Also, in the future I would like to use real world data sets of different species, and maybe even try multiple data sets and see how different types of data fare under this method.

\hfill\break

\section{Aknowledgements}
I would like to thank my mentors Dr. Andy Rominger and Dr. Jacopo Grilli for their support, patience and guidance throughout my project.

\begin{thebibliography}{999}

\bibitem{one} Wigner's Semicircle Law. (n.d.). Retrieved from http://mathworld.wolfram.com/WignersSemicircleLaw.html

%On top of that, the stability of a biological system is very pertinent. In an ecological context it determines the survival of species. Generally we look at the "community matrix", which for a population of S species is influenced by S equations for population fluctuation. The community matrix looks at equilibrium solutions for these equations in small perturbations around the equilibria. We say the system is stable if when starting close to an equilibrium we stay close to that equilibria. Local stability can be determined by the eigenvalues of the matrix M.

\end{thebibliography}
\end{document}