Combinador de punto fijo

ImprimirCitar

En matemáticas e informática en general, un punto fijo de una función es un valor que la función asigna a sí mismo.

In combinatory logic for computer science, a combinador de puntos fijos (o fijador combinador) es una función de orden superior que devuelve algún punto fijo de su función argumental, si existe.

Formalmente, si la función f tiene uno o más puntos fijos, entonces

y por lo tanto, por aplicación repetida,

Combinador Y

En el cálculo lambda clásico sin tipo, cada función tiene un punto fijo.

Una implementación particular de fix es el combinador paradójico Y de Curry, representado por

En la programación funcional, el combinador Y se puede usar para definir formalmente funciones recursivas en un lenguaje de programación que no admita recursividad.

Este combinador puede usarse para implementar la paradoja de Curry. El corazón de la paradoja de Curry es que el cálculo lambda sin tipo no es sólido como sistema deductivo, y el combinador Y lo demuestra al permitir que una expresión anónima represente cero, o incluso muchos valores. Esto es inconsistente en la lógica matemática.

Aplicado a una función con una variable, el combinador Y generalmente no termina. Se obtienen resultados más interesantes aplicando el combinador Y a funciones de dos o más variables. Las variables adicionales se pueden utilizar como contador o índice. La función resultante se comporta como un bucle while o for en un lenguaje imperativo.

Usado de esta manera, el combinador Y implementa una recursividad simple. En el cálculo lambda, no es posible referirse a la definición de una función dentro de su propio cuerpo por su nombre. Sin embargo, la recursividad se puede lograr obteniendo la misma función pasada como argumento y luego usando ese argumento para realizar la llamada recursiva, en lugar de usar el propio nombre de la función, como se hace en los lenguajes que admiten la recursividad de forma nativa. El combinador Y demuestra este estilo de programación.

A continuación se presenta un ejemplo de implementación del combinador Y en dos idiomas.

# Y Combinator in PythonY=lambda f: ()lambda x: f()x()x)()lambda x: f()x()x))Y()Y)


// Combinador Y en C++int principal() {} auto Y = [](auto f) {} auto f1 = [f]auto x) - decltype()f) {} // Puede insertarse aquí una declaración de impresión, // para observar que tenemos un bucle infinito // (al menos hasta que la pila desborde) retorno f()x()x)); }; retorno f1()f1); }; Y()Y);}

Combinador de punto fijo

El combinador Y es una implementación de un combinador de punto fijo en cálculo lambda. Los combinadores de punto fijo también se pueden definir fácilmente en otros lenguajes funcionales e imperativos. La implementación en el cálculo lambda es más difícil debido a las limitaciones del cálculo lambda. El combinador de punto fijo se puede utilizar en varias áreas diferentes:

  • Matemáticas generales
  • Cálculo de lambda no tipo
  • Cálculo de lambda
  • Programación funcional
  • Programación imperativa

Los combinadores de punto fijo se pueden aplicar a una variedad de funciones diferentes, pero normalmente no terminarán a menos que haya un parámetro adicional. Cuando la función a corregir se refiere a su parámetro, se invoca otra llamada a la función, por lo que el cálculo nunca se inicia. En su lugar, el parámetro adicional se utiliza para desencadenar el inicio del cálculo.

El tipo del punto fijo es el tipo de retorno de la función que se está fijando. Este puede ser un real o una función o cualquier otro tipo.

En el cálculo lambda sin tipo, la función a la que se aplica el combinador de punto fijo se puede expresar mediante una codificación, como la codificación Church. En este caso, los términos lambda particulares (que definen funciones) se consideran valores. "Corriendo" (reducción beta) el combinador de punto fijo en la codificación da un término lambda para el resultado que luego puede interpretarse como un valor de punto fijo.

Alternativamente, una función puede considerarse como un término lambda definido puramente en cálculo lambda.

Estos enfoques diferentes afectan cómo un matemático y un programador pueden considerar un combinador de punto fijo. Un matemático de cálculo lambda puede considerar que el combinador Y aplicado a una función es una expresión que satisface la ecuación de punto fijo y, por lo tanto, una solución.

Por el contrario, una persona que solo desee aplicar un combinador de punto fijo a alguna tarea de programación general puede verlo solo como un medio para implementar la recursividad.

