Algoritmos y Estructuras de Datos 1
Especificaciones, Verificaciones y Derivaciones

Especificaciones, Verificaciones y Derivaciones

Construcción de programas y paradigmas

El proceso de construcción de programas se establece de la siguiente forma:

Problema

(Impreciso/Informal, poco detallado)

Especificación

(Preciso/Formal, poco detallado)

Derivación

(Crear la definición)

Verificación

(Demostrar su validez)

Programa

(Preciso/Formal, detallado)


La programación funcional, se basa en la definición de funciones y el cálculo/reducción de expresiones.

Podemos resolver problemas a través de funciones, y las especificaciones tendrán la siguiente estructura:

  • 1) Nombre de la función
  • 2) Tipo de la función (Input / Output)
  • 3) Predicado que indica qué debe satisfacer la función.

Ejemplo: quisiera saber si un número es impar

  • 1) esImparesImpar
  • 2) IntBoolInt \to Bool
  • 3) mod  x  20mod \; x \; 2 \neq 0

Nuestro programa sería:

 esImpar:IntBool  esImpar.x  mod  x  20\begin{array}{l} \Big\vert\ esImpar : Int \to Bool \\ \overline{\Big\vert \; esImpar.x \doteq } \; mod \; x \; 2 \neq 0 \end{array}

Y también podemos definirlo en Haskell:

esImpar :: Int -> Bool
esImpar x = mod x 2 /= 0

Especificaciones (PF)

Suponiendo que sabemos la definición de un programa dado:

 sum:[Num]Num  sum.[]0 sum.(xxs)x+sum.xs\begin{array}{l} \Big\vert\ sum : [Num] \to Num \\ \overline{\Big\vert \; sum.[] \doteq 0} \\ \Big\vert\ sum.(x \triangleright xs) \doteq x + sum.xs \end{array}

Por la definición de la función, podemos escribir una especificación mediante una expresión cuantificada:

sum.xs=  i:0i<#xs:xs.i  sum.xs = \bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle

Ya tenemos una una descripción formal de la tarea que el programa tiene que realizar

Derivaciones (PF)

Podemos no disponer de la definición de la función, pero sí de una especificación. En este caso, podemos derivar la definición de la función a partir de la especificación.

Por ejemplo, para encontrar el programa de la función sumsum a partir de la especificación:

sum.xs=  i:0i<#xs:xs.i  sum.xs = \bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle

Caso base (cuanto vale sum.[]sum.[])

sum.[]={ Especificacioˊn de sum  }  i:0i<#[]:[].i  ={ Definicioˊn de #  }  i:0i<0:[].i  ={ Aritmeˊtica }  i:False:[].i  ={ Rango vacıˊ}0\begin{array}{ll} sum.[] \\ \\ = \{ \textnormal{ Especificación de } sum \; \} \\ \\ \bigl \langle \; \sum i : 0 \leq i < \# [] : [].i \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \# \; \} \\ \\ \bigl \langle \; \sum i : 0 \leq i < 0 : [].i \; \bigr \rangle \\ \\ = \{ \textnormal{ Aritmética } \} \\ \\ \bigl \langle \; \sum i : False : [].i \; \bigr \rangle \\ \\ = \{ \textnormal{ Rango vacío } \} \\ \\ 0 \end{array}

Por lo tanto, sum.[]=0sum.[] = 0

Paso inductivo (cuanto vale sum.(xxs)sum.(x \triangleright xs))

HI:sum.xs=  i:0i<#xs:xs.i  HI : sum.xs = \bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle sum.(xxs)={ Especificacioˊn de sum  }  i:0i<#(xxs):(xxs).i  ={ Definicioˊn de #  }  i:0i<1+#xs:(xxs).i  ={ Separacioˊn de un teˊrmino }(xxs).0+  i:0i<#xs:(xxs).(i+1)  ={ Definicioˊn de .  }x+  i:0i<#xs:xs.i  ={ Hipoˊtesis inductiva }x+sum.xs\begin{array}{ll} \underline{sum.(x \triangleright xs)} \\ \\ = \{ \textnormal{ Especificación de } sum \; \} \\ \\ \bigl \langle \; \sum i : 0 \leq i < \underline{\# (x \triangleright xs)} : (x \triangleright xs).i \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \# \; \} \\ \\ \underline{\bigl \langle \; \sum i : 0 \leq i < 1 + \# xs : (x \triangleright xs).i \; \bigr \rangle \\} \\ \\ = \{ \textnormal{ Separación de un término } \} \\ \\ \underline{(x \triangleright xs).0} + \bigl \langle \; \sum i : 0 \leq i < \# xs : \underline{(x \triangleright xs).(i + 1)} \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } . \; \} \\ \\ x + \underline{\bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle} \\ \\ = \{ \textnormal{ Hipótesis inductiva } \} \\ \\ x + sum.xs \end{array}

