\section{Medidas de complexidade}

\emph{Complexidade concreta de algoritmos}\footnote{
Termo introduzido por Knuth, veja artigo \emph{Mathematical Analysis of
Algorithms} em \cite{dek:spaa}.} 
refere-se
\`a avalia\cao\ da quantidade de recuros demandados por um algoritmo para
resolver um problema. Por recursos gastos pode-se entender:
\begin{itemize}
	\item n\uu mero de processadores;
	\item mem\oo ria;
	\item tempo.
\end{itemize}

Qualquer dessas medidas pode se revelar inadequada se adotada de forma
estrita.
Por exemplo, mem\oo ria poderia ser medida em palavras, mas o tamanho da
palavra dos computadores varia com o fabricante e a gera\cao\ do processador.
O mesmo vale para tempo: avalia\coes\ de tempo em rel\oo gio s\ao\ inadequadas
porque o n\uu mero de instru\coes\ executadas em um segundo por um processador
muda todos os anos. Compara\coes\  de desempenho de programas s\oo\
fazem sentido em experimentos em que o ambiente, incluindo m\aa quina e dados
usados, est\ao\ muito bem definidos e controlados e, na verdade, s\oo\ fazem
sentido quando o estado da arte da \emph{An\aa lise de Algoritmos} n\ao\
permite an\aa lise mais detalhada dos algoritmos em estudo. \footnote{
Na maioria dos
casos, estudos de programas para avalia\cao\ de desempenho revelam
incompet\^encia inerente do \emph{experimentador}.}
Consequentemente, medidas mais abstratas de complexidade s\ao\ usadas. Por
exemplo, para avaliar a complexidade de tempo de algoritmo \ee\ usual
considerar: n\uu mero de transi\coes\ executadas, n\uu mero de chamadas
recursivas, n\uu mero de compara\coes ou opera\coes\ aritm\ee ticas, etc.

Por outro lado, \ee\ importante considerar, estando definida, por exemplo, a
medida de tempo usar, que um algoritmo $A$ pode demandar tempos
complemente diferentes quando usado para conjuntos de dados diferentes, mesmo
que esses conjuntos tenham o mesmo n\uu mero de elementos. Um algoritmo pode,
por exemplo, demandar mil compara\coes\ de itens para ordenar um conjunto de
mil inteiros e demandar um milh\ao\ de compara\coes\ para um outro conjunto
de mil inteiros. A an\aa lise de complexidade lida ao menos com a avalia\cao\
dos seguintes casos:
\begin{itemize}
	\item \textbf{melhor caso:} qual \ee\ o melhor desempenho do algoritmo
		para um conjunto de dados de tamanho $n$ e que 
		caracter\ii sticas desse conjunto determinam tal desempenho;
	\item \textbf{pior desempenho:} qual \ee\ o pior desempenho poss\ii
		vel do algoritmo.
	\item \textbf{caso m\ee dio:} qual \ee\ o desempenho m\ee dio quando 
		consideradas todas as distribui\coes\ \emph{prov\aa veis} dos
		poss\ii veis conjuntos de dados a usar.
\end{itemize}

Considere o programa em Haskell da figura \ref{seqsum}.
\begin{figure}
	\begin{center}
	\lstinputlisting{seqsum.hs}	
	\end{center}
	\caption{Soma de elementos de uma \sqn}
	\label{seqsum}
\end{figure}

Se medirmos o tempo desse programa por chamadas recursivas para uma entrada
com $n$ itens obtemos as equa\coes:
\begin{gather*}
	T(0) = 0
	T(n+1) = 1+T(n)
\end{gather*}

Parece \oo bvio verificar que esse sistema de equa\coes\footnote{
Chamado recorrente por causa da ocorr\^encia de $T(n)$ na equa\cao\ que d\aa\
o valor de $T(n+1)$.}
na verdade representa a somat\oo ria
\[ \sum_{\lele 1in} 1\]
dando o valor de $T(n) = n$. 

\begin{ex}
	Verifica o resultado da recorr\^encia usando indu\cao. 
\end{ex}

Note tamb\ee m que:
\begin{itemize}
	\item Esse algoritmo executa a cada chamada recursiva: uma adi\cao,
		uma decomposi\cao\ de lista (em \emph{head} e \emph{tail})
		e uma compara\cao, para deteminar se a lista \ee\ vazia.
	\item Esse algoritmo executa, na \uu ltima chamada recursiva, apenas
		uma compara\cao\ para detectar se a \sqn\ \ee\ vazia.
\end{itemize}

Somando tudo sentimo-nos tentados a dizer que o n\uu mero total de opera\coes\
do algoritmo \ee: $4n+1$. O problema \ee\ que, dependendo da tecnologia
do processador e do compilador cada uma dessas opera\coes\ poder\aa\ ser
decomposta em v\aa rias instru\coes.  Por causa disso, \ee\ mais adequado
dizer que esse algoritmo demanada $kn$ opera\coes\ para alguma constante
$k$ que ser\aa\ pequena quando o $n$ crescer arbitrariamente.  Mais
exatamente, diz-se que
\[ T(n) \in \Theta(n)\]

E o que \ee\ $\Theta(n)$?

Em 1976, Knuth prop\^os \footnote{
Artigo intitulado \emph{Big Omicron and Big Omega and Big Theta} publicado
em na revista SIGACT News e na colet\^anea \cite{dek:spaa}. Esse artigo
continua sendo a explana\cao\ mais clara do que seja essa nota\cao\ e de
sua origem. Deveria ser leitua obrigat\oo ria de todos os alunos de
\emph{Ci\^encia de Computa\cao.}}
a seguinte nota\cao\ para descrever o comportamento assint\oo tico de
fun\coes:

\begin{itemize}
	\item $O(f(n))$ denota o conjunto de todas as fun\coes\ $g(n)$ tal
		que existem constantes positivas $C$ e $n_0$ tal que
		\[ \bndA{n}{n\ge n_0}{|g(n)|\le Cf(n)}\]
	\item $\Omega(f(n))$ denota o conjunto de todas as fun\coes\ $g(n)$ tal
		que existem constantes positivas $C$ e $n_0$ tal que
		\[ \bndA{n}{n\ge n_0}{g(n)\ge Cf(n)}\]
	\item $\Theta(f(n))$ denota o conjunto de todas as fun\coes\ $g(n)$ tal
		que existem constantes positivas $C,C'$ e $n_0$ tal que
		\[ \bndA{n}{n\ge n_0}{\lele{Cf(n)}{g(n)}{Cf(n)}}\]
\end{itemize}




\begin{ex}
	Apresenta defini\cao\ alternativa para essas tr\^es noat\coes\ baseada
	em estudo de crescimento de fun\coes.
\end{ex}

A \rffig{linsearch} apresenta programa em Haskell para fazer uma busca linear
em uma \sqn\ por um elemento dado.
\begin{figure}
	\begin{center}
	\lstinputlisting{linsearch.hs}	
	\end{center}
	\caption{Pesquisa linear}
	\label{linsearch}
\end{figure}

Dada uma \sqn\ de $n$ elementos e um elemento $x$ esse algoritmo pode:
\begin{itemize}
	\item encontrar o elemento procurado na primeira posi\cao\ da
		\sqn: isso demandaria o teste para determinar que a \sqn\
		n\ao\ \ee\ vazia e o teste para determinar que $x$ e o
		primeiro elemento da \sqn\ s\ao\ iguais;
	\item comparar $x$ com cada elemento e descobrir que ele n\ao\ ocorre
		na \sqn: isso demandaria $n$ chamadas recursivas, $n+1$ testes
		de \sqn\ vazia,  $n$ compara\coes\ de itens e $n$ opera\coes\ 
		de desconstru\cao\ da \sqn.
\end{itemize}

Num caso desses afirma-se que 
\begin{itemize}
	\item no melhor caso $T(n) \in \Omega(1)$:
		porque o menor tempo de execu\cao\ desse
		algritmo \ee\ constante.
        \item no pior caso $T(n) \in O(n)$: porque o pior tempo do 
		algoritmo \ee\ menor ou igual a $kn$ para alguma constante $k$.
\end{itemize}

\begin{ex}
	Em cada caso, determine a veracidade (e justifique):
	\begin{itemize}
		\item $n\in O(n^2)$
		\item $n^2 in \Omega(n)$
		\item $n\lg n+n \in O(n\log n)$
		\item $n^2+n \in  O(n^2)$
	\end{itemize}
\end{ex}