Valores y dominios

Cada expresión tiene un valor. Esto es cierto en las matemáticas generales y debe ser cierto en el cálculo lambda. Esto significa que en el cálculo lambda, aplicar un combinador de punto fijo a una función te da una expresión cuyo valor es el punto fijo de la función.

Sin embargo, este es un valor en el dominio de cálculo lambda, puede no corresponder a ningún valor en el dominio de la función, por lo que en un sentido práctico no es necesariamente un punto fijo de la función, y solo en el lambda dominio de cálculo es un punto fijo de la ecuación.

Por ejemplo, considere

La división de números firmados se puede implementar en la codificación de la Iglesia, por lo que f puede estar representado por un término de lambda. Esta ecuación no tiene solución en los números reales. Pero en el dominio de los números complejos i y...i son soluciones. Esto demuestra que puede haber soluciones a una ecuación en otro dominio. Sin embargo, el término lambda para la solución para la ecuación anterior es más raro que eso. El término lambda representa el estado donde x podría ser i o...iComo un valor. La información que distingue estos dos valores se ha perdido, en el cambio de dominio. Tenga en cuenta que esto todavía puede ser representado como un único valor, si la lógica se expande a ser paraconsistente.

Para el matemático del cálculo lambda, esto es una consecuencia de la definición de cálculo lambda. Para el programador, significa que la reducción beta del término lambda se repetirá para siempre, sin llegar nunca a una forma normal.

Función versus implementación

El combinador de punto fijo puede definirse en matemáticas y luego implementarse en otros lenguajes. Las matemáticas generales definen una función en función de sus propiedades extensionales. Es decir, dos funciones son iguales si realizan el mismo mapeo. El cálculo lambda y los lenguajes de programación consideran la identidad de función como una propiedad intencional. La identidad de una función se basa en su implementación.

Una función (o término) de cálculo lambda es una implementación de una función matemática. En el cálculo lambda hay varios combinadores (implementaciones) que satisfacen la definición matemática de un combinador de punto fijo.

Definición del término "combinador"

La lógica combinatoria es una teoría de funciones de orden superior. Un combinador es una expresión lambda cerrada, lo que significa que no tiene variables libres. Los combinadores se pueden combinar para dirigir los valores a sus lugares correctos en la expresión sin siquiera nombrarlos como variables.

Uso en programación

Los combinadores de punto fijo se pueden usar para implementar la definición recursiva de funciones. Sin embargo, rara vez se utilizan en la programación práctica. Los sistemas de tipos fuertemente normalizados, como el cálculo lambda tipificado simplemente, no permiten la no terminación y, por lo tanto, a los combinadores de punto fijo a menudo no se les puede asignar un tipo o requieren características complejas del sistema de tipos. Además, los combinadores de punto fijo a menudo son ineficientes en comparación con otras estrategias para implementar la recursividad, ya que requieren más reducciones de funciones y construyen y separan una tupla para cada grupo de definiciones mutuamente recursivas.

La función factorial

La función factorial proporciona un buen ejemplo de cómo se puede aplicar el combinador de punto fijo. El resultado demuestra una recursividad simple, como se implementaría en un solo ciclo en un lenguaje imperativo. La definición de números utilizados se explica en la codificación de la Iglesia.

La función que se toma a sí misma como parámetro es

Esto da Y F n como

Ajuste da

Esta definición pone a F en el papel del cuerpo de un ciclo que se va a iterar, y es equivalente a la definición matemática de factorial:

Combinadores de punto fijo en cálculo lambda

El combinador Y, descubierto por Haskell B. Curry, se define como

Por reducción beta tenemos:

(por definición de Y)
(por β-reducción de λf: aplicado Y a g)
(por β-reducción de λx: función izquierda aplicada a la función derecha)
(por segunda igualdad)

La aplicación repetida de esta igualdad da:

(La igualdad anterior debe ser considerada como una secuencia de reducciones β multi-paso de izquierda a derecha. El término lambda no puede, en general, β-reducir al término . Uno puede interpretar los signos de igualdad como β-equivalencias en lugar de las reducciones β multi-paso para permitir ir en ambas direcciones.)

Definición equivalente de un combinador de punto fijo

Este combinador de punto fijo se puede definir como y, como en

Se puede derivar una expresión para y usando reglas de la definición de una expresión let. En primer lugar, utilizando la regla

da

Además, usando

da

Y luego usando la regla de reducción eta

da

Derivación del combinador Y

El combinador Y de Curry se puede obtener fácilmente a partir de la definición de y.

Empezamos con

Una abstracción de lambda no admite referencia al nombre variable en la expresión aplicada, por lo que x debe ser pasado como un parámetro x. Podemos pensar en esto como reemplazar x por x, pero formalmente esto no es correcto. En lugar de definir Sí. por da

La expresión let puede considerarse como la definición de la función y, donde z es el parámetro. La instanciación z como y en la llamada da

Y, debido a que el parámetro z siempre pasa la función y,

Usando la regla de reducción eta,

da

Una expresión let puede expresarse como una abstracción lambda; usando

da

Esta es posiblemente la implementación más simple de un combinador de punto fijo en el cálculo lambda. Sin embargo, una reducción beta da la forma más simétrica del combinador Y de Curry:

Consulte también Traducir entre expresiones let y lambda.

Otros combinadores de punto fijo

En el cálculo lambda sin tipo, los combinadores de punto fijo no son especialmente raros. De hecho, hay infinitas de ellas. En 2005, Mayer Goldberg demostró que el conjunto de combinadores de punto fijo del cálculo lambda sin tipo es recursivamente enumerable.

El combinador Y se puede expresar en el cálculo SKI como

Los combinadores adicionales (sistema B, C, K, W) permiten una definición mucho más corta. Con U = SII el combinador de autoaplicación, ya que S(Kx)yz = x(yz) = Bxyz y Sx(Ky)z = xzy = Cxyz, lo anterior se convierte en

El combinador de punto fijo más simple en el cálculo SK, encontrado por John Tromp, es

aunque tenga en cuenta que no está en su forma normal, que es más larga. Este combinador corresponde a la expresión lambda

El siguiente combinador de punto fijo es más simple que el combinador Y, y β se reduce al combinador Y; a veces se cita como el propio combinador Y:

Otro combinador de punto fijo común es el combinador de punto fijo de Turing (llamado así por su descubridor, Alan Turing):

Su ventaja sobre es que beta-reduce a , mientras que y sólo beta-reducir a un término común.

también tiene una forma sencilla de llamada a valor:

El análogo para la recursividad mutua es un combinador polivariádico de punto fijo, que se puede denotar Y*.

Combinador estricto de punto fijo

En un lenguaje de programación estricto, el combinador Y se expandirá hasta el desbordamiento de la pila, o nunca se detendrá en caso de optimización de llamadas finales. El combinador Z funcionará en lenguajes estrictos (también llamados lenguajes ansiosos, donde se aplica el orden de evaluación aplicativo). El combinador Z tiene el siguiente argumento definido explícitamente, evitando la expansión de Z g en el lado derecho de la definición:

y en cálculo lambda es una expansión eta del combinador Y:

Combinadores de punto fijo no estándar

En el cálculo lambda sin tipo, hay términos que tienen el mismo árbol de Böhm que un combinador de punto fijo, es decir, tienen la misma extensión infinita λx.x (x (x...)). Estos se denominan combinadores de punto fijo no estándar. Cualquier combinador de punto fijo también es no estándar, pero no todos los combinadores de punto fijo no estándar son combinadores de punto fijo porque algunos de ellos no cumplen con la ecuación que define el "estándar" unos. Estos extraños combinadores se denominan combinadores de punto fijo estrictamente no estándar; un ejemplo es el siguiente combinador:

dónde

El conjunto de combinadores de punto fijo no estándar no es enumerable recursivamente.

Implementación en otros idiomas

(El combinador Y es una implementación particular de un combinador de punto fijo en el cálculo lambda. Su estructura está determinada por las limitaciones del cálculo lambda. No es necesario ni útil usar esta estructura para implementar el combinador de punto fijo en otros idiomas.)

A continuación se proporcionan ejemplos simples de combinadores de punto fijo implementados en algunos paradigmas de programación.

Implementación funcional perezosa