Por lo tanto, sum.(xxs)=x+sum.xssum.(x \triangleright xs) = x + sum.xs

El programa sería:

 sum:[Num]Num  sum.[]0 sum.(xxs)x+sum.xs\begin{array}{l} \Big\vert\ sum : [Num] \to Num \\ \overline{\Big\vert \; sum.[] \doteq 0} \\ \Big\vert\ sum.(x \triangleright xs) \doteq x + sum.xs \end{array}

Podemos recurrir a otras técnicas para derivar, estas se encuentran más abajo.

Ejercicios - Derivaciones (PF)

1.

Derivar la función pin8pin8 a partir de la especificación (donde prodprod es una función que devuelve el producto de los elementos de una lista):

pin8.xs=  as,bs:xs=as    bs:prod.as=8  pin8.xs = \bigl \langle \; \exists as, bs : xs = as \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle

Comenzando por la especificación, evaluamos el caso base, xs=[]xs = []:

pin8.[]={ Especificacioˊn de pin8  }  as,bs:[]=asbs:prod.as=8  ={ Propiedad de ⧺  }  as,bs:as=[]bs=[]:prod.as=8  ={ Definicioˊn de as  }  as,bs:[]=asbs:prod.[]=8  ={ Evaluˊo el Teˊrmino }prod.[]=8={ Definicioˊn de prod  }1=8={ Aritmeˊtica }False\begin{array}{ll} \underline{pin8}.[] \\ \\ = \{ \textnormal{ Especificación de } pin8 \; \} \\ \\ \bigl \langle \; \exists as, bs : \underline{[] = as ⧺ bs} : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Propiedad de } ⧺ \; \} \\ \\ \bigl \langle \; \exists as, bs : as = [] \land bs = [] : prod.\underline{as} = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } as \; \} \\ \\ \bigl \langle \; \underline{\exists as, bs : [] = as ⧺ bs : prod.[] = 8} \; \bigr \rangle \\ \\ = \{ \textnormal{ Evalúo el Término } \} \\ \\ \underline{prod.[]} = 8 \\ \\ = \{ \textnormal{ Definición de } prod \; \} \\ \\ \underline{1 = 8} \\ \\ = \{ \textnormal{ Aritmética } \} \\ \\ False \end{array}

Por lo tanto, pin8.[]=Falsepin8.[] = False

Para el Paso inductivo, seguimos con xs=(xxs)xs = (x \triangleright xs):

pin8.(xxs)={ Especificacioˊn de pin8  }  as,bs:(xxs)=as    bs:prod.as=8  ={ Posibles valores de as  }  as,bs:(xxs)=(as=[]as[])    bs:prod.as=8  ={ Particioˊn de Rango   }  as,bs:(xxs)=[]    bs:prod.as=8    as,bs:(xxs)=as    bs:prod.as=8  ={ Definicioˊn de , Cambio de variable: as(aas)}  as,bs:(xxs)=bs:prod.as=8    as,bs:(xxs)=(aas)    bs:prod.as=8  ={ Rango Unitario, Propiedad de las []}(xxs)=bs      as,bs:x=axs=as    bs:prod.as=8  ={ Eliminacioˊn de una variable   }(xxs)=bs      as,bs:xs=as    bs:prod.as=8  ={ Hipoˊtesis Inductiva }(xxs)=bs    pin8.xs\begin{array}{ll} \underline{pin8}.(x \triangleright xs) \\ \\ = \{ \textnormal{ Especificación de } pin8 \; \} \\ \\ \bigl \langle \; \exists as, bs : (x \triangleright xs) = \underline{as} \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Posibles valores de } as \; \} \\ \\ \bigl \langle \; \exists as, bs : (x \triangleright xs) = \underline{(as = [] \lor as \neq [])} \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Partición de Rango } \; \} \\ \\ \bigl \langle \; \exists as, bs : (x \triangleright xs) = \underline{[]} \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle \\ \lor \\ \bigl \langle \; \exists as, bs : (x \triangleright xs) = \underline{as} \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \textnormal{⧺}, \textnormal{ Cambio de variable: } as \rightarrow (a \triangleright as) \} \\ \\ \bigl \langle \; \exists as, bs : \underline{(x \triangleright xs) = bs} : prod.as = 8 \; \bigr \rangle \\ \lor \\ \bigl \langle \; \exists as, bs : \underline{(x \triangleright xs) = (a \triangleright as) \textnormal{\;⧺\;} bs} : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Rango Unitario, Propiedad de las } [] \} \\ \\ (x \triangleright xs) = bs \; \lor \; \bigl \langle \; \exists as, bs : \underline{x = a} \land xs = as \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle \\ \\ = \{ \textnormal{ Eliminación de una variable }\; \} \\ \\ (x \triangleright xs) = bs \; \lor \; \underline{\bigl \langle \; \exists as, bs : xs = as \textnormal{\;⧺\;} bs : prod.as = 8 \; \bigr \rangle} \\ \\ = \{ \textnormal{ Hipótesis Inductiva } \} \\ \\ (x \triangleright xs) = bs \; \lor \; pin8.xs \end{array}

Por lo tanto, pin8.(xxs)=(xxs)=bs    pin8.xspin8.(x \triangleright xs) = (x \triangleright xs) = bs \; \lor \; pin8.xs


Análisis por casos (PF)

Supongamos que nuestro programa tiene la siguiente especificación:

sum_par.n+  i:0inpar.i:i  sum \_ par.n + \bigl \langle \; \sum i : 0 \leq i \leq n \land par.i : i \; \bigr \rangle

Y en nuestro paso inductivo (n+1)(n + 1) llegamos a la siguiente expresión:

sum_par.n+  i:i=n+1par.(n+1):i  sum \_ par.n + \bigl \langle \; \sum i : i = n + 1 \land par.(n + 1) : i \; \bigr \rangle

Observemos que la expresión par.(n+1)par.(n + 1) puede ser verdadera o falsa, por lo que debemos analizar ambos casos:

Caso 1: par.(n+1)par.(n + 1)

sum_par.n+  i:i=n+1par.(n+1):i  ={  Caso 1:  par.(n+1)  }sum_par.n+  i:i=n+1True:i  ...sum_par.n+n+1\begin{array}{ll} sum \_ par.n + \bigl \langle \; \sum i : i = n + 1 \land \underline{par.(n + 1)} : i \; \bigr \rangle \\ \\ = \{ \; \textnormal{Caso 1:} \; par.(n + 1) \; \} \\ \\ sum \_ par.n + \bigl \langle \; \sum i : i = n + 1 \land True : i \; \bigr \rangle \\ \\ ... \\ \\ sum \_ par.n + n + 1 \end{array}

Caso 2: ¬par.(n+1)\neg par.(n + 1)

sum_par.n+  i:i=n+1par.(n+1):i  ={  Caso 2:  ¬par.(n+1)  }sum_par.n+  i:i=n+1False:i  ...sum_par.n\begin{array}{ll} sum \_ par.n + \bigl \langle \; \sum i : i = n + 1 \land \underline{par.(n + 1)} : i \; \bigr \rangle \\ \\ = \{ \; \textnormal{Caso 2:} \; \neg par.(n + 1) \; \} \\ \\ sum \_ par.n + \bigl \langle \; \sum i : i = n + 1 \land False : i \; \bigr \rangle \\ \\ ... \\ \\ sum \_ par.n \end{array}

Nuestra definición final sería:

 sum_par:NumNum  sum_par.00 sum_par.(n+1)( □  par.(n+1)sum_par.n+n+1 □  ¬par.(n+1)sum_par.n )\begin{array}{l} \Big\vert\ sum \_ par : Num \to Num \\ \overline{\Big\vert \; sum \_ par.0 \doteq 0} \\ \Big\vert\ sum \_ par.(n + 1) \doteq ( \\ \Big\vert\ □ \; par.(n+1) → sum \_ par.n + n + 1 \\ \Big\vert\ □ \; \neg par.(n+1) → sum \_ par.n \\ \Big\vert\ ) \end{array}

Modularización (PF)

Supongamos que nuestro programa tiene la siguiente especificación:

f.x.n=  i:0in:xi  f.x.n = \bigl \langle \; \sum i : 0 \leq i \leq n : x^i \; \bigr \rangle

Y en nuestro paso inductivo (n+1)(n + 1) llegamos a la siguiente expresión:

f.x.n+xnf.x.n + \textcolor{darkred}{x^n}

La expresión xnx^n tiene sentido en el lenguaje de la matemática, no de los programas.
Podemos modularizar la expresión derivando otra función tal que:

exp.x.n=xnexp.x.n = x^n

Tras derivarla obtenemos:

 exp:NumNumNum  exp.x.01 exp.x.(n+1)nexp.x.n\begin{array}{l} \Big\vert\ exp : Num \to Num \to Num \\ \overline{\Big\vert \; exp.x.0 \doteq 1} \\ \Big\vert\ exp.x.(n + 1) \doteq n * exp.x.n \end{array}

Y podemos reemplazar la expresión en nuestra definición:

 f:NumNumNum  f.x.0x f.x.(n+1)f.x.n+exp.x.n\begin{array}{l} \Big\vert\ f : Num \to Num \to Num \\ \overline{\Big\vert \; f.x.0 \doteq x} \\ \Big\vert\ f.x.(n + 1) \doteq f.x.n + exp.x.n \end{array}

Generalización (PF)

Supongamos que nuestro programa tiene la siguiente especificación:

psum.xs=  i:0i<#xs:sum.(xsi)0  psum.xs = \bigl \langle \; \forall i : 0 \leq i < \# xs : sum.(xs↑i) \geq 0 \; \bigr \rangle

Al seguir en el paso inductivo (xxs)(x \triangleright xs), llegamos a la siguiente expresión:

psum.(xxs)={ Especificacioˊn de psum}  i:0i<#(xxs):sum.((xxs)i)0  ={ Definicioˊn de #}  i:0i<1+#xs:sum.((xxs)i)0  ={ Aritmeˊtica }  i:i=01i<#xs+1:sum.((xxs)i)0  ={ Particioˊn de Rango }  i:i=0:sum.((xxs)i)0        i:1i<#xs+1:sum.((xxs)i)0  ={ Rango Unitario, Cambio de Variable: i ← i + 1 }sum.((xxs)0)0      i:1i<#xs+1:sum.((xxs)(i+1))0  ={ Definicioˊn de , Aritmeˊtica }sum.[]0  i:0i<#xs:sum.((x(xsi)))0  ={ Definicioˊn de sum}00  i:0i<#xs:x+sum.(xsi)0  ={ Aritmeˊtica, Elemento neutro de }  i:0i<#xs:x+sum.(xsi)0  \begin{array}{ll} \underline{psum}.(x \triangleright xs) \\ \\ = \{ \textnormal{ Especificación de } psum \} \\ \\ \bigl \langle \; \forall i : 0 \leq i < \underline{\# (x \triangleright xs)} : sum.((x \triangleright xs)↑i) \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \# \} \\ \\ \bigl \langle \; \forall i : \underline{0 \leq i < 1 + \# xs} : sum.((x \triangleright xs)↑i) \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Aritmética } \} \\ \\ \bigl \langle \; \forall i : \underline{i = 0 \lor 1 \leq i < \# xs + 1} : sum.((x \triangleright xs)↑i) \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Partición de Rango } \} \\ \\ \underline{\bigl \langle \; \forall i : i = 0 : sum.((x \triangleright xs)↑i) \geq 0 \; \bigr \rangle \; \land \; \bigl \langle \; \forall i : 1 \leq i < \# xs + 1 : sum.((x \triangleright xs)↑i) \geq 0 \; \bigr \rangle} \\ \\ = \{ \textnormal{ Rango Unitario, Cambio de Variable: i ← i + 1 } \} \\ \\ sum.((\underline{x \triangleright xs)↑0}) \geq 0 \; \land \; \bigl \langle \; \forall i : 1 \leq i < \# xs + 1 : sum.(\underline{(x \triangleright xs)↑(i + 1)}) \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } ↑, \textnormal{ Aritmética } \} \\ \\ \underline{sum.[]} \geq 0 \land \bigl \langle \; \forall i : 0 \leq i < \# xs : \underline{sum.((x \triangleright (xs↑i)))} \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } sum \} \\ \\ \underline{0 \geq 0} \land \bigl \langle \; \forall i : 0 \leq i < \# xs : x + sum.(xs↑i) \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Aritmética, Elemento neutro de } \land \} \\ \\ \bigl \langle \; \forall i : 0 \leq i < \# xs : x + sum.(xs↑i) \geq 0 \; \bigr \rangle \end{array}

No aplicar nuestra Hipótesis Inductiva, ya que tenemos:

  i:0i<#xs:sum.(xsi)0    (HI)  i:0i<#xs:x+sum.(xsi)0  \begin{array}{ll} \bigl \langle \; \forall i : 0 \leq i < \# xs : sum.(xs↑i) \geq 0 \; \bigr \rangle \; (HI) \\ \\ \bigl \langle \; \forall i : 0 \leq i < \# xs : \textcolor{darkred}{x} + sum.(xs↑i) \geq 0 \; \bigr \rangle \end{array}

Podemos generalizar psumpsum definiendo una nueva función gpsumgpsum, de forma tal que:

gpsum.n.xs=  i:0i<n:n+sum.(xsi)0  gpsum.n.xs = \bigl \langle \; \forall i : 0 \leq i < n : \textcolor{darkred}{n} + sum.(xs↑i) \geq 0 \; \bigr \rangle

Podemos decir que psum.xs=gpsum.0.xspsum.xs = gpsum.0.xs, ya que:

gpsum.0.xs={ Especificacioˊn de gpsum}  i:0i<0:0+sum.(xsi)0  ={ Aritmeˊtica }  i:0i<0:sum.(xsi)0  ={ Especificacioˊn de psum}psum.xs\begin{array}{ll} \underline{gpsum}.0.xs \\ \\ = \{ \textnormal{ Especificación de } gpsum \} \\ \\ \bigl \langle \; \forall i : 0 \leq i < \underline{0} : \underline{0 + sum.(xs↑i)} \geq 0 \; \bigr \rangle \\ \\ = \{ \textnormal{ Aritmética } \} \\ \\ \underline{\bigl \langle \; \forall i : 0 \leq i < 0 : sum.(xs↑i) \geq 0 \; \bigr \rangle} \\ \\ = \{ \textnormal{ Especificación de } psum \} \\ \\ psum.xs \end{array}  psum:[Num]Bool  psum.xsgpsum.0.xs\begin{array}{l} \Big\vert\ psum : [Num] \to Bool \\ \overline{\Big\vert \; psum.xs} \doteq gpsum.0.xs \end{array}

Una vez derivado gpsumgpsum, tendremos dos programas finales:

 gpsum:Num[Num]Bool  gpsum.n.[]... gpsum.n.(xxs)...\begin{array}{l} \Big\vert\ gpsum : Num \to [Num] \to Bool \\ \overline{\Big\vert \; gpsum.n.[]} \doteq ... \\ \Big\vert\ gpsum.n.(x \triangleright xs) \doteq ... \end{array}  psum:[Num]Bool  psum.xsgpsum.0.xs\begin{array}{l} \Big\vert\ psum : [Num] \to Bool \\ \overline{\Big\vert \; psum.xs} \doteq gpsum.0.xs \end{array}

Esquemas de Inducción

En algunos casos los esquemas inductivos convencionales no son los necesarios para derivar.

En el caso de la inducción con naturales, tenemos:

Inducción Básica:

f.0?f.(n+1)?f.0 \doteq ? \\ f.(n + 1) \doteq ?

Inducción a lo Fibonacci:

fib.00fib.11fib.(n+2)fib.(n+1)+fib.nfib.0 \doteq 0 \\ fib.1 \doteq 1 \\ fib.(n + 2) \doteq fib.(n + 1) + fib.n

En el caso de la inducción con listas, tenemos:

Inducción básica: (sumsum, prodprod, etc.)

f.[]?f.(xxs)?f.[] \doteq ? \\ f.(x \triangleright xs) \doteq ?

Inducción con dos o más elementos: (funciones igualesiguales, minimominimo y crecientecreciente)

f.[]?f.[x]?f.(xyxs)?f.[] \doteq ? \\ f.[x] \doteq ? \\ f.(x \triangleright y \triangleright xs) \doteq ?

Ejemplo:

minimo.xs=  Min  i:0i<#xs:xs.iminimo.xs = \bigl \langle \; \textnormal{Min} \; i : 0 \leq i < \# xs : xs.i \bigr \rangle

Si derivamos y el caso base es [][] , tendremos como resultado \infty.
Necesitamos reemplazar el caso base por [x][x] y el Paso inductivo por (xyxs)(x \triangleright y \triangleright xs).


Segmentos de listas

Podemos buscar un segmento inicial de una lista derivando la siguiente especificación.

Q.xs.ys=  bs::ys=xs    bs  Q.xs.ys = \bigl \langle \; \exists bs :: ys = xs \textnormal{\;⧺\;} bs \; \bigr \rangle

Para derivarlo, nuestro esquema inductivo debe ser el siguiente:

Caso Base 1: (xs=[],ysxs = [], ys)

Caso Base 2: (xs,ys=[]xs, ys = [])

Paso Inductivo: (xxs,yysx \triangleright xs, y \triangleright ys)

Verificación (PF)

Podemos demostrar que xs::P.xs\bigl \langle \forall xs :: P.xs \bigr \rangle

Cumple con:

P.xs:sum.xs=  i:0i<#xs:xs.i  P.xs : sum.xs = \bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle

Para lograrlo podemos utilizar inducción matemática o inducción estructural sobre listas (en este caso, la segunda):

Caso base: (xs=[]xs = [])

Debemos demostrar que:

P.[]:sum.[]=  i:0i<#[]:[].i  P.[] : sum.[] = \bigl \langle \; \sum i : 0 \leq i < \# [] : [].i \; \bigr \rangle

Para ello podemos comenzar del lado derecho:

  i:0i<#[]:[].i  ={ Definicioˊn de #  }  i:0i<0:[].i  ={ Aritmeˊtica }  i:False:[].i  ={ Rango vacıˊ}0={ Definicioˊn de sum  }sum.[]\begin{array}{ll} \bigl \langle \; \sum i : 0 \leq i < \underline{\#[]} : [].i \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \# \; \} \\ \\ \bigl \langle \; \sum i : \underline{0 \leq i < 0} : [].i \; \bigr \rangle \\ \\ = \{ \textnormal{ Aritmética } \} \\ \\ \bigl \langle \; \underline{\sum i : False : [].i} \; \bigr \rangle \\ \\ = \{ \textnormal{ Rango vacío } \} \\ \\ 0 \\ \\ = \{ \textnormal{ Definición de } sum\; \} \\ \\ sum.[] \end{array}

Por lo tanto, probamos la propiedad P.[]P.[]

Paso inductivo: (xxsx \triangleright xs)

Debemos demostrar que:

P.xs:sum.xs=  i:0i<#xs:xs.i      P.(xxs):sum.(xxs)=  i:0i<#(xxs):(xxs).i  \begin{array}{ll} P.xs : sum.xs = \bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle \implies \\ \\ P.(x \triangleright xs) : sum.(x \triangleright xs) = \bigl \langle \; \sum i : 0 \leq i < \# (x \triangleright xs) : (x \triangleright xs).i \; \bigr \rangle \end{array}

Donde P.xsP.xs es la hipótesis inductiva.

Para ello podemos comenzar del lado derecho:

  i:0i<#(xxs):(xxs).i  ={ Definicioˊn de #  }  i:0i<1+#xs:(xxs).i  ={ Separacioˊn de un teˊrmino }(xxs).0+  i:0i<#xs:(xxs).(i+1)  ={ Definicioˊn de .  }x+  i:0i<#xs:xs.i  ={ Hipoˊtesis inductiva }x+sum.xs\begin{array}{ll} \bigl \langle \; \sum i : 0 \leq i < \underline{ \# (x \triangleright xs) } : (x \triangleright xs).i \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } \# \; \} \\ \\ \bigl \langle \; \underline{ \sum i : 0 \leq i < 1 + \# xs : (x \triangleright xs).i } \; \bigr \rangle \\ \\ = \{ \textnormal{ Separación de un término } \} \\ \\ \underline{ (x \triangleright xs).0 } + \bigl \langle \; \sum i : 0 \leq i < \# xs : \underline{(x \triangleright xs).(i + 1)} \; \bigr \rangle \\ \\ = \{ \textnormal{ Definición de } .\; \} \\ \\ x + \underline{\bigl \langle \; \sum i : 0 \leq i < \# xs : xs.i \; \bigr \rangle} \\ \\ = \{ \textnormal{ Hipótesis inductiva } \} \\ \\ x + sum.xs \end{array}

Por lo tanto, probamos la propiedad P.(xxs)P.(x \triangleright xs), y su validez en cualquier lista.