Este documento tem como objetivo apresentar conceitos de programação não-linear e como implementar tais problemas de otimização no R. Desta forma, vamos apresentar como identificar um problema de programação não-linear e seus diversos tipos.
INTRODUÇÃO
Os modelos de Programação Linear são utilizados para otimizar (maximizar ou minimzar) uma função objetivo linear bem como restrições lineares. Porém, a necessidade de linearidade é a maior das restrições impostas sobre um modelo de Programação.
De fato, muitos economistas descobriram que algum grau de não-linearidade é a regra e não a exceção em problemas de planejamento econômico. Portanto, muitas vezes é necessário lidar diretamente com problemas de programação não-linear.
Em geral, o problema de programação não-linear é encontrar \(x =(x_1,x_2,...,x_n)\) de modo a:
\[
\begin{aligned}
& \text{MAX (MIN)}
& & F(\boldsymbol{x}) \\
& \text{s.a.}
& & G_{i}(\boldsymbol{x}) \leq b_{i} && \text{para i=1,2,...,m} \\
&&& \boldsymbol{x} \geq \boldsymbol{0}
\end{aligned}
\] em que \(F(\boldsymbol{x})\) e os \(G_{i}(\boldsymbol{x})\) são funções dadas das \(n\) variáveis de escolha.
Há muitos tipos de problemas de programação não-linear, dependendo das características das funções \(F(\boldsymbol{x})\) e os \(G_{i}(\boldsymbol{x})\). Diferentes algoritmos são usados para os diferentes tipos. Para certos tipos em que as funções têm formas simples, os problemas podem ser resolvidos de forma relativamente eficiente.
EXEMPLO DE PROBLEMA DE PROGRAMAÇÃO NÃO-LINEAR
Hoje em dia é prática comum entre os administradores profissionais de grandes carteiras de ações usarem modelos computacionais baseados parcialmente em programação não-linear para orientá-los. Pelo fato de os investidores estarem preocupados com o retorno esperado (ganho) e o risco associado a seus investimentos, a programação não-linear é usda para determinar uma carteira que, sob certas hipóteses, forneça uma relação ótima entre esses dois fatores.
Essa metodologia se baseia em grande parte sobre a pesquisa revolucionária feita por Harry Markowitz e William Sharpe que lhes conferiu o Prêmio Nobel de Economia do ano de 1990.
Um modelo de programação não-linear pode ser formulado para esse problema como mostrado a seguir. Suponha que sejam consideradas \(n\) ações (títulos) para inclusão nessa carteira e façamos que as variáveis de escolha \(x_{j}(j=1,2,...,n)\) representem o número de cotas das ações \(j\) a serem incluídas. Estipulamos que \(\mu_{j}\) e \(\sigma_{jj}\) sejam, respectivamente, a média e variância, (estimadas) do retorno sobre cada ação \(j\), em que \(\sigma_{jj}\) mede o risco dessa ação. Para \(i=1,2,...,n\) (\(i\neq j\)), façamos que \(\sigma_{ij}\), a metodologia usual é partir de certas hipóteses sobre o comportamento do mercado que nos permitam calcular \(\sigma_{ij}\) diretamente de \(\sigma_{ii}\) e \(\sigma_{jj}\). A seguir, o valor esperado \(R(x)\) e variância \(V(x)\) do retorno total de toda a carteira são:
\[
R(x)=\sum _{ j=1 }^{ n }{ { \mu }_{ j }{ x }_{ j } }
\] \[
V(x)=\sum _{ i=1 }^{ n }{ \sum _{ j=1 }^{ n }{ { \sigma }_{ ij }{ x }_{ i }{ x }_{ j } } }
\] em que \(V(x)\) mede o risco associado à carteira. Uma maneira de se considerar a relação conflitante entre esses dois fatores é usar \(V(x)\) como função objetivo a ser minimizada e, depois, impor a restrição de que \(R(x)\) não pode ser menor que o retorno mínimo esperado aceitável. O modelo de programação não-linear completo ficaria então:
\[
\begin{aligned}
& \text{Minimizar}
& & V(\boldsymbol{x})=\sum_{i=1}^{n}{\sum_{j=1}^{n}{{\sigma}_{ij}{x}_{i}{x}_{j}}} \\
& \text{s.a.}
& & \sum_{j=1}^{n}{{\mu}_{j}{x}_{j}} \geq L \\
&&& \sum_{j=1}^{n}{P_{j}{x}_{j}} \leq B \\
&&& x_{j} \geq 0 && \text{para j=1,2,...,n}
\end{aligned}
\] em que \(L\) é o retorno mínimo esperado aceitável, \(P_{j}\) é o preço para cada cota da ação \(j\) e \(B\) o volume de dinheiro previsto para a carteira.
REPRESENTAÇÃO GRÁFICA
Quando um problema de programação não-linear tem apenas uma ou duas variáveis, ele pode ser representado graficamente de modo muito parecido com o exemplo do problema de programação linear apresentado neste link.
TIPOS DE PROBLEMAS DE PROGRAMAÇÃO NÃO-LINEAR
Os problemas de programação não-linear se apresentam em muitas formas e formatos diferentes. Ao contrário do método SIMPLEX para programação linear, não existe um algoritmo único capaz de resolver todos esses tipos de problemas.
Em vez disso, foram desenvolvidos algoritmos para várias classes individuais de problemas de programação não-linear. Em seguida, introduzimos brevemente algumas destas classes e como elas podem ser resolvidas.
- OTIMIZAÇÃO LINEARMENTE RESTRITA
Problemas de otimização linearmente restrita são caracterizados por restrições que se ajustam completamente à programação linear, de modo que todas as funções de restrição \(G_{i}(\boldsymbol{x})\) sejam lineares, porém a função objetivo seja não-linear. Foi desenvolvida uma série de algoritmos especiais baseados na extensão do método SIMPLEX para considerar a função objetivo não-linear. Um importante caso especial, que consideramos a seguir, é a programação quadrática.
Problemas de programação quadrática novamente possuem restrições lineares. No entanto, agora a função objetivo deve ser quadrática. Portanto, a única diferença entre um problema destes e um problema de programação linear é que alguns dos termos na função objetivo envolvem o quadrado de uma variável ou o produto de duas variáveis.
Foram desenvolvidos diversos algoritmos para esse caso sob a hipótese adicional de que a função objetivo seja uma função côncava. Um exemplo de aplicação da programação quadrática é o problema da seleção de carteira com ativos de risco.
A programação convexa cobre ampla gama de problemas que engloba como casos especiais todos os tipos precedentes quando a função objetivo é uma função côncava a ser maximizada. As hipóteses são:
- A função objetivo é uma função côncava
- Cada restrição é uma função convexa
A programação separável é um caso especial de programação convexa, em que a única hipótese adicional é que todas as funções (objetivo e restrições) sejam funções separáveis.
Uma função separável é uma função na qual cada termo envolve apenas uma única variável, de modo que a função seja separável em uma soma de funções de variáveis individuais. Por exemplo, \(f(x_{1},x_{2})=126x_{1}-9x_{1}^{2}+182x_{2}-13x_{2}^{2}\) é uma função separável, pois ela pode ser expressa como \(f(x_{1},x_{2})=f(x_{1})+f(x_{2})\).
A programação não-convexa engloba problemas de programação não-linear que não satisfazem as hipóteses de programação convexa. Certos tipos de problemas de programação não-convexa podem ser resolvidos sem grandes dificuldades por métodos especiais. Dois tipos desses são discutivos brevemente a seguir.
Ao aplicar a programação não-linear a problemas de engenharia, economia e estatística, a função objetivo e as funções de restrição assumem frequentemente a forma:
\[
G(\boldsymbol{x}) = \sum _{i=1}^{N}{{c}_{i}{P}_{i}(\boldsymbol{x})}
\] em que
\[
P_{i}(\boldsymbol{x}) = x_{1}^{a_{i1}}x_{2}^{a_{i2}}...x_{n}^{a_{in}}
\]
para \(i=1,2,...,N\). Em tais casos, \(c_{i}\) e \(a_{ij}\) representam tipicamente constantes físicas e \(x_{j}\) são variáveis de projeto. Essas funções geralmente não são convexas nem côncavas e, portanto, as técnicas de programação convexa não podem ser aplicadas diretamente a esses problemas de programação geométrica.
Suponha que a função objetivo se encontre na forma de uma fração, isto é, a razão de duas funções:
\[
\begin{aligned}
& \text{Maximizar}
& & f(\boldsymbol{x})=\frac{f_{1}(\boldsymbol{x})}{f_{2}(\boldsymbol{x})}
\end{aligned}
\] Tais problemas de programação fracionária surgem, por exemplo, quando se está maximizando a razão entre produção e horas de mão-de-obra gastas (produtividade) ou entre lucro e capital investido (taxa de retorno) ou ainda entre valor esperado e desvio-padrão de alguma medida de desempenho para uma carteira de investimentos (retorno/risco).
CONDIÇÕES DE KUHN-TUCKER
No problema clássico de otimização, sem nenhuma restrição explícita aos sinais das variáveis de escolha e sem nenhuma desigualdade nas restrições, a condição de primeira ordem para um extremo relativo ou local é simplesmente que as derivadas parciais primeiras da função de Lagrange em relação a todas as variáveis de escolha e os multiplicadores de Lagrange sejam iguais a zero.
Em programação não-linear existe um tipo semelhante de condição de primeira ordem, conhecida como condições de Kuhn-Tucker (Kuhn and Tucker (2014)). Contudo, como veremos, enquanto a condição de primeira orde clássica é sempre necessária, não se pode conceder às condições de Kuhn-Tucker o status de condições necessárias a menos que cumpram uma certa hipótese.
- EFEITO DE RESTRIÇÕES DE NÃO-NEGATIVIDADE
Considere um problema com restrições de não-negatividade nas variáveis de escolha, mas sem nenhuma outra restrição. Para o caso de uma variável, temos:
\[
\begin{aligned}
& \text{Maximize}
& & \pi=f(x_{1}) \\
& \text{s.a.}
& & x_{1} \geq 0
\end{aligned}
\]
onde supõe-se que a função \(f\) é diferenciável. Em vista da restrição \(x_{1} \geq 0\), podem surgir três situações. Primeira, se ocorrer um máximo local de \(\pi\) no interior da região viável da figura \((a)\) abaixo, tal como o ponto \(A\), então temos uma solução interior. A condição de primeira ordem neste caso é \(\frac{d\pi}{dx_{1}}=f^{'}(x_{1})=0\), a mesma do problema clássico de otimização. Segunda, como ilustrado pelo ponto \(B\) na figura abaixo, um máximo local também pode ocorrer no eixo vertical, onde \(x_{1}=0\). Mesmo neste segundo caso, onde temos uma solução de fronteira, a condição de primeira ordem \(f^{'}(x_{1})=0\) permanece válida. Contudo, há uma terceira possibilidade, ou seja, no presente contexto, um máximo local pode ocorrer no ponto \(C\) ou no ponto \(D\) da figura abaixo porque, para se qualificar como um máximo local no problema, basta que o ponto candidato seja mais alto que os pontos vizinhos dentro da região viável.
Em vista desta última possibilidade, o ponto máximo em um problema como o proposto pode ser caracterizado não apenas pela equação \(f^{'}(x_{1})=0\), mas também pela desigualdade \(f^{'}(x_{1})<0\). Por outro lado, note que a desigualdade oposta \(f^{'}(x_{1})>0\) pode ser excluída com segurança, pois em um ponto onde a inclinação da curva é ascendente, nunca podemos ter um máximo (como no ponto \(E\)). Assim, podemos resumir as condições para que \(x_{1}\) dê um máximo local de \(\pi\) no problema em:
\[
\begin{aligned}
f^{'}(x_{1})<0 && x_{1}\geq 0 && \text{e} && x_{1}f^{'}(x_{1})=0
\end{aligned}
\]

- EFEITO DE RESTRIÇÕES DE DESIGUALDADE
Por simplicidade, em primeiro lugar vamos tratar de uma problema com três variáveis de escolha (\(n=3\)) e duas restrições (\(m=2\)):
\[
\begin{aligned}
& \text{Maximize}
& & \pi = f(x_{1},x_{2},x_{3}) \\
& \text{s.a.}
& & G^{1}(x_{1},x_{2},x_{3}) \leq r_{1} \\
&&& G^{2}(x_{1},x_{2},x_{3}) \leq r_{2} \\
&&& x_{1},x_{2},x_{3} \geq 0
\end{aligned}
\] que, com o auxílio de duas novas variáveis \(s_{1}\) e \(s_{2}\), pode ser transformada na forma equivalente:
\[
\begin{aligned}
& \text{Maximize}
& & \pi = f(x_{1},x_{2},x_{3}) \\
& \text{s.a.}
& & G^{1}(x_{1},x_{2},x_{3}) + s_{1} = r_{1} \\
&&& G^{2}(x_{1},x_{2},x_{3}) + s_{2} = r_{2} \\
&&& x_{1},x_{2},x_{3},s_{1},s_{2} \geq 0
\end{aligned}
\]
Se as restrições de não-negatividade estiverem ausente, podemos, em conformidade com a abordagem clássica, formar a função Lagrange:
\[
Z = f(x_{1},x_{2},x_{3}) + \lambda_{1}[r_{1}-G^{1}(x_{1},x_{2},x_{3}) - s_{1}] + \lambda_{2}[r_{1}-G^{2}(x_{1},x_{2},x_{3}) - s_{2}]
\] e escrever a condição de primeira ordem como:
\[
\frac{dZ}{dx_{1}}=\frac{dZ}{dx_{2}}=\frac{dZ}{dx_{3}}=\frac{dZ}{ds_{1}}=\frac{dZ}{ds_{2}}=\frac{dZ}{d\lambda_{1}}=\frac{dZ}{d\lambda_{2}}=0
\] Mas visto que as variáveis \(x_{j}\) e \(s_{i}\) têm de ser obrigatoriamente não-negativas, a condição de primeira ordem para essas variáveis deve ser modificada de acordo com o problema de não-negatividade. Ou seja,
\[
\begin{aligned}
& \frac{dZ}{dx_{j}} \leq 0 && x_{j}\geq 0 && \text{e} && x_{j}\frac{dZ}{dx_{j}}=0 \\
& \frac{dZ}{ds_{i}} \leq 0 && s_{i}\geq 0 && \text{e} && s_{i}\frac{dZ}{ds_{i}}=0 \\
& \frac{dZ}{d \lambda_{i}}=0 && \text{para i=1,2} && \text{e} && \text{para j=1,2,3}
\end{aligned}
\]
Cada linha acima está relacionada a um tipo diferente de variável. Mas podemos consolidar as duas últimas linhas e, no processo, eliminar a nova variável \(s_{i}\) da condição de primeira ordem. Considerando que \({dZ}/{d}{s}_{i}=-\lambda_{i}\), a segunda linha nos diz que devemos ter \(-\lambda_{i}\leq0\), \(s_{i}\geq0\) e \(-s_{i}\lambda_{i}=0\), ou de modo equivalente:
\[
\begin{aligned}
s_{i}\geq0 && \lambda_{i}\geq0 && \text{e} && s_{i}\lambda_{i}=0
\end{aligned}
\] Mas a terceira linha significa que \(s_{i}=r_{i}-G^{i}(x_{1},x_{2},x_{3})\). Assim, a restrição se torna:
\[
\begin{aligned}
r_{i}-G^{i}(x_{1},x_{2},x_{3})\geq0 && \lambda_{i}\geq0 && \text{e} && \lambda_{i}[r_{i}-G^{i}(x_{1},x_{2},x_{3})]=0
\end{aligned}
\]
Por fim, podemos expressar a condição de primeira ordem em uma forma equivalente sem as novas variáveis. Usando o símbolo \(G^{i}_{j}\) para denotar \({dG^{i}}/{d}{x}_{j}\), escrevemos agora:
\[
\begin{aligned}
& \frac{dZ}{dx_{j}} = f_{j} - (\lambda_{1}G^{1}_{j}+\lambda_{2}G^{2}_{j}) \leq 0 && x_{j}\geq 0 && \text{e} && x_{j}\frac{dZ}{dx_{j}}=0 \\
& r_{i}-G^{i}(x_{1},x_{2},x_{3})\geq0 && \lambda_{i}\geq 0 && \text{e} && \lambda_{i}[r_{i}-G^{i}(x_{1},x_{2},x_{3})]=0
\end{aligned}
\] São essas as condições de Kuhn-Tucker para o problema proposto.
Se formularmos o problema familiar de maximização de utilidade segundo o modelo da programação não-linear, podemos ter um problema com a restrição de desigualdade, como segue:
\[
\begin{aligned}
& \text{Maximize}
& & U = xy \\
& \text{s.a.}
& & x + y \leq 100 \\
&&& x \leq 40 \\
&&& x,y \geq 0
\end{aligned}
\] Note que com a restrição de desigualdade, o consumidor já não é mais obrigado a gastar toda a quantia na compra dos dois bens. Assim, a função de Lagrange se torna:
\[
Z = xy + \lambda_{1}(100-x-y) + \lambda_{2}(40-x)
\] e as condições de Kuhn-Tucker se tornam:
\[
\begin{aligned}
& Z_{x} = y -\lambda_{1} - \lambda_{2}\leq 0 && x\geq 0 && \text{e} && xZ_{x}=0 \\
& Z_{y} = x -\lambda_{1}\leq 0 && y\geq 0 && \text{e} && yZ_{y}=0 \\
& Z_{\lambda_{1}} = 100 -x -y \geq 0 && \lambda_{1}\geq 0 && \text{e} && \lambda_{1}Z_{\lambda_{1}}=0 \\
& Z_{\lambda_{2}} = 40 -x \geq 0 && \lambda_{2}\geq 0 && \text{e} && \lambda_{2}Z_{\lambda_{2}}=0
\end{aligned}
\] A abordagem típica para resolver um problema de programação não-linear é a de tentativa e erro. Para o presente exemplo, não faz sentido experimentar \(x=0\) ou \(y=0\), pois teríamos \(U=xy=0\). Portanto, vamos supor que ambos, \(x\) e \(y\), são diferentes de zero e deduzir que \(Z_{x}=Z_{y}=0\) pela folga complementar, o que significa que:
\[
y-\lambda_{1}-\lambda_{2}=x-\lambda_{1}(=0)
\] de modo que
\[
y-\lambda_{2}=x
\] Agora, suponha que a restrição de racionamento seja não-vinculadora na solução, o que implica que \(\lambda_{2}=0\). Então temos \(x=y\) e o orçamento (\(100\)) resulta na solução experimental \(x=y=50\). Mas essa solução viola a restrição de racionamento \(x\leq40\). Por conseguinte, temos de adotar a hipótese alternativa de que a restrição de racionamento é vinculadora com \(x^{\ast}=40\). Então, a restrição orçamentária permite que o consumidor tenha \(y^{\ast}=60\). Além disso, visto que a folga complementar determina que \(Z_{x}=Z_{y}=0\), podemos calcular, de imediato, que \(\lambda_{1}^{\ast}=40\) e \(\lambda_{2}^{\ast}=20\)
RESOLVENDO PROBLEMAS DE PROGRAMAÇÃO NÃO-LINEAR NO R
No R, temos o pacote Rsolnp que fornece a função solnp() que resolve problemas gerais de programação não-linear. Assim, vamos usar este pacote para resolver exemplos de problemas de programação não-linear no R.
- Considere o seguinte problema de minimização (Programação Quadrática):
\[
\begin{aligned}
& \text{Minimize}
& & f(x,y) = 4x^{2} + 10y^{2} \\
& \text{s.a.}
& & 0 \leq x^{2} + y^{2} \leq 4
\end{aligned}
\] Tal problema pode se adicionado no R, da seguinte forma:
##########################
#### PACOTES #####
##########################
# Instalar pacotes necessários
# install.packages("Rsolnp")
# Carregar pacotes necessários para o restante do documento
suppressMessages(require(Rsolnp))
##########################
#### PROBMELA #####
##########################
# Função Objetivo
fn <- function(x) {
4*x[1]^2 + 10*x[2]^2 +5
}
# Restrição 1: x^2+y^2 <= 4
ineq1 <- function(x) {
z1=x[1]^2 + x[2]^2
return(c(z1))
}
# Limite inferior (lower) e superior (upper) das restrições de desigualdade
lh <- c(0)
uh <- c(4)
# Valores iniciais para o algoritmo
x0 <- c(1, 1)
##########################
#### SOLUÇÃO #####
##########################
# Basicamente, usamos a função solnp do pacote Rsolnp com os seguintes parâmetros:
# pars: que recebe o vetor de parâmetros iniciais para a solução
# fun: que recebe a função objetivo
# ineqfun: que recebe a função de restrição
# ineqLB: que recebe o limite inferior da restrição de desigualdade
# ineqUB: que recebe o limite superior da restrição de desigualdade
# mais opções da função podem ser obtidas por meio do help(solnp)
solucao.problema <- Rsolnp::solnp(pars = x0,
fun = fn,
ineqfun = ineq1,
ineqLB = lh,
ineqUB=uh)
Iter: 1 fn: 7.8697 Pars: 0.68437 0.31563
Iter: 2 fn: 5.6456 Pars: 0.39701 0.03895
Iter: 3 fn: 5.1604 Pars: 0.200217 0.002001
Iter: 4 fn: 5.0401 Pars: 0.10011821 0.00005323
Iter: 5 fn: 5.0100 Pars: 0.0500592618 0.0000006781
Iter: 6 fn: 5.0025 Pars: 0.02502983706 -0.00000004425
Iter: 7 fn: 5.0006 Pars: 0.01251500215 -0.00000005034
Iter: 8 fn: 5.0002 Pars: 0.00625757145 -0.00000005045
Iter: 9 fn: 5.0000 Pars: 0.00312915970 -0.00000004968
Iter: 10 fn: 5.0000 Pars: 0.00156561388 -0.00000004983
Iter: 11 fn: 5.0000 Pars: 0.0007831473 -0.0000000508
Iter: 12 fn: 5.0000 Pars: 0.00039896484 -0.00000005045
Iter: 13 fn: 5.0000 Pars: 0.00021282342 -0.00000004897
Iter: 14 fn: 5.0000 Pars: 0.00014285437 -0.00000004926
Iter: 15 fn: 5.0000 Pars: 0.00011892066 -0.00000004976
solnp--> Completed in 15 iterations
Como resultado, temos que o algoritmo precisou de 15 iterações pra encontrar a solução do problema. Podemos verificar o resultado da função objetivo em cada uma das iterações. Para tanto, basta fazer:
solucao.problema$values
[1] 19.000000 7.869675 5.645626 5.160388 5.040095 5.010024 5.002506 5.000627 5.000157 5.000039
[11] 5.000010 5.000002 5.000001 5.000000 5.000000 5.000000
O que nos mostra que a partir da iteração 14 a função objetivo não alterou seu valor e por isso o algoritmo parou na iteração 15. Já a solução para \(x_{1}\) e \(x_{2}\) pode ser
Podemos alterar a tolerância para que o algorimo pare as iterações ou até mesmo optar por não mostrar os resultados de cada iteração. Para tanto, basta adicionar a opção control como abaixo:
# Adicionar a tolerância para convergência e não mostrar os resultados
# de cada iteração no console do R (trace=0)
ctrl <- list(TOL = 1e-15, trace = 0)
solucao.problema2 <- Rsolnp::solnp(pars = x0,
fun = fn,
ineqfun = ineq1,
ineqLB = lh,
ineqUB=uh,
control = ctrl)
# Para ver os valore da função objetivo em cada iteração
solucao.problema2$values
# Para saber a solução
solucao.problema2$pars
- Outro exemplo:
\[
\begin{aligned}
& \text{Minimize}
& & f(\boldsymbol{x}) = -x_{1}x_{2}x_{3} \\
& \text{s.a.}
& & 4x_{1}x_{2} + 2x_{2}x_{3} + 2x_{3}x_{1} = 100 \\
&&& 1 \leq x_{i} \leq10 & \text{i=1,2,3}
\end{aligned}
\]
Tal problema pode se adicionado no R, da seguinte forma:
##########################
#### PROBMELA #####
##########################
# Função Objetivo
fn2 <- function(x, ...){
-x[1]*x[2]*x[3]
}
# Restrição 1:
eqn <- function(x, ...){
4*x[1]*x[2]+2*x[2]*x[3]+2*x[3]*x[1]
}
# Limite da restrição
constraints <- c(100)
# Limite inferior (lower) e superior (upper) da restrição de desigualdade
lx <- rep(1, 3)
ux <- rep(10, 3)
# Valores iniciais para o algoritmo
pars <- c(2, 1, 7)
##########################
#### SOLUÇÃO #####
##########################
# Restrições de tolerância e não mostrar o resultado de cada iteração no console
ctrl2 <- list(TOL = 1e-6, trace = 0)
# Basicamente, usamos a função solnp do pacote Rsolnp com os seguintes parâmetros:
# pars: que recebe o vetor de parâmetros iniciais para a solução
# fun: que recebe a função objetivo
# eqfun: que recebe a função de restrição de igualdade
# eqB: a igualdade da restrição de igualdade
# LB: limite inferior da restrição de desigualdade
# UB: limite superior da restrição de desigualdade
# control: as opções de tolerância e mostrar resultados
# mais opções da função podem ser obtidas por meio do help(solnp)
solucao.problema2 <- Rsolnp::solnp(pars = pars,
fun = fn2,
eqfun = eqn,
eqB = constraints,
LB = lx,
UB = ux,
control = ctrl)
# Valores da função objetivo em cada iteração
solucao.problema2$values
[1] -14.00000 -52.58442 -46.78681 -48.05588 -48.11152 -48.11249 -48.11250 -48.11250 -48.11250 -48.11250
[11] -48.11250
# Solução
solucao.problema2$pars
[1] 2.885893 2.884811 5.779102
REFERÊNCIAS
Chiang, Alpha C., and Kevin Wainwright. 2006. Matemática Para Economistas. Elsevier.
Dantzig, George B. 1951. “Maximization of a Linear Function of Variables Subject to Linear Inequalities.” New York.
Hillier, Frederick S, and Gerald J Lieberman. 2013. Introdução à Pesquisa Pesquisa Operacional. McGraw Hill Brasil.
Kuhn, Harold W, and Albert W Tucker. 2014. Nonlinear Programming. Springer.
Soetaert, Karline, and Peter MJ Herman. 2008. A Practical Guide to Ecological Modelling Using R as a Simulation Platform. Springer Science & Business Media.
LS0tCnRpdGxlOiA8Y2VudGVyPiA8aDI+IDxiPiBQcm9ncmFtYcOnw6NvIE7Do28tTGluZWFyIDwvYj4gPC9oMj4gPC9jZW50ZXI+IAphdXRob3I6IDxjZW50ZXI+IEh1ZHNvbiBDaGF2ZXMgQ29zdGEgPC9jZW50ZXI+CmdyYXBoaWNzOiB5ZXMKbGlua2NvbG9yOiBibHVlCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgZmlnX2NhcHRpb246IHllcwpyZWZlcmVuY2VzOgotIGlkOiBzb2V0YWVydDIwMDhwcmFjdGljYWwKICB0aXRsZTogQSBwcmFjdGljYWwgZ3VpZGUgdG8gZWNvbG9naWNhbCBtb2RlbGxpbmcgdXNpbmcgUiBhcyBhIHNpbXVsYXRpb24gcGxhdGZvcm0KICBhdXRob3I6CiAgLSBmYW1pbHk6IFNvZXRhZXJ0CiAgICBnaXZlbjogS2FybGluZQogIC0gZmFtaWx5OiBIZXJtYW4KICAgIGdpdmVuOiBQZXRlciBNSgogIHB1Ymxpc2hlcjogU3ByaW5nZXIgU2NpZW5jZSBcJiBCdXNpbmVzcyBNZWRpYQogIHR5cGU6IGJvb2sKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDA4Ci0gaWQ6IGFscGhhMjAwNG1hdGVtYXRpY2EKICB0aXRsZTogTWF0ZW3DoXRpY2EgcGFyYSBlY29ub21pc3RhcwogIGF1dGhvcjogCiAgLSBmYW1pbHk6IENoaWFuZwogICAgZ2l2ZW46IEFscGhhIEMuCiAgLSBmYW1pbHk6IFdhaW53cmlnaHQKICAgIGdpdmVuOiBLZXZpbgogIHB1Ymxpc2hlcjogRWxzZXZpZXIKICB0eXBlOiBib29rCiAgaXNzdWVkOgogICAgeWVhcjogMjAwNgotIGlkOiBkYW50emlnMTk1MW1heGltaXphdGlvbgogIHRpdGxlOiBNYXhpbWl6YXRpb24gb2YgYSBsaW5lYXIgZnVuY3Rpb24gb2YgdmFyaWFibGVzIHN1YmplY3QgdG8gbGluZWFyIGluZXF1YWxpdGllcwogIGF1dGhvcjogCiAgLSBmYW1pbHk6IERhbnR6aWcKICAgIGdpdmVuOiBHZW9yZ2UgQgogIHB1Ymxpc2hlcjogTmV3IFlvcmsKICB0eXBlOiBhcnRpY2xlLWpvdXJuYWwgCiAgaXNzdWVkOgogICAgeWVhcjogMTk1MQotIGlkOiBrdWhuMjAxNG5vbmxpbmVhcgogIHRpdGxlOiBOb25saW5lYXIgcHJvZ3JhbW1pbmcKICBhdXRob3I6IAogIC0gZmFtaWx5OiBLdWhuCiAgICBnaXZlbjogSGFyb2xkIFcKICAtIGZhbWlseTogVHVja2VyCiAgICBnaXZlbjogQWxiZXJ0IFcKICBwdWJsaXNoZXI6IFNwcmluZ2VyCiAgdHlwZTogYm9vayAKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDE0Ci0gaWQ6IGhpbGxpZXIyMDEzaW50cm9kdWNjYW8KICB0aXRsZTogSW50cm9kdcOnw6NvIMOgIHBlc3F1aXNhIHBlc3F1aXNhIG9wZXJhY2lvbmFsCiAgYXV0aG9yOgogIC0gZmFtaWx5OiBIaWxsaWVyCiAgICBnaXZlbjogRnJlZGVyaWNrIFMKICAtIGZhbWlseTogTGllYmVybWFuCiAgICBnaXZlbjogR2VyYWxkIEoKICBwdWJsaXNoZXI6IE1jR3JhdyBIaWxsIEJyYXNpbAogIHR5cGU6IGJvb2sKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDEzCm5vY2l0ZTogfCAKICBAc29ldGFlcnQyMDA4cHJhY3RpY2FsLCBAYWxwaGEyMDA0bWF0ZW1hdGljYSwgQGRhbnR6aWcxOTUxbWF4aW1pemF0aW9uLCBAa3VobjIwMTRub25saW5lYXIsIEBoaWxsaWVyMjAxM2ludHJvZHVjY2FvCi0tLQoKRXN0ZSBkb2N1bWVudG8gdGVtIGNvbW8gb2JqZXRpdm8gYXByZXNlbnRhciBjb25jZWl0b3MgZGUgcHJvZ3JhbWHDp8OjbyBuw6NvLWxpbmVhciBlIGNvbW8gaW1wbGVtZW50YXIgdGFpcyBwcm9ibGVtYXMgZGUgb3RpbWl6YcOnw6NvIG5vIFtSXShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLykuIERlc3RhIGZvcm1hLCB2YW1vcyBhcHJlc2VudGFyIGNvbW8gaWRlbnRpZmljYXIgdW0gcHJvYmxlbWEgZGUgcHJvZ3JhbWHDp8OjbyBuw6NvLWxpbmVhciBlIHNldXMgZGl2ZXJzb3MgdGlwb3MuIAoKIyMjIyMgKipJTlRST0RVw4fDg08qKgoKT3MgbW9kZWxvcyBkZSBQcm9ncmFtYcOnw6NvIExpbmVhciBzw6NvIHV0aWxpemFkb3MgcGFyYSBvdGltaXphciAobWF4aW1pemFyIG91IG1pbmltemFyKSB1bWEgZnVuw6fDo28gb2JqZXRpdm8gbGluZWFyIGJlbSBjb21vIHJlc3RyacOnw7VlcyBsaW5lYXJlcy4gUG9yw6ltLCBhIG5lY2Vzc2lkYWRlIGRlIGxpbmVhcmlkYWRlIMOpIGEgbWFpb3IgZGFzIHJlc3RyacOnw7VlcyBpbXBvc3RhcyBzb2JyZSB1bSBtb2RlbG8gZGUgUHJvZ3JhbWHDp8Ojby4gCgpEZSBmYXRvLCBtdWl0b3MgZWNvbm9taXN0YXMgZGVzY29icmlyYW0gcXVlIGFsZ3VtIGdyYXUgZGUgbsOjby1saW5lYXJpZGFkZSDDqSBhIHJlZ3JhIGUgbsOjbyBhIGV4Y2XDp8OjbyBlbSBwcm9ibGVtYXMgZGUgcGxhbmVqYW1lbnRvIGVjb27DtG1pY28uIFBvcnRhbnRvLCBtdWl0YXMgdmV6ZXMgw6kgbmVjZXNzw6FyaW8gbGlkYXIgZGlyZXRhbWVudGUgY29tIHByb2JsZW1hcyBkZSBwcm9ncmFtYcOnw6NvIG7Do28tbGluZWFyLgoKRW0gZ2VyYWwsIG8gcHJvYmxlbWEgZGUgcHJvZ3JhbWHDp8OjbyBuw6NvLWxpbmVhciDDqSBlbmNvbnRyYXIgJHggPSh4XzEseF8yLC4uLix4X24pJCBkZSBtb2RvIGE6CgokJApcYmVnaW57YWxpZ25lZH0KJiBcdGV4dHtNQVggKE1JTil9CiYgJiBGKFxib2xkc3ltYm9se3h9KSBcXAomIFx0ZXh0e3MuYS59CiYgJiBHX3tpfShcYm9sZHN5bWJvbHt4fSkgXGxlcSBiX3tpfSAmJiBcdGV4dHtwYXJhIGk9MSwyLC4uLixtfSBcXCAKJiYmIFxib2xkc3ltYm9se3h9IFxnZXEgXGJvbGRzeW1ib2x7MH0KXGVuZHthbGlnbmVkfQokJAplbSBxdWUgJEYoXGJvbGRzeW1ib2x7eH0pJCBlIG9zICRHX3tpfShcYm9sZHN5bWJvbHt4fSkkIHPDo28gZnVuw6fDtWVzIGRhZGFzIGRhcyAkbiQgdmFyacOhdmVpcyBkZSBlc2NvbGhhLiAKCkjDoSBtdWl0b3MgdGlwb3MgZGUgcHJvYmxlbWFzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIsIGRlcGVuZGVuZG8gZGFzIGNhcmFjdGVyw61zdGljYXMgZGFzIGZ1bsOnw7VlcyAkRihcYm9sZHN5bWJvbHt4fSkkIGUgb3MgJEdfe2l9KFxib2xkc3ltYm9se3h9KSQuIERpZmVyZW50ZXMgYWxnb3JpdG1vcyBzw6NvIHVzYWRvcyBwYXJhIG9zIGRpZmVyZW50ZXMgdGlwb3MuIFBhcmEgY2VydG9zIHRpcG9zIGVtIHF1ZSBhcyBmdW7Dp8O1ZXMgdMOqbSBmb3JtYXMgc2ltcGxlcywgb3MgcHJvYmxlbWFzIHBvZGVtIHNlciByZXNvbHZpZG9zIGRlIGZvcm1hIHJlbGF0aXZhbWVudGUgZWZpY2llbnRlLiAKCiMjIyMjICoqRVhFTVBMTyBERSBQUk9CTEVNQSBERSBQUk9HUkFNQcOHw4NPIE7Dg08tTElORUFSKioKCkhvamUgZW0gZGlhIMOpIHByw6F0aWNhIGNvbXVtIGVudHJlIG9zIGFkbWluaXN0cmFkb3JlcyBwcm9maXNzaW9uYWlzIGRlIGdyYW5kZXMgY2FydGVpcmFzIGRlIGHDp8O1ZXMgdXNhcmVtIG1vZGVsb3MgY29tcHV0YWNpb25haXMgYmFzZWFkb3MgcGFyY2lhbG1lbnRlIGVtIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgcGFyYSBvcmllbnTDoS1sb3MuIFBlbG8gZmF0byBkZSBvcyBpbnZlc3RpZG9yZXMgZXN0YXJlbSBwcmVvY3VwYWRvcyBjb20gbyAqKnJldG9ybm8gZXNwZXJhZG8qKiAoZ2FuaG8pIGUgbyAqKnJpc2NvKiogYXNzb2NpYWRvIGEgc2V1cyBpbnZlc3RpbWVudG9zLCBhIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgw6kgdXNkYSBwYXJhIGRldGVybWluYXIgdW1hIGNhcnRlaXJhIHF1ZSwgc29iIGNlcnRhcyBoaXDDs3Rlc2VzLCBmb3JuZcOnYSB1bWEgcmVsYcOnw6NvIMOzdGltYSBlbnRyZSBlc3NlcyBkb2lzIGZhdG9yZXMuCgpFc3NhIG1ldG9kb2xvZ2lhIHNlIGJhc2VpYSBlbSBncmFuZGUgcGFydGUgc29icmUgYSBwZXNxdWlzYSByZXZvbHVjaW9uw6FyaWEgZmVpdGEgcG9yIEhhcnJ5IE1hcmtvd2l0eiBlIFdpbGxpYW0gU2hhcnBlIHF1ZSBsaGVzIGNvbmZlcml1IG8gUHLDqm1pbyBOb2JlbCBkZSBFY29ub21pYSBkbyBhbm8gZGUgMTk5MC4KClVtIG1vZGVsbyBkZSBwcm9ncmFtYcOnw6NvIG7Do28tbGluZWFyIHBvZGUgc2VyIGZvcm11bGFkbyBwYXJhIGVzc2UgcHJvYmxlbWEgY29tbyBtb3N0cmFkbyBhIHNlZ3Vpci4gU3Vwb25oYSBxdWUgc2VqYW0gY29uc2lkZXJhZGFzICRuJCBhw6fDtWVzICh0w610dWxvcykgcGFyYSBpbmNsdXPDo28gbmVzc2EgY2FydGVpcmEgZSBmYcOnYW1vcyBxdWUgYXMgdmFyacOhdmVpcyBkZSBlc2NvbGhhICR4X3tqfShqPTEsMiwuLi4sbikkIHJlcHJlc2VudGVtIG8gbsO6bWVybyBkZSBjb3RhcyBkYXMgYcOnw7VlcyAkaiQgYSBzZXJlbSBpbmNsdcOtZGFzLiBFc3RpcHVsYW1vcyBxdWUgJFxtdV97an0kIGUgJFxzaWdtYV97amp9JCBzZWphbSwgcmVzcGVjdGl2YW1lbnRlLCBhIG3DqWRpYSBlIHZhcmnDom5jaWEsIChlc3RpbWFkYXMpIGRvIHJldG9ybm8gc29icmUgY2FkYSBhw6fDo28gJGokLCBlbSBxdWUgJFxzaWdtYV97amp9JCBtZWRlIG8gcmlzY28gZGVzc2EgYcOnw6NvLiBQYXJhICRpPTEsMiwuLi4sbiQgKCRpXG5lcSBqJCksIGZhw6dhbW9zIHF1ZSAkXHNpZ21hX3tpan0kLCBhIG1ldG9kb2xvZ2lhIHVzdWFsIMOpIHBhcnRpciBkZSBjZXJ0YXMgaGlww7N0ZXNlcyBzb2JyZSBvIGNvbXBvcnRhbWVudG8gZG8gbWVyY2FkbyBxdWUgbm9zIHBlcm1pdGFtIGNhbGN1bGFyICRcc2lnbWFfe2lqfSQgZGlyZXRhbWVudGUgZGUgJFxzaWdtYV97aWl9JCBlICRcc2lnbWFfe2pqfSQuIEEgc2VndWlyLCBvIHZhbG9yIGVzcGVyYWRvICRSKHgpJCBlIHZhcmnDom5jaWEgJFYoeCkkIGRvIHJldG9ybm8gdG90YWwgZGUgdG9kYSBhIGNhcnRlaXJhIHPDo286CgokJApSKHgpPVxzdW0gX3sgaj0xIH1eeyBuIH17IHsgXG11ICB9X3sgaiB9eyB4IH1feyBqIH0gfSAKJCQKJCQKVih4KT1cc3VtIF97IGk9MSB9XnsgbiB9eyBcc3VtIF97IGo9MSB9XnsgbiB9eyB7IFxzaWdtYSAgfV97IGlqIH17IHggfV97IGkgfXsgeCB9X3sgaiB9IH0gIH0gCiQkCmVtIHF1ZSAkVih4KSQgbWVkZSBvIHJpc2NvIGFzc29jaWFkbyDDoCBjYXJ0ZWlyYS4gVW1hIG1hbmVpcmEgZGUgc2UgY29uc2lkZXJhciBhIHJlbGHDp8OjbyBjb25mbGl0YW50ZSBlbnRyZSBlc3NlcyBkb2lzIGZhdG9yZXMgw6kgdXNhciAkVih4KSQgY29tbyBmdW7Dp8OjbyBvYmpldGl2byBhIHNlciBtaW5pbWl6YWRhIGUsIGRlcG9pcywgaW1wb3IgYSByZXN0cmnDp8OjbyBkZSBxdWUgJFIoeCkkIG7Do28gcG9kZSBzZXIgbWVub3IgcXVlIG8gcmV0b3JubyBtw61uaW1vIGVzcGVyYWRvIGFjZWl0w6F2ZWwuIE8gbW9kZWxvIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgY29tcGxldG8gZmljYXJpYSBlbnTDo286CgokJApcYmVnaW57YWxpZ25lZH0KJiBcdGV4dHtNaW5pbWl6YXJ9CiYgJiBWKFxib2xkc3ltYm9se3h9KT1cc3VtX3tpPTF9XntufXtcc3VtX3tqPTF9XntufXt7XHNpZ21hfV97aWp9e3h9X3tpfXt4fV97an19fSBcXAomIFx0ZXh0e3MuYS59CiYgJiBcc3VtX3tqPTF9XntufXt7XG11fV97an17eH1fe2p9fSAgXGdlcSBMIFxcIAomJiYgXHN1bV97aj0xfV57bn17UF97an17eH1fe2p9fSBcbGVxIEIgXFwgCiYmJiB4X3tqfSBcZ2VxIDAgJiYgXHRleHR7cGFyYSBqPTEsMiwuLi4sbn0KXGVuZHthbGlnbmVkfQokJAplbSBxdWUgJEwkIMOpIG8gcmV0b3JubyBtw61uaW1vIGVzcGVyYWRvIGFjZWl0w6F2ZWwsICRQX3tqfSQgw6kgbyBwcmXDp28gcGFyYSBjYWRhIGNvdGEgZGEgYcOnw6NvICRqJCBlICRCJCBvIHZvbHVtZSBkZSBkaW5oZWlybyBwcmV2aXN0byBwYXJhIGEgY2FydGVpcmEuIAoKIyMjIyMgKipSRVBSRVNFTlRBw4fDg08gR1LDgUZJQ0EqKgoKUXVhbmRvIHVtIHByb2JsZW1hIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgdGVtIGFwZW5hcyB1bWEgb3UgZHVhcyB2YXJpw6F2ZWlzLCBlbGUgcG9kZSBzZXIgcmVwcmVzZW50YWRvIGdyYWZpY2FtZW50ZSBkZSBtb2RvIG11aXRvIHBhcmVjaWRvIGNvbSBvIGV4ZW1wbG8gZG8gcHJvYmxlbWEgZGUgcHJvZ3JhbWHDp8OjbyBsaW5lYXIgYXByZXNlbnRhZG8gbmVzdGUgW2xpbmtdKGh0dHBzOi8vcnB1YnMuY29tL2h1ZHNvbmNoYXZzL2xpbmVhcnByb2dyYW1taW5nKS4KCiMjIyMjICoqVElQT1MgREUgUFJPQkxFTUFTIERFIFBST0dSQU1Bw4fDg08gTsODTy1MSU5FQVIqKgoKT3MgcHJvYmxlbWFzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgc2UgYXByZXNlbnRhbSBlbSBtdWl0YXMgZm9ybWFzIGUgZm9ybWF0b3MgZGlmZXJlbnRlcy4gQW8gY29udHLDoXJpbyBkbyBtw6l0b2RvIFNJTVBMRVggcGFyYSBwcm9ncmFtYcOnw6NvIGxpbmVhciwgbsOjbyBleGlzdGUgdW0gYWxnb3JpdG1vIMO6bmljbyBjYXBheiBkZSByZXNvbHZlciB0b2RvcyBlc3NlcyB0aXBvcyBkZSBwcm9ibGVtYXMuIAoKRW0gdmV6IGRpc3NvLCBmb3JhbSBkZXNlbnZvbHZpZG9zIGFsZ29yaXRtb3MgcGFyYSB2w6FyaWFzIGNsYXNzZXMgaW5kaXZpZHVhaXMgZGUgcHJvYmxlbWFzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIuIEVtIHNlZ3VpZGEsIGludHJvZHV6aW1vcyBicmV2ZW1lbnRlIGFsZ3VtYXMgZGVzdGFzIGNsYXNzZXMgZSBjb21vIGVsYXMgcG9kZW0gc2VyIHJlc29sdmlkYXMuCgoqICoqT1RJTUlaQcOHw4NPIExJTkVBUk1FTlRFIFJFU1RSSVRBKioKClByb2JsZW1hcyBkZSBvdGltaXphw6fDo28gbGluZWFybWVudGUgcmVzdHJpdGEgc8OjbyBjYXJhY3Rlcml6YWRvcyBwb3IgcmVzdHJpw6fDtWVzIHF1ZSBzZSBhanVzdGFtIGNvbXBsZXRhbWVudGUgw6AgcHJvZ3JhbWHDp8OjbyBsaW5lYXIsIGRlIG1vZG8gcXVlICoqdG9kYXMqKiBhcyBmdW7Dp8O1ZXMgZGUgcmVzdHJpw6fDo28gJEdfe2l9KFxib2xkc3ltYm9se3h9KSQgc2VqYW0gbGluZWFyZXMsIHBvcsOpbSBhIGZ1bsOnw6NvIG9iamV0aXZvIHNlamEgbsOjby1saW5lYXIuIEZvaSBkZXNlbnZvbHZpZGEgdW1hIHPDqXJpZSBkZSBhbGdvcml0bW9zIGVzcGVjaWFpcyBiYXNlYWRvcyBuYSBleHRlbnPDo28gZG8gbcOpdG9kbyBTSU1QTEVYIHBhcmEgY29uc2lkZXJhciBhIGZ1bsOnw6NvIG9iamV0aXZvIG7Do28tbGluZWFyLiBVbSBpbXBvcnRhbnRlIGNhc28gZXNwZWNpYWwsIHF1ZSBjb25zaWRlcmFtb3MgYSBzZWd1aXIsIMOpIGEgcHJvZ3JhbWHDp8OjbyBxdWFkcsOhdGljYS4KCiogKipQUk9HUkFNQcOHw4NPIFFVQURSw4FUSUNBKioKClByb2JsZW1hcyBkZSBwcm9ncmFtYcOnw6NvIHF1YWRyw6F0aWNhIG5vdmFtZW50ZSBwb3NzdWVtIHJlc3RyacOnw7VlcyBsaW5lYXJlcy4gTm8gZW50YW50bywgYWdvcmEgYSBmdW7Dp8OjbyBvYmpldGl2byBkZXZlIHNlciAqKnF1YWRyw6F0aWNhKiouIFBvcnRhbnRvLCBhIMO6bmljYSBkaWZlcmVuw6dhIGVudHJlIHVtIHByb2JsZW1hIGRlc3RlcyBlIHVtIHByb2JsZW1hIGRlIHByb2dyYW1hw6fDo28gbGluZWFyIMOpIHF1ZSBhbGd1bnMgZG9zIHRlcm1vcyBuYSBmdW7Dp8OjbyBvYmpldGl2byBlbnZvbHZlbSBvIHF1YWRyYWRvIGRlIHVtYSB2YXJpw6F2ZWwgb3UgbyBwcm9kdXRvIGRlIGR1YXMgdmFyacOhdmVpcy4gCgpGb3JhbSBkZXNlbnZvbHZpZG9zIGRpdmVyc29zIGFsZ29yaXRtb3MgcGFyYSBlc3NlIGNhc28gc29iIGEgaGlww7N0ZXNlIGFkaWNpb25hbCBkZSBxdWUgYSBmdW7Dp8OjbyBvYmpldGl2byBzZWphIHVtYSAqKmZ1bsOnw6NvIGPDtG5jYXZhKiouIFVtIGV4ZW1wbG8gZGUgYXBsaWNhw6fDo28gZGEgcHJvZ3JhbWHDp8OjbyBxdWFkcsOhdGljYSDDqSBvIHByb2JsZW1hIGRhIHNlbGXDp8OjbyBkZSBjYXJ0ZWlyYSBjb20gYXRpdm9zIGRlIHJpc2NvLgoKKiAqKlBST0dSQU1Bw4fDg08gQ09OVkVYQSoqCgpBIHByb2dyYW1hw6fDo28gY29udmV4YSBjb2JyZSBhbXBsYSBnYW1hIGRlIHByb2JsZW1hcyBxdWUgZW5nbG9iYSBjb21vIGNhc29zIGVzcGVjaWFpcyB0b2RvcyBvcyB0aXBvcyBwcmVjZWRlbnRlcyBxdWFuZG8gYSBmdW7Dp8OjbyBvYmpldGl2byDDqSB1bWEgZnVuw6fDo28gY8O0bmNhdmEgYSBzZXIgbWF4aW1pemFkYS4gQXMgaGlww7N0ZXNlcyBzw6NvOgoKMS4gQSBmdW7Dp8OjbyBvYmpldGl2byDDqSB1bWEgZnVuw6fDo28gY8O0bmNhdmEKMi4gQ2FkYSByZXN0cmnDp8OjbyDDqSB1bWEgZnVuw6fDo28gY29udmV4YQogICAgCiogKipQUk9HUkFNQcOHw4NPIFNFUEFSw4FWRUwqKgoKQSBwcm9ncmFtYcOnw6NvIHNlcGFyw6F2ZWwgw6kgdW0gY2FzbyBlc3BlY2lhbCBkZSBwcm9ncmFtYcOnw6NvIGNvbnZleGEsIGVtIHF1ZSBhIMO6bmljYSBoaXDDs3Rlc2UgYWRpY2lvbmFsIMOpIHF1ZSB0b2RhcyBhcyBmdW7Dp8O1ZXMgKG9iamV0aXZvIGUgcmVzdHJpw6fDtWVzKSBzZWphbSBmdW7Dp8O1ZXMgc2VwYXLDoXZlaXMuIAoKVW1hIGZ1bsOnw6NvIHNlcGFyw6F2ZWwgw6kgdW1hIGZ1bsOnw6NvIG5hIHF1YWwgY2FkYSB0ZXJtbyBlbnZvbHZlIGFwZW5hcyB1bWEgw7puaWNhIHZhcmnDoXZlbCwgZGUgbW9kbyBxdWUgYSBmdW7Dp8OjbyBzZWphIHNlcGFyw6F2ZWwgZW0gdW1hIHNvbWEgZGUgZnVuw6fDtWVzIGRlIHZhcmnDoXZlaXMgaW5kaXZpZHVhaXMuIFBvciBleGVtcGxvLCAkZih4X3sxfSx4X3syfSk9MTI2eF97MX0tOXhfezF9XnsyfSsxODJ4X3syfS0xM3hfezJ9XnsyfSQgw6kgdW1hIGZ1bsOnw6NvIHNlcGFyw6F2ZWwsIHBvaXMgZWxhIHBvZGUgc2VyIGV4cHJlc3NhIGNvbW8gJGYoeF97MX0seF97Mn0pPWYoeF97MX0pK2YoeF97Mn0pJC4KCiogKipQUk9HUkFNQcOHw4NPIE7Dg08tQ09OVkVYQSoqCgpBIHByb2dyYW1hw6fDo28gbsOjby1jb252ZXhhIGVuZ2xvYmEgcHJvYmxlbWFzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgcXVlIG7Do28gc2F0aXNmYXplbSBhcyBoaXDDs3Rlc2VzIGRlIHByb2dyYW1hw6fDo28gY29udmV4YS4gQ2VydG9zIHRpcG9zIGRlIHByb2JsZW1hcyBkZSBwcm9ncmFtYcOnw6NvIG7Do28tY29udmV4YSBwb2RlbSBzZXIgcmVzb2x2aWRvcyBzZW0gZ3JhbmRlcyBkaWZpY3VsZGFkZXMgcG9yIG3DqXRvZG9zIGVzcGVjaWFpcy4gRG9pcyB0aXBvcyBkZXNzZXMgc8OjbyBkaXNjdXRpdm9zIGJyZXZlbWVudGUgYSBzZWd1aXIuCgoKKiAqKlBST0dSQU1Bw4fDg08gR0VPTcOJVFJJQ0EqKgoKQW8gYXBsaWNhciBhIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgYSBwcm9ibGVtYXMgZGUgZW5nZW5oYXJpYSwgZWNvbm9taWEgZSBlc3RhdMOtc3RpY2EsIGEgZnVuw6fDo28gb2JqZXRpdm8gZSBhcyBmdW7Dp8O1ZXMgZGUgcmVzdHJpw6fDo28gYXNzdW1lbSBmcmVxdWVudGVtZW50ZSBhIGZvcm1hOgoKJCQKRyhcYm9sZHN5bWJvbHt4fSkgPSBcc3VtIF97aT0xfV57Tn17e2N9X3tpfXtQfV97aX0oXGJvbGRzeW1ib2x7eH0pfSAKJCQKZW0gcXVlCgokJApQX3tpfShcYm9sZHN5bWJvbHt4fSkgPSB4X3sxfV57YV97aTF9fXhfezJ9XnthX3tpMn19Li4ueF97bn1ee2Ffe2lufX0KJCQKCnBhcmEgJGk9MSwyLC4uLixOJC4gRW0gdGFpcyBjYXNvcywgJGNfe2l9JCBlICRhX3tpan0kIHJlcHJlc2VudGFtIHRpcGljYW1lbnRlIGNvbnN0YW50ZXMgZsOtc2ljYXMgZSAkeF97an0kIHPDo28gdmFyacOhdmVpcyBkZSBwcm9qZXRvLiBFc3NhcyBmdW7Dp8O1ZXMgZ2VyYWxtZW50ZSBuw6NvIHPDo28gY29udmV4YXMgbmVtIGPDtG5jYXZhcyBlLCBwb3J0YW50bywgYXMgdMOpY25pY2FzIGRlIHByb2dyYW1hw6fDo28gY29udmV4YSBuw6NvIHBvZGVtIHNlciBhcGxpY2FkYXMgZGlyZXRhbWVudGUgYSBlc3NlcyBwcm9ibGVtYXMgZGUgcHJvZ3JhbWHDp8OjbyBnZW9tw6l0cmljYS4gCgoqICoqUFJPR1JBTUHDh8ODTyBGUkFDSU9Ow4FSSUEqKgoKU3Vwb25oYSBxdWUgYSBmdW7Dp8OjbyBvYmpldGl2byBzZSBlbmNvbnRyZSBuYSBmb3JtYSBkZSB1bWEgZnJhw6fDo28sIGlzdG8gw6ksIGEgcmF6w6NvIGRlIGR1YXMgZnVuw6fDtWVzOgoKJCQKXGJlZ2lue2FsaWduZWR9CiYgXHRleHR7TWF4aW1pemFyfQomICYgZihcYm9sZHN5bWJvbHt4fSk9XGZyYWN7Zl97MX0oXGJvbGRzeW1ib2x7eH0pfXtmX3syfShcYm9sZHN5bWJvbHt4fSl9ClxlbmR7YWxpZ25lZH0KJCQKVGFpcyBwcm9ibGVtYXMgZGUgcHJvZ3JhbWHDp8OjbyBmcmFjaW9uw6FyaWEgc3VyZ2VtLCBwb3IgZXhlbXBsbywgcXVhbmRvIHNlIGVzdMOhIG1heGltaXphbmRvIGEgcmF6w6NvIGVudHJlIHByb2R1w6fDo28gZSBob3JhcyBkZSBtw6NvLWRlLW9icmEgZ2FzdGFzIChwcm9kdXRpdmlkYWRlKSBvdSBlbnRyZSBsdWNybyBlIGNhcGl0YWwgaW52ZXN0aWRvICh0YXhhIGRlIHJldG9ybm8pIG91IGFpbmRhIGVudHJlIHZhbG9yIGVzcGVyYWRvIGUgZGVzdmlvLXBhZHLDo28gZGUgYWxndW1hIG1lZGlkYSBkZSBkZXNlbXBlbmhvIHBhcmEgdW1hIGNhcnRlaXJhIGRlIGludmVzdGltZW50b3MgKHJldG9ybm8vcmlzY28pLgoKIyMjIyMgKipDT05EScOHw5VFUyBERSBLVUhOLVRVQ0tFUioqCgpObyBwcm9ibGVtYSBjbMOhc3NpY28gZGUgb3RpbWl6YcOnw6NvLCBzZW0gbmVuaHVtYSByZXN0cmnDp8OjbyBleHBsw61jaXRhIGFvcyBzaW5haXMgZGFzIHZhcmnDoXZlaXMgZGUgZXNjb2xoYSBlIHNlbSBuZW5odW1hIGRlc2lndWFsZGFkZSBuYXMgcmVzdHJpw6fDtWVzLCBhIGNvbmRpw6fDo28gZGUgcHJpbWVpcmEgb3JkZW0gcGFyYSB1bSBleHRyZW1vIHJlbGF0aXZvIG91IGxvY2FsIMOpIHNpbXBsZXNtZW50ZSBxdWUgYXMgZGVyaXZhZGFzIHBhcmNpYWlzIHByaW1laXJhcyBkYSBmdW7Dp8OjbyBkZSBMYWdyYW5nZSBlbSByZWxhw6fDo28gYSB0b2RhcyBhcyB2YXJpw6F2ZWlzIGRlIGVzY29saGEgZSBvcyBtdWx0aXBsaWNhZG9yZXMgZGUgTGFncmFuZ2Ugc2VqYW0gaWd1YWlzIGEgemVyby4gCgpFbSBwcm9ncmFtYcOnw6NvIG7Do28tbGluZWFyIGV4aXN0ZSB1bSB0aXBvIHNlbWVsaGFudGUgZGUgY29uZGnDp8OjbyBkZSBwcmltZWlyYSBvcmRlbSwgY29uaGVjaWRhIGNvbW8gKipjb25kacOnw7VlcyBkZSBLdWhuLVR1Y2tlcioqIChAa3VobjIwMTRub25saW5lYXIpLiBDb250dWRvLCBjb21vIHZlcmVtb3MsIGVucXVhbnRvIGEgY29uZGnDp8OjbyBkZSBwcmltZWlyYSBvcmRlIGNsw6Fzc2ljYSDDqSBzZW1wcmUgbmVjZXNzw6FyaWEsIG7Do28gc2UgcG9kZSBjb25jZWRlciDDoHMgY29uZGnDp8O1ZXMgZGUgS3Vobi1UdWNrZXIgbyBzdGF0dXMgZGUgY29uZGnDp8O1ZXMgbmVjZXNzw6FyaWFzIGEgbWVub3MgcXVlIGN1bXByYW0gdW1hIGNlcnRhIGhpcMOzdGVzZS4gCgoqICoqRUZFSVRPIERFIFJFU1RSScOHw5VFUyBERSBOw4NPLU5FR0FUSVZJREFERSoqCgpDb25zaWRlcmUgdW0gcHJvYmxlbWEgY29tIHJlc3RyacOnw7VlcyBkZSBuw6NvLW5lZ2F0aXZpZGFkZSBuYXMgdmFyacOhdmVpcyBkZSBlc2NvbGhhLCBtYXMgc2VtIG5lbmh1bWEgb3V0cmEgcmVzdHJpw6fDo28uIFBhcmEgbyBjYXNvIGRlIHVtYSB2YXJpw6F2ZWwsIHRlbW9zOgoKJCQKXGJlZ2lue2FsaWduZWR9CiYgXHRleHR7TWF4aW1pemV9CiYgJiBccGk9Zih4X3sxfSkgXFwKJiBcdGV4dHtzLmEufQomICYgeF97MX0gXGdlcSAwIApcZW5ke2FsaWduZWR9CiQkCgpvbmRlIHN1cMO1ZS1zZSBxdWUgYSBmdW7Dp8OjbyAkZiQgw6kgZGlmZXJlbmNpw6F2ZWwuIEVtIHZpc3RhIGRhIHJlc3RyacOnw6NvICR4X3sxfSBcZ2VxIDAkLCBwb2RlbSBzdXJnaXIgdHLDqnMgc2l0dWHDp8O1ZXMuIFByaW1laXJhLCBzZSBvY29ycmVyIHVtIG3DoXhpbW8gbG9jYWwgZGUgJFxwaSQgbm8gaW50ZXJpb3IgZGEgcmVnacOjbyB2acOhdmVsIGRhIGZpZ3VyYSAkKGEpJCBhYmFpeG8sIHRhbCBjb21vIG8gcG9udG8gJEEkLCBlbnTDo28gdGVtb3MgdW1hICpzb2x1w6fDo28gaW50ZXJpb3IqLiBBIGNvbmRpw6fDo28gZGUgcHJpbWVpcmEgb3JkZW0gbmVzdGUgY2FzbyDDqSAkXGZyYWN7ZFxwaX17ZHhfezF9fT1mXnsnfSh4X3sxfSk9MCQsIGEgbWVzbWEgZG8gcHJvYmxlbWEgY2zDoXNzaWNvIGRlIG90aW1pemHDp8Ojby4gU2VndW5kYSwgY29tbyBpbHVzdHJhZG8gcGVsbyBwb250byAkQiQgbmEgZmlndXJhIGFiYWl4bywgdW0gbcOheGltbyBsb2NhbCB0YW1iw6ltIHBvZGUgb2NvcnJlciBubyBlaXhvIHZlcnRpY2FsLCBvbmRlICR4X3sxfT0wJC4gTWVzbW8gbmVzdGUgc2VndW5kbyBjYXNvLCBvbmRlIHRlbW9zIHVtYSAqc29sdcOnw6NvIGRlIGZyb250ZWlyYSosIGEgY29uZGnDp8OjbyBkZSBwcmltZWlyYSBvcmRlbSAkZl57J30oeF97MX0pPTAkIHBlcm1hbmVjZSB2w6FsaWRhLiBDb250dWRvLCBow6EgdW1hIHRlcmNlaXJhIHBvc3NpYmlsaWRhZGUsIG91IHNlamEsIG5vIHByZXNlbnRlIGNvbnRleHRvLCB1bSBtw6F4aW1vIGxvY2FsIHBvZGUgb2NvcnJlciBubyBwb250byAkQyQgb3Ugbm8gcG9udG8gJEQkIGRhIGZpZ3VyYSBhYmFpeG8gcG9ycXVlLCBwYXJhIHNlIHF1YWxpZmljYXIgY29tbyB1bSBtw6F4aW1vIGxvY2FsIG5vIHByb2JsZW1hLCBiYXN0YSBxdWUgbyBwb250byBjYW5kaWRhdG8gc2VqYSBtYWlzIGFsdG8gcXVlIG9zIHBvbnRvcyB2aXppbmhvcyBkZW50cm8gZGEgcmVnacOjbyB2acOhdmVsLiAKCkVtIHZpc3RhIGRlc3RhIMO6bHRpbWEgcG9zc2liaWxpZGFkZSwgbyBwb250byBtw6F4aW1vIGVtIHVtIHByb2JsZW1hIGNvbW8gbyBwcm9wb3N0byBwb2RlIHNlciBjYXJhY3Rlcml6YWRvIG7Do28gYXBlbmFzIHBlbGEgZXF1YcOnw6NvICRmXnsnfSh4X3sxfSk9MCQsIG1hcyB0YW1iw6ltIHBlbGEgZGVzaWd1YWxkYWRlICRmXnsnfSh4X3sxfSk8MCQuIFBvciBvdXRybyBsYWRvLCBub3RlIHF1ZSBhIGRlc2lndWFsZGFkZSBvcG9zdGEgJGZeeyd9KHhfezF9KT4wJCBwb2RlIHNlciBleGNsdcOtZGEgY29tIHNlZ3VyYW7Dp2EsIHBvaXMgZW0gdW0gcG9udG8gb25kZSBhIGluY2xpbmHDp8OjbyBkYSBjdXJ2YSDDqSBhc2NlbmRlbnRlLCBudW5jYSBwb2RlbW9zIHRlciB1bSBtw6F4aW1vIChjb21vIG5vIHBvbnRvICRFJCkuIEFzc2ltLCBwb2RlbW9zIHJlc3VtaXIgYXMgY29uZGnDp8O1ZXMgcGFyYSBxdWUgJHhfezF9JCBkw6ogdW0gbcOheGltbyBsb2NhbCBkZSAkXHBpJCBubyBwcm9ibGVtYSBlbToKCiQkClxiZWdpbnthbGlnbmVkfQpmXnsnfSh4X3sxfSk8MCAgJiYgeF97MX1cZ2VxIDAgJiYgXHRleHR7ZX0gJiYgeF97MX1mXnsnfSh4X3sxfSk9MApcZW5ke2FsaWduZWR9CiQkCgoKYGBge3IgIGVjaG89RkFMU0UsIG91dC53aWR0aCA9ICIzMCUiLCBmaWcuYWxpZ249J3JpZ2h0J30KbGlicmFyeShrbml0cikKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ2ZvdG8xLmpwZycpCmBgYAoKKiAqKkVGRUlUTyBERSBSRVNUUknDh8OVRVMgREUgREVTSUdVQUxEQURFKioKClBvciBzaW1wbGljaWRhZGUsIGVtIHByaW1laXJvIGx1Z2FyIHZhbW9zIHRyYXRhciBkZSB1bWEgcHJvYmxlbWEgY29tIHRyw6pzIHZhcmnDoXZlaXMgZGUgZXNjb2xoYSAoJG49MyQpIGUgZHVhcyByZXN0cmnDp8O1ZXMgKCRtPTIkKToKCiQkClxiZWdpbnthbGlnbmVkfQomIFx0ZXh0e01heGltaXplfQomICYgXHBpID0gZih4X3sxfSx4X3syfSx4X3szfSkgXFwKJiBcdGV4dHtzLmEufQomICYgR157MX0oeF97MX0seF97Mn0seF97M30pIFxsZXEgcl97MX0gXFwgCiYmJiBHXnsyfSh4X3sxfSx4X3syfSx4X3szfSkgXGxlcSByX3syfSBcXAomJiYgeF97MX0seF97Mn0seF97M30gXGdlcSAwClxlbmR7YWxpZ25lZH0KJCQKcXVlLCBjb20gbyBhdXjDrWxpbyBkZSBkdWFzIG5vdmFzIHZhcmnDoXZlaXMgJHNfezF9JCBlICRzX3syfSQsIHBvZGUgc2VyIHRyYW5zZm9ybWFkYSBuYSBmb3JtYSBlcXVpdmFsZW50ZToKCiQkClxiZWdpbnthbGlnbmVkfQomIFx0ZXh0e01heGltaXplfQomICYgXHBpID0gZih4X3sxfSx4X3syfSx4X3szfSkgXFwKJiBcdGV4dHtzLmEufQomICYgR157MX0oeF97MX0seF97Mn0seF97M30pICsgc197MX0gPSByX3sxfSBcXCAKJiYmIEdeezJ9KHhfezF9LHhfezJ9LHhfezN9KSArIHNfezJ9ID0gcl97Mn0gXFwKJiYmIHhfezF9LHhfezJ9LHhfezN9LHNfezF9LHNfezJ9IFxnZXEgMApcZW5ke2FsaWduZWR9CiQkCgpTZSBhcyByZXN0cmnDp8O1ZXMgZGUgbsOjby1uZWdhdGl2aWRhZGUgZXN0aXZlcmVtIGF1c2VudGUsIHBvZGVtb3MsIGVtIGNvbmZvcm1pZGFkZSBjb20gYSBhYm9yZGFnZW0gY2zDoXNzaWNhLCBmb3JtYXIgYSBmdW7Dp8OjbyBMYWdyYW5nZToKCiQkClogPSBmKHhfezF9LHhfezJ9LHhfezN9KSArIFxsYW1iZGFfezF9W3JfezF9LUdeezF9KHhfezF9LHhfezJ9LHhfezN9KSAtIHNfezF9XSArIFxsYW1iZGFfezJ9W3JfezF9LUdeezJ9KHhfezF9LHhfezJ9LHhfezN9KSAtIHNfezJ9XQokJAplIGVzY3JldmVyIGEgY29uZGnDp8OjbyBkZSBwcmltZWlyYSBvcmRlbSBjb21vOgoKJCQKXGZyYWN7ZFp9e2R4X3sxfX09XGZyYWN7ZFp9e2R4X3syfX09XGZyYWN7ZFp9e2R4X3szfX09XGZyYWN7ZFp9e2RzX3sxfX09XGZyYWN7ZFp9e2RzX3syfX09XGZyYWN7ZFp9e2RcbGFtYmRhX3sxfX09XGZyYWN7ZFp9e2RcbGFtYmRhX3syfX09MAokJApNYXMgdmlzdG8gcXVlIGFzIHZhcmnDoXZlaXMgJHhfe2p9JCBlICRzX3tpfSQgdMOqbSBkZSBzZXIgb2JyaWdhdG9yaWFtZW50ZSBuw6NvLW5lZ2F0aXZhcywgYSBjb25kacOnw6NvIGRlIHByaW1laXJhIG9yZGVtIHBhcmEgZXNzYXMgdmFyacOhdmVpcyBkZXZlIHNlciBtb2RpZmljYWRhIGRlIGFjb3JkbyBjb20gbyBwcm9ibGVtYSBkZSBuw6NvLW5lZ2F0aXZpZGFkZS4gT3Ugc2VqYSwKCiQkClxiZWdpbnthbGlnbmVkfQomIFxmcmFje2RafXtkeF97an19IFxsZXEgMCAgJiYgeF97an1cZ2VxIDAgJiYgXHRleHR7ZX0gJiYgeF97an1cZnJhY3tkWn17ZHhfe2p9fT0wIFxcCiYgXGZyYWN7ZFp9e2RzX3tpfX0gXGxlcSAwICAmJiBzX3tpfVxnZXEgMCAmJiBcdGV4dHtlfSAmJiBzX3tpfVxmcmFje2RafXtkc197aX19PTAgXFwKJiBcZnJhY3tkWn17ZCBcbGFtYmRhX3tpfX09MCAmJiBcdGV4dHtwYXJhIGk9MSwyfSAmJiBcdGV4dHtlfSAmJiBcdGV4dHtwYXJhIGo9MSwyLDN9ClxlbmR7YWxpZ25lZH0gCiQkCgpDYWRhIGxpbmhhIGFjaW1hIGVzdMOhIHJlbGFjaW9uYWRhIGEgdW0gdGlwbyBkaWZlcmVudGUgZGUgdmFyacOhdmVsLiBNYXMgcG9kZW1vcyBjb25zb2xpZGFyIGFzIGR1YXMgw7psdGltYXMgbGluaGFzIGUsIG5vIHByb2Nlc3NvLCBlbGltaW5hciBhIG5vdmEgdmFyacOhdmVsICRzX3tpfSQgZGEgY29uZGnDp8OjbyBkZSBwcmltZWlyYSBvcmRlbS4gQ29uc2lkZXJhbmRvIHF1ZSAke2RafS97ZH17c31fe2l9PS1cbGFtYmRhX3tpfSQsIGEgc2VndW5kYSBsaW5oYSBub3MgZGl6IHF1ZSBkZXZlbW9zIHRlciAkLVxsYW1iZGFfe2l9XGxlcTAkLCAkc197aX1cZ2VxMCQgZSAkLXNfe2l9XGxhbWJkYV97aX09MCQsIG91IGRlIG1vZG8gZXF1aXZhbGVudGU6CgokJApcYmVnaW57YWxpZ25lZH0Kc197aX1cZ2VxMCAgJiYgXGxhbWJkYV97aX1cZ2VxMCAmJiBcdGV4dHtlfSAmJiBzX3tpfVxsYW1iZGFfe2l9PTAKXGVuZHthbGlnbmVkfQokJApNYXMgYSB0ZXJjZWlyYSBsaW5oYSBzaWduaWZpY2EgcXVlICRzX3tpfT1yX3tpfS1HXntpfSh4X3sxfSx4X3syfSx4X3szfSkkLiBBc3NpbSwgYSByZXN0cmnDp8OjbyBzZSB0b3JuYToKCiQkClxiZWdpbnthbGlnbmVkfQpyX3tpfS1HXntpfSh4X3sxfSx4X3syfSx4X3szfSlcZ2VxMCAgJiYgXGxhbWJkYV97aX1cZ2VxMCAmJiBcdGV4dHtlfSAmJiBcbGFtYmRhX3tpfVtyX3tpfS1HXntpfSh4X3sxfSx4X3syfSx4X3szfSldPTAKXGVuZHthbGlnbmVkfQokJAoKUG9yIGZpbSwgcG9kZW1vcyBleHByZXNzYXIgYSBjb25kacOnw6NvIGRlIHByaW1laXJhIG9yZGVtIGVtIHVtYSBmb3JtYSBlcXVpdmFsZW50ZSBzZW0gYXMgbm92YXMgdmFyacOhdmVpcy4gVXNhbmRvIG8gc8OtbWJvbG8gJEdee2l9X3tqfSQgcGFyYSBkZW5vdGFyICR7ZEdee2l9fS97ZH17eH1fe2p9JCwgZXNjcmV2ZW1vcyBhZ29yYToKCiQkClxiZWdpbnthbGlnbmVkfQomIFxmcmFje2RafXtkeF97an19ID0gZl97an0gLSAoXGxhbWJkYV97MX1HXnsxfV97an0rXGxhbWJkYV97Mn1HXnsyfV97an0pIFxsZXEgMCAgJiYgeF97an1cZ2VxIDAgJiYgXHRleHR7ZX0gJiYgeF97an1cZnJhY3tkWn17ZHhfe2p9fT0wIFxcCiYgcl97aX0tR157aX0oeF97MX0seF97Mn0seF97M30pXGdlcTAgICYmIFxsYW1iZGFfe2l9XGdlcSAwICYmIFx0ZXh0e2V9ICYmIFxsYW1iZGFfe2l9W3Jfe2l9LUdee2l9KHhfezF9LHhfezJ9LHhfezN9KV09MCAKXGVuZHthbGlnbmVkfSAKJCQKU8OjbyBlc3NhcyBhcyBjb25kacOnw7VlcyBkZSAqKkt1aG4tVHVja2VyKiogcGFyYSBvIHByb2JsZW1hIHByb3Bvc3RvLiAKCiogKipFWEVNUExPKioKClNlIGZvcm11bGFybW9zIG8gcHJvYmxlbWEgZmFtaWxpYXIgZGUgbWF4aW1pemHDp8OjbyBkZSB1dGlsaWRhZGUgc2VndW5kbyBvIG1vZGVsbyBkYSBwcm9ncmFtYcOnw6NvIG7Do28tbGluZWFyLCBwb2RlbW9zIHRlciB1bSBwcm9ibGVtYSBjb20gYSByZXN0cmnDp8OjbyBkZSBkZXNpZ3VhbGRhZGUsIGNvbW8gc2VndWU6CgokJApcYmVnaW57YWxpZ25lZH0KJiBcdGV4dHtNYXhpbWl6ZX0KJiAmIFUgPSB4eSBcXAomIFx0ZXh0e3MuYS59CiYgJiB4ICsgeSBcbGVxIDEwMCBcXCAKJiYmIHggXGxlcSA0MCBcXAomJiYgeCx5IFxnZXEgMApcZW5ke2FsaWduZWR9CiQkCk5vdGUgcXVlIGNvbSBhIHJlc3RyacOnw6NvIGRlIGRlc2lndWFsZGFkZSwgbyBjb25zdW1pZG9yIGrDoSBuw6NvIMOpIG1haXMgb2JyaWdhZG8gYSBnYXN0YXIgdG9kYSBhIHF1YW50aWEgbmEgY29tcHJhIGRvcyBkb2lzIGJlbnMuIEFzc2ltLCBhIGZ1bsOnw6NvIGRlIExhZ3JhbmdlIHNlIHRvcm5hOgoKJCQKWiA9IHh5ICsgXGxhbWJkYV97MX0oMTAwLXgteSkgKyBcbGFtYmRhX3syfSg0MC14KQokJAplIGFzIGNvbmRpw6fDtWVzIGRlIEt1aG4tVHVja2VyIHNlIHRvcm5hbToKCiQkClxiZWdpbnthbGlnbmVkfQomIFpfe3h9ID0geSAtXGxhbWJkYV97MX0gLSBcbGFtYmRhX3syfVxsZXEgMCAgJiYgeFxnZXEgMCAmJiBcdGV4dHtlfSAmJiB4Wl97eH09MCBcXAomIFpfe3l9ID0geCAtXGxhbWJkYV97MX1cbGVxIDAgICYmIHlcZ2VxIDAgJiYgXHRleHR7ZX0gJiYgeVpfe3l9PTAgXFwKJiBaX3tcbGFtYmRhX3sxfX0gPSAxMDAgLXggLXkgXGdlcSAwICAmJiBcbGFtYmRhX3sxfVxnZXEgMCAmJiBcdGV4dHtlfSAmJiBcbGFtYmRhX3sxfVpfe1xsYW1iZGFfezF9fT0wIFxcCiYgWl97XGxhbWJkYV97Mn19ID0gNDAgLXggXGdlcSAwICAmJiBcbGFtYmRhX3syfVxnZXEgMCAmJiBcdGV4dHtlfSAmJiBcbGFtYmRhX3syfVpfe1xsYW1iZGFfezJ9fT0wClxlbmR7YWxpZ25lZH0gCiQkCkEgYWJvcmRhZ2VtIHTDrXBpY2EgcGFyYSByZXNvbHZlciB1bSBwcm9ibGVtYSBkZSBwcm9ncmFtYcOnw6NvIG7Do28tbGluZWFyIMOpIGEgZGUgdGVudGF0aXZhIGUgZXJyby4gUGFyYSBvIHByZXNlbnRlIGV4ZW1wbG8sIG7Do28gZmF6IHNlbnRpZG8gZXhwZXJpbWVudGFyICR4PTAkIG91ICR5PTAkLCBwb2lzIHRlcsOtYW1vcyAkVT14eT0wJC4gUG9ydGFudG8sIHZhbW9zIHN1cG9yIHF1ZSBhbWJvcywgJHgkIGUgJHkkLCBzw6NvIGRpZmVyZW50ZXMgZGUgemVybyBlIGRlZHV6aXIgcXVlICRaX3t4fT1aX3t5fT0wJCBwZWxhIGZvbGdhIGNvbXBsZW1lbnRhciwgbyBxdWUgc2lnbmlmaWNhIHF1ZToKCiQkCnktXGxhbWJkYV97MX0tXGxhbWJkYV97Mn09eC1cbGFtYmRhX3sxfSg9MCkKJCQKZGUgbW9kbyBxdWUgCgokJAp5LVxsYW1iZGFfezJ9PXgKJCQKQWdvcmEsIHN1cG9uaGEgcXVlIGEgcmVzdHJpw6fDo28gZGUgcmFjaW9uYW1lbnRvIHNlamEgbsOjby12aW5jdWxhZG9yYSBuYSBzb2x1w6fDo28sIG8gcXVlIGltcGxpY2EgcXVlICRcbGFtYmRhX3syfT0wJC4gRW50w6NvIHRlbW9zICR4PXkkIGUgbyBvcsOnYW1lbnRvICgkMTAwJCkgcmVzdWx0YSBuYSBzb2x1w6fDo28gZXhwZXJpbWVudGFsICR4PXk9NTAkLiBNYXMgZXNzYSBzb2x1w6fDo28gdmlvbGEgYSByZXN0cmnDp8OjbyBkZSByYWNpb25hbWVudG8gJHhcbGVxNDAkLiBQb3IgY29uc2VndWludGUsIHRlbW9zIGRlIGFkb3RhciBhIGhpcMOzdGVzZSBhbHRlcm5hdGl2YSBkZSBxdWUgYSByZXN0cmnDp8OjbyBkZSByYWNpb25hbWVudG8gw6kgdmluY3VsYWRvcmEgY29tICR4XntcYXN0fT00MCQuIEVudMOjbywgYSByZXN0cmnDp8OjbyBvcsOnYW1lbnTDoXJpYSBwZXJtaXRlIHF1ZSBvIGNvbnN1bWlkb3IgdGVuaGEgJHlee1xhc3R9PTYwJC4gQWzDqW0gZGlzc28sIHZpc3RvIHF1ZSBhIGZvbGdhIGNvbXBsZW1lbnRhciBkZXRlcm1pbmEgcXVlICRaX3t4fT1aX3t5fT0wJCwgcG9kZW1vcyBjYWxjdWxhciwgZGUgaW1lZGlhdG8sIHF1ZSAkXGxhbWJkYV97MX1ee1xhc3R9PTQwJCBlICRcbGFtYmRhX3syfV57XGFzdH09MjAkCgojIyMjIyAqKlJFU09MVkVORE8gUFJPQkxFTUFTIERFIFBST0dSQU1Bw4fDg08gTsODTy1MSU5FQVIgTk8gUioqCgpObyBSLCB0ZW1vcyBvIHBhY290ZSBgUnNvbG5wYCBxdWUgZm9ybmVjZSBhIGZ1bsOnw6NvIGBzb2xucCgpYCBxdWUgcmVzb2x2ZSBwcm9ibGVtYXMgZ2VyYWlzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIuIEFzc2ltLCB2YW1vcyB1c2FyIGVzdGUgcGFjb3RlIHBhcmEgcmVzb2x2ZXIgZXhlbXBsb3MgZGUgcHJvYmxlbWFzIGRlIHByb2dyYW1hw6fDo28gbsOjby1saW5lYXIgbm8gUi4KCjEuIENvbnNpZGVyZSBvIHNlZ3VpbnRlIHByb2JsZW1hIGRlIG1pbmltaXphw6fDo28gKFByb2dyYW1hw6fDo28gUXVhZHLDoXRpY2EpOgoKJCQKXGJlZ2lue2FsaWduZWR9CiYgXHRleHR7TWluaW1pemV9CiYgJiBmKHgseSkgPSA0eF57Mn0gKyAxMHleezJ9IFxcCiYgXHRleHR7cy5hLn0KJiAmIDAgXGxlcSB4XnsyfSArIHleezJ9IFxsZXEgNApcZW5ke2FsaWduZWR9CiQkClRhbCBwcm9ibGVtYSBwb2RlIHNlIGFkaWNpb25hZG8gbm8gUiwgZGEgc2VndWludGUgZm9ybWE6CgpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICAgICBQQUNPVEVTICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBJbnN0YWxhciBwYWNvdGVzIG5lY2Vzc8OhcmlvcyAKIyBpbnN0YWxsLnBhY2thZ2VzKCJSc29sbnAiKQoKIyBDYXJyZWdhciBwYWNvdGVzIG5lY2Vzc8OhcmlvcyBwYXJhIG8gcmVzdGFudGUgZG8gZG9jdW1lbnRvCnN1cHByZXNzTWVzc2FnZXMocmVxdWlyZShSc29sbnApKQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyAgICAgUFJPQk1FTEEgICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgRnVuw6fDo28gT2JqZXRpdm8KZm4gPC0gZnVuY3Rpb24oeCkgeyAKICA0KnhbMV1eMiArIDEwKnhbMl1eMiArNQp9CgojIFJlc3RyacOnw6NvIDE6IHheMit5XjIgPD0gNAppbmVxMSA8LSBmdW5jdGlvbih4KSB7IAogIHoxPXhbMV1eMiArIHhbMl1eMgogIHJldHVybihjKHoxKSkKfQoKIyBMaW1pdGUgaW5mZXJpb3IgKGxvd2VyKSBlIHN1cGVyaW9yICh1cHBlcikgZGFzIHJlc3RyacOnw7VlcyBkZSBkZXNpZ3VhbGRhZGUKbGggPC0gYygwKQp1aCA8LSBjKDQpCgojIFZhbG9yZXMgaW5pY2lhaXMgcGFyYSBvIGFsZ29yaXRtbwp4MCA8LSBjKDEsIDEpIAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyAgICAgU09MVcOHw4NPICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBCYXNpY2FtZW50ZSwgdXNhbW9zIGEgZnVuw6fDo28gc29sbnAgZG8gcGFjb3RlIFJzb2xucCBjb20gb3Mgc2VndWludGVzIHBhcsOibWV0cm9zOgojIHBhcnM6IHF1ZSByZWNlYmUgbyB2ZXRvciBkZSBwYXLDom1ldHJvcyBpbmljaWFpcyBwYXJhIGEgc29sdcOnw6NvCiMgZnVuOiBxdWUgcmVjZWJlIGEgZnVuw6fDo28gb2JqZXRpdm8KIyBpbmVxZnVuOiBxdWUgcmVjZWJlIGEgZnVuw6fDo28gZGUgcmVzdHJpw6fDo28KIyBpbmVxTEI6IHF1ZSByZWNlYmUgbyBsaW1pdGUgaW5mZXJpb3IgZGEgcmVzdHJpw6fDo28gZGUgZGVzaWd1YWxkYWRlCiMgaW5lcVVCOiBxdWUgcmVjZWJlIG8gbGltaXRlIHN1cGVyaW9yIGRhIHJlc3RyacOnw6NvIGRlIGRlc2lndWFsZGFkZQojIG1haXMgb3DDp8O1ZXMgZGEgZnVuw6fDo28gcG9kZW0gc2VyIG9idGlkYXMgcG9yIG1laW8gZG8gaGVscChzb2xucCkKCnNvbHVjYW8ucHJvYmxlbWEgPC0gUnNvbG5wOjpzb2xucChwYXJzID0geDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW4gPSBmbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZXFmdW4gPSBpbmVxMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZXFMQiA9IGxoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5lcVVCPXVoKQpgYGAKCkNvbW8gcmVzdWx0YWRvLCB0ZW1vcyBxdWUgbyBhbGdvcml0bW8gcHJlY2lzb3UgZGUgMTUgaXRlcmHDp8O1ZXMgcHJhIGVuY29udHJhciBhIHNvbHXDp8OjbyBkbyBwcm9ibGVtYS4gUG9kZW1vcyB2ZXJpZmljYXIgbyByZXN1bHRhZG8gZGEgZnVuw6fDo28gb2JqZXRpdm8gZW0gY2FkYSB1bWEgZGFzIGl0ZXJhw6fDtWVzLiBQYXJhIHRhbnRvLCBiYXN0YSBmYXplcjoKCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9CnNvbHVjYW8ucHJvYmxlbWEkdmFsdWVzCmBgYAoKTyBxdWUgbm9zIG1vc3RyYSBxdWUgYSBwYXJ0aXIgZGEgaXRlcmHDp8OjbyAxNCBhIGZ1bsOnw6NvIG9iamV0aXZvIG7Do28gYWx0ZXJvdSBzZXUgdmFsb3IgZSBwb3IgaXNzbyBvIGFsZ29yaXRtbyBwYXJvdSBuYSBpdGVyYcOnw6NvIDE1LiBKw6EgYSBzb2x1w6fDo28gcGFyYSAkeF97MX0kIGUgJHhfezJ9JCBwb2RlIHNlciAKCgpQb2RlbW9zIGFsdGVyYXIgYSB0b2xlcsOibmNpYSBwYXJhIHF1ZSBvIGFsZ29yaW1vIHBhcmUgYXMgaXRlcmHDp8O1ZXMgb3UgYXTDqSBtZXNtbyBvcHRhciBwb3IgbsOjbyBtb3N0cmFyIG9zIHJlc3VsdGFkb3MgZGUgY2FkYSBpdGVyYcOnw6NvLiBQYXJhIHRhbnRvLCBiYXN0YSBhZGljaW9uYXIgYSBvcMOnw6NvIGBjb250cm9sYCBjb21vIGFiYWl4bzoKCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGV2YWw9RkFMU0V9CiMgQWRpY2lvbmFyIGEgdG9sZXLDom5jaWEgcGFyYSBjb252ZXJnw6puY2lhIGUgbsOjbyBtb3N0cmFyIG9zIHJlc3VsdGFkb3MKIyBkZSBjYWRhIGl0ZXJhw6fDo28gbm8gY29uc29sZSBkbyBSICh0cmFjZT0wKQpjdHJsIDwtIGxpc3QoVE9MID0gMWUtMTUsIHRyYWNlID0gMCkKCgpzb2x1Y2FvLnByb2JsZW1hMiA8LSBSc29sbnA6OnNvbG5wKHBhcnMgPSB4MCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZuLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5lcWZ1biA9IGluZXExLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5lcUxCID0gbGgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmVxVUI9dWgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gY3RybCkKCiMgUGFyYSB2ZXIgb3MgdmFsb3JlIGRhIGZ1bsOnw6NvIG9iamV0aXZvIGVtIGNhZGEgaXRlcmHDp8Ojbwpzb2x1Y2FvLnByb2JsZW1hMiR2YWx1ZXMKCiMgUGFyYSBzYWJlciBhIHNvbHXDp8OjbyAKc29sdWNhby5wcm9ibGVtYTIkcGFycwpgYGAKCgoyLiBPdXRybyBleGVtcGxvOgoKJCQKXGJlZ2lue2FsaWduZWR9CiYgXHRleHR7TWluaW1pemV9CiYgJiBmKFxib2xkc3ltYm9se3h9KSA9IC14X3sxfXhfezJ9eF97M30gXFwKJiBcdGV4dHtzLmEufQomICYgNHhfezF9eF97Mn0gKyAyeF97Mn14X3szfSArIDJ4X3szfXhfezF9ID0gMTAwIFxcCiYmJiAxIFxsZXEgeF97aX0gXGxlcTEwICYgXHRleHR7aT0xLDIsM30KXGVuZHthbGlnbmVkfQokJAoKVGFsIHByb2JsZW1hIHBvZGUgc2UgYWRpY2lvbmFkbyBubyBSLCBkYSBzZWd1aW50ZSBmb3JtYToKCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgIFBST0JNRUxBICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEZ1bsOnw6NvIE9iamV0aXZvCmZuMiA8LSBmdW5jdGlvbih4LCAuLi4pewogIC14WzFdKnhbMl0qeFszXQp9CgojIFJlc3RyacOnw6NvIDE6IAplcW4gPC0gZnVuY3Rpb24oeCwgLi4uKXsKICAgIDQqeFsxXSp4WzJdKzIqeFsyXSp4WzNdKzIqeFszXSp4WzFdCn0KCiMgTGltaXRlIGRhIHJlc3RyacOnw6NvCmNvbnN0cmFpbnRzIDwtIGMoMTAwKQoKIyBMaW1pdGUgaW5mZXJpb3IgKGxvd2VyKSBlIHN1cGVyaW9yICh1cHBlcikgZGEgcmVzdHJpw6fDo28gZGUgZGVzaWd1YWxkYWRlCmx4IDwtIHJlcCgxLCAzKQp1eCA8LSByZXAoMTAsIDMpCgojIFZhbG9yZXMgaW5pY2lhaXMgcGFyYSBvIGFsZ29yaXRtbwpwYXJzIDwtIGMoMiwgMSwgNykKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgIFNPTFXDh8ODTyAgICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgUmVzdHJpw6fDtWVzIGRlIHRvbGVyw6JuY2lhIGUgbsOjbyBtb3N0cmFyIG8gcmVzdWx0YWRvIGRlIGNhZGEgaXRlcmHDp8OjbyBubyBjb25zb2xlCmN0cmwyIDwtIGxpc3QoVE9MID0gMWUtNiwgdHJhY2UgPSAwKQoKIyBCYXNpY2FtZW50ZSwgdXNhbW9zIGEgZnVuw6fDo28gc29sbnAgZG8gcGFjb3RlIFJzb2xucCBjb20gb3Mgc2VndWludGVzIHBhcsOibWV0cm9zOgojIHBhcnM6IHF1ZSByZWNlYmUgbyB2ZXRvciBkZSBwYXLDom1ldHJvcyBpbmljaWFpcyBwYXJhIGEgc29sdcOnw6NvCiMgZnVuOiBxdWUgcmVjZWJlIGEgZnVuw6fDo28gb2JqZXRpdm8KIyBlcWZ1bjogcXVlIHJlY2ViZSBhIGZ1bsOnw6NvIGRlIHJlc3RyacOnw6NvIGRlIGlndWFsZGFkZQojIGVxQjogYSBpZ3VhbGRhZGUgZGEgcmVzdHJpw6fDo28gZGUgaWd1YWxkYWRlCiMgTEI6IGxpbWl0ZSBpbmZlcmlvciBkYSByZXN0cmnDp8OjbyBkZSBkZXNpZ3VhbGRhZGUKIyBVQjogbGltaXRlIHN1cGVyaW9yIGRhIHJlc3RyacOnw6NvIGRlIGRlc2lndWFsZGFkZQojIGNvbnRyb2w6IGFzIG9ww6fDtWVzIGRlIHRvbGVyw6JuY2lhIGUgbW9zdHJhciByZXN1bHRhZG9zCiMgbWFpcyBvcMOnw7VlcyBkYSBmdW7Dp8OjbyBwb2RlbSBzZXIgb2J0aWRhcyBwb3IgbWVpbyBkbyBoZWxwKHNvbG5wKQoKc29sdWNhby5wcm9ibGVtYTIgPC0gUnNvbG5wOjpzb2xucChwYXJzID0gcGFycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZuMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVxZnVuID0gZXFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcUIgPSBjb25zdHJhaW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTEIgPSBseCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVUIgPSB1eCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGN0cmwpCgojIFZhbG9yZXMgZGEgZnVuw6fDo28gb2JqZXRpdm8gZW0gY2FkYSBpdGVyYcOnw6NvCnNvbHVjYW8ucHJvYmxlbWEyJHZhbHVlcwoKIyBTb2x1w6fDo28gIApzb2x1Y2FvLnByb2JsZW1hMiRwYXJzCmBgYAoKIyMjIyAqKlJFRkVSw4pOQ0lBUyoq