En un lenguaje que admite la evaluación perezosa, como en Haskell, es posible definir un combinador de punto fijo utilizando la ecuación de definición del combinador de punto fijo que se denomina convencionalmente fix. Dado que Haskell tiene tipos de datos perezosos, este combinador también se puede usar para definir puntos fijos de constructores de datos (y no solo para implementar funciones recursivas). La definición se da aquí, seguida de algunos ejemplos de uso. En Hackage, la muestra original es:

arreglar, arreglar ' :: ()a - a) - aarreglar f = Deja x = f x dentro x - Lambda cayó. Compartir. -- Definición original en Data.Function.-- alternativa:arreglar ' f = f ()arreglar ' f) - Lambda se levantó. No compartir.arreglar ()x - 9) - esto evalúa a 9arreglar ()x - 3:x) -- evalúa a la lista infinita perezosa [3,3,...]hecho = arreglar fac -- evalúa a la función factorial Donde fac f 0 = 1 fac f x = x * f ()x-1)hecho 5 - evalúa a 120

Implementación funcional estricta

En un lenguaje funcional estricto, como se ilustra a continuación con OCaml, el argumento para f se expande de antemano, lo que produce una secuencia de llamada infinita,

.

Esto se puede resolver definiendo arreglo con un parámetro adicional.

Deja rec arreglar f x = f ()arreglar f) x (* nota el extra x; aquí fijar f = x- título f (fix f) x *)Deja factabs hecho = función (* factabs tiene un nivel extra de abstracción de lambda *) 0 - 1 Silencio x - x * hecho ()x-1)Deja ¿Qué? = ()arreglar factabs) 5 (* evalúa a "120" *)

En un lenguaje funcional multiparadigma (uno decorado con funciones imperativas), como Lisp, Landin (1963) sugiere el uso de una asignación variable para crear un combinador de punto fijo, como en el siguiente ejemplo usando Scheme:

()definir ¡Sí! ()lambda ()f) ()lambda ()i) ()¡Listo! i ()f ()lambda ()x) ()i x))) ; (set! i expr) asigna i el valor de expr i) ; su sustitución en el actual ámbito lexical #f))

Usando un cálculo lambda con axiomas para sentencias de asignación, se puede demostrar que Y! satisface la misma ley de punto fijo que el combinador Y de llamada por valor:

En un uso más idiomático de Lisp moderno, esto normalmente se manejaría a través de una etiqueta con alcance léxico (una expresión let), ya que el alcance léxico no se introdujo en Lisp hasta la década de 1970:

()definir Y* ()lambda ()f) ()lambda ()i) ()Deja ()i ()f ()lambda ()x) ()i x)))) i) Localmente define i como expr i) ;; no-recursivamente: por lo tanto en expr no es expr #f))

O sin la etiqueta interna:

()definir Y ()lambda ()f) ()lambda ()i) ()i i) ()lambda ()i) ()f ()lambda ()x) ()aplicación ()i i) x))))))

Implementación de lenguaje imperativo

Este ejemplo es una implementación ligeramente interpretativa de un combinador de punto fijo. Se usa una clase para contener la función fix, llamada fixer. La función a corregir está contenida en una clase que hereda de fixer. La función fix accede a la función a corregir como una función virtual. En cuanto a la definición funcional estricta, fix recibe explícitamente un parámetro adicional x, lo que significa que no se necesita una evaluación perezosa.

plantilla .nombre R, nombre Dclase fijador{}público: R arreglar()D x) {} retorno f()x); }privado: virtual R f()D) = 0;};clase hecho : público fijador.largo, largo{} virtual largo f()largo x) {} si ()x == 0) {} retorno 1; } retorno x * arreglar()x-1); }};largo resultado = hecho().arreglar()5);

Escribiendo

En el Sistema F (cálculo lambda polimórfico) un combinador polimórfico de punto fijo tiene tipo;

(a → a) → a

donde a es una variable de tipo. Es decir, fix toma una función, que mapea a → a y la usa para devolver un valor de tipo a.

En el cálculo lambda de tipo simple ampliado con tipos de datos recursivos, se pueden escribir operadores de punto fijo, pero el tipo de un "útil" operador de punto fijo (aquel cuya aplicación siempre regresa) puede estar restringido.

En el cálculo de lambda simplemente escrito, el combinador de punta fija Y no se puede asignar un tipo porque en algún momento se trataría con el sub-term de la autoaplicación por la regla de aplicación:

Donde tiene el tipo infinito . De hecho, no se puede escribir un combinador de puntos fijos; en esos sistemas, cualquier apoyo a la recursión debe añadirse explícitamente al idioma.

Tipo para el combinador Y

En los lenguajes de programación que admiten tipos de datos recursivos, es posible escribir el combinador Y teniendo en cuenta adecuadamente la recurrencia en el nivel de tipo. La necesidad de autoaplicar la variable x se puede gestionar mediante un tipo (Rec a), que se define de manera que sea isomorfo a (Rec a -> a).

Por ejemplo, en el siguiente código Haskell, tenemos In y out siendo los nombres de las dos direcciones del isomorfismo, con tipos:

In :: ()Rec a - a) - Rec aFuera. :: Rec a - ()Rec a - a)

que nos permite escribir:

nuevo tipo Rec a = In {} Fuera. :: Rec a - a }Sí. :: ()a - a) - aSí. = f - ()x - f ()Fuera. x x) ()In ()x - f ()Fuera. x x))

O de forma equivalente en OCaml:

Tipo 'a rec = In de ()'a rec - 'a)Deja Fuera. ()In x) = xDeja Sí. f = ()diversión x a - f ()Fuera. x x) a) ()In ()diversión x a - f ()Fuera. x x) a)

Alternativamente:

Deja Sí. f = ()diversión x - f ()diversión z - Fuera. x x z) ()In ()diversión x - f ()diversión z - Fuera. x x z))

Información general

Debido a que los combinadores de punto fijo se pueden usar para implementar recursividad, es posible usarlos para describir tipos específicos de cálculos recursivos, como los de iteración de punto fijo, métodos iterativos, combinación recursiva en bases de datos relacionales, flujo de datos análisis, conjuntos FIRST y FOLLOW de no terminales en una gramática independiente del contexto, cierre transitivo y otros tipos de operaciones de cierre.

Una función para la cual cada entrada es un punto fijo se llama función de identidad. Formalmente:

En contraste con la cuantificación universal sobre todos , una combinación de puntos fijos construye uno valor que es un punto fijo . La propiedad notable de un combinador de punto fijo es que construye un punto fijo para un arbitrarias función .

Otras funciones tienen la propiedad especial de que, después de aplicarse una vez, las aplicaciones posteriores no tienen ningún efecto. Más formalmente:

Tales funciones se denominan idempotentes (ver también Proyección (matemáticas)). Un ejemplo de tal función es la función que devuelve 0 para todos los enteros pares y 1 para todos los enteros impares.

En el cálculo lambda, desde un punto de vista computacional, la aplicación de un combinador de punto fijo a una función de identidad o una función idempotente generalmente da como resultado un cálculo sin terminación. Por ejemplo, obtenemos

donde el término resultante solo puede reducirse a sí mismo y representa un bucle infinito.

Los combinadores de punto fijo no existen necesariamente en modelos de computación más restrictivos. Por ejemplo, no existen en el cálculo lambda de tipo simple.

El combinador Y permite que la recursividad se defina como un conjunto de reglas de reescritura, sin necesidad de compatibilidad con recursividad nativa en el lenguaje.

En los lenguajes de programación que admiten funciones anónimas, los combinadores de punto fijo permiten la definición y el uso de funciones recursivas anónimas, es decir, sin tener que vincular dichas funciones a identificadores. En esta configuración, el uso de combinadores de punto fijo a veces se denomina recursión anónima.

Contenido relacionado

Max agosto zorn

Max August Zorn fue un matemático alemán. Fue algebrista, teórico de grupos y analista numérico. Es mejor conocido por el lema de Zorn, un método...

Cambiador de genero

Los cambiadores de género se utilizan para los puertos RS-232C en el formato original DB-25 o IBM AT DE-9. También se usan para extender cualquier tipo de...

Relación de compresión de datos

Relación de compresión de datos, también conocida como potencia de compresión, es una medida de la reducción relativa en el tamaño de la representación...
Más resultados...
Tamaño del texto:
Editar