En informática teórica , el cálculo π (o cálculo pi ) es un cálculo de procesos . El cálculo π permite comunicar los nombres de los canales a lo largo de los mismos, y de esta manera es capaz de describir cálculos concurrentes cuya configuración de red puede cambiar durante el cálculo.
El cálculo π tiene pocos términos y es un lenguaje pequeño, pero expresivo (ver § Sintaxis). Los programas funcionales pueden codificarse en el cálculo π , y la codificación enfatiza la naturaleza dialógica del cálculo, estableciendo conexiones con la semántica de los juegos . Las extensiones del cálculo π , como el cálculo spi y el cálculo π aplicado , han tenido éxito en el razonamiento sobre protocolos criptográficos . Además del uso original para describir sistemas concurrentes, el cálculo π también se ha utilizado para razonar sobre procesos comerciales [1] y biología molecular . [2]
El cálculo π pertenece a la familia de los cálculos de procesos , formalismos matemáticos para describir y analizar propiedades de computación concurrente. De hecho, el cálculo π , al igual que el cálculo λ , es tan minimalista que no contiene primitivos como números, booleanos, estructuras de datos, variables, funciones o incluso las instrucciones de flujo de control habituales (como if-then-else
, while
).
El concepto de nombre es central en el cálculo π . La simplicidad del cálculo reside en el doble papel que desempeñan los nombres como canales de comunicación y variables .
Las construcciones de proceso disponibles en el cálculo son las siguientes [3] (una definición precisa se da en la siguiente sección):
c
goto c
goto c
c
goto c
Aunque el minimalismo del cálculo π nos impide escribir programas en el sentido normal, es fácil extender el cálculo. En particular, es fácil definir tanto estructuras de control como recursión, bucles y composición secuencial como tipos de datos como funciones de primer orden, valores de verdad , listas y números enteros. Además, se han propuesto extensiones del cálculo π que tienen en cuenta la distribución o la criptografía de clave pública. El cálculo π aplicado debido a Abadi y Fournet [1] puso estas diversas extensiones en una base formal al extender el cálculo π con tipos de datos arbitrarios.
A continuación se muestra un pequeño ejemplo de un proceso que consta de tres componentes paralelos. El nombre del canal x solo lo conocen los dos primeros componentes.
Los dos primeros componentes pueden comunicarse en el canal x y el nombre y queda asociado a z . Por lo tanto, el siguiente paso del proceso es
Tenga en cuenta que el resto de y no se ve afectado porque está definido en un ámbito interno. El segundo y tercer componente paralelo ahora pueden comunicarse en el canal llamado z y el nombre v se vincula a x . El siguiente paso en el proceso ahora es
Tenga en cuenta que, dado que se ha enviado el nombre local x , el alcance de x se amplía para cubrir también el tercer componente. Por último, el canal x se puede utilizar para enviar el nombre x . Después de eso, todos los procesos que se ejecutan simultáneamente se han detenido
Sea Χ un conjunto de objetos llamados nombres . La sintaxis abstracta para el cálculo π se construye a partir de la siguiente gramática BNF (donde x e y son nombres cualesquiera de Χ): [4]
En la sintaxis concreta que se muestra a continuación, los prefijos se unen con más fuerza que la composición paralela (|) y los paréntesis se utilizan para eliminar la ambigüedad.
Los nombres están limitados por las construcciones de restricción y prefijo de entrada. Formalmente, el conjunto de nombres libres de un proceso en el cálculo π se define de manera inductiva mediante la siguiente tabla. El conjunto de nombres limitados de un proceso se define como los nombres de un proceso que no están en el conjunto de nombres libres.
La noción de congruencia estructural es central tanto para la semántica de reducción como para la semántica de transición etiquetada . Dos procesos son estructuralmente congruentes si son idénticos en cuanto a su estructura. En particular, la composición paralela es conmutativa y asociativa.
Más precisamente, la congruencia estructural se define como la relación de equivalencia mínima preservada por los constructos del proceso y que satisface:
Conversión alfa :
Axiomas para composición paralela :
Axiomas de restricción :
Axioma para la replicación :
Axioma que relaciona restricción y paralelismo :
Este último axioma se conoce como el axioma de "extensión del alcance". Este axioma es fundamental, ya que describe cómo un nombre x ligado puede ser extruido por una acción de salida, lo que hace que el alcance de x se extienda. En los casos en que x es un nombre libre de , se puede utilizar la conversión alfa para permitir que la extensión continúe.
Escribimos si podemos realizar un paso de cálculo, después del cual ahora es . Esta relación de reducción se define como la relación mínima cerrada bajo un conjunto de reglas de reducción.
La principal regla de reducción que captura la capacidad de los procesos para comunicarse a través de canales es la siguiente:
Hay tres reglas adicionales:
La última regla establece que los procesos que son estructuralmente congruentes tienen las mismas reducciones.
Consideremos nuevamente el proceso
Aplicando la definición de la semántica de reducción, obtenemos la reducción
Observe cómo, al aplicar el axioma de reducción-sustitución, las apariciones libres de ahora se etiquetan como .
A continuación, obtenemos la reducción.
Tenga en cuenta que, dado que se ha generado el nombre local x , el alcance de x se amplía para cubrir también el tercer componente. Esto se capturó utilizando el axioma de extensión del alcance.
A continuación, utilizando el axioma de reducción-sustitución, obtenemos
Finalmente, utilizando los axiomas de composición paralela y restricción, obtenemos
Como alternativa, se puede dar al cálculo pi una semántica de transición etiquetada (como se ha hecho con el cálculo de sistemas de comunicación ).
En esta semántica, una transición de un estado a otro estado después de una acción se anota como:
Donde los estados y representan procesos y es una acción de entrada , una acción de salida o una acción silenciosa τ . [5]
Un resultado estándar sobre la semántica etiquetada es que concuerda con la semántica de reducción hasta la congruencia estructural, en el sentido de que si y sólo si [6]
La sintaxis que se muestra arriba es mínima. Sin embargo, se puede modificar de varias maneras.
Se puede agregar un operador de elección no determinista a la sintaxis.
Se puede añadir a la sintaxis una prueba de igualdad de nombres . Este operador de coincidencia puede proceder como si y solo si x y son el mismo nombre. De manera similar, se puede añadir un operador de desajuste para la desigualdad de nombres . Los programas prácticos que pueden pasar nombres (URL o punteros) suelen utilizar dicha funcionalidad: para modelar directamente dicha funcionalidad dentro del cálculo, esta y otras extensiones relacionadas suelen ser útiles.
El cálculo π asincrónico [7] [8] sólo permite salidas sin continuación, es decir, átomos de salida de la forma , lo que produce un cálculo más pequeño. Sin embargo, cualquier proceso en el cálculo original puede ser representado por el cálculo π asincrónico más pequeño utilizando un canal adicional para simular un reconocimiento explícito del proceso receptor. Dado que una salida sin continuación puede modelar un mensaje en tránsito, este fragmento muestra que el cálculo π original , que se basa intuitivamente en la comunicación sincrónica, tiene un modelo de comunicación asincrónica expresivo dentro de su sintaxis. Sin embargo, el operador de elección no determinista definido anteriormente no puede expresarse de esta manera, ya que una elección sin protección se convertiría en una con protección; este hecho se ha utilizado para demostrar que el cálculo asincrónico es estrictamente menos expresivo que el sincrónico (con el operador de elección). [9]
El cálculo poliádico π permite comunicar más de un nombre en una sola acción: (salida poliádica) y (entrada poliádica) . Esta extensión poliádica, que es útil especialmente cuando se estudian tipos para procesos de paso de nombres, se puede codificar en el cálculo monádico pasando el nombre de un canal privado a través del cual se pasan los múltiples argumentos en secuencia. La codificación se define recursivamente mediante las cláusulas
está codificado como
está codificado como
Todas las demás construcciones del proceso no se modifican con la codificación.
En lo anterior, se denota la codificación de todos los prefijos en la continuación de la misma manera.
No se necesita toda la potencia de replicación . A menudo, solo se considera la entrada replicada , cuyo axioma de congruencia estructural es .
Proceso de entrada replicado, como se puede entender por servidores, que esperan en el canal x a que los clientes lo invoquen. La invocación de un servidor genera una nueva copia del proceso , donde a es el nombre que el cliente pasa al servidor durante la invocación de este último.
Se puede definir un cálculo π de orden superior en el que no solo se envían nombres sino también procesos a través de canales. La regla de reducción de claves para el caso de orden superior es
Aquí, denota una variable de proceso que puede ser instanciada por un término de proceso. Sangiorgi estableció que la capacidad de pasar procesos no aumenta la expresividad del cálculo π : pasar un proceso P puede simularse simplemente pasando un nombre que apunte a P.
El cálculo π es un modelo universal de computación . Esto fue observado por primera vez por Milner en su artículo "Funciones como procesos", [10] en el que presenta dos codificaciones del cálculo lambda en el cálculo π . Una codificación simula la estrategia de evaluación ansiosa (llamada por valor) , la otra codificación simula la estrategia de orden normal (llamada por nombre). En ambas, la idea crucial es el modelado de los enlaces del entorno -por ejemplo, " x está enlazado a término "- como agentes replicadores que responden a las solicitudes de sus enlaces enviando de vuelta una conexión al término .
Las características del cálculo π que hacen posible estas codificaciones son el paso de nombres y la replicación (o, equivalentemente, los agentes definidos recursivamente). En ausencia de replicación/recursión, el cálculo π deja de ser Turing-completo. Esto se puede ver por el hecho de que la equivalencia de bisimulación se vuelve decidible para el cálculo sin recursión e incluso para el cálculo π de control finito donde el número de componentes paralelos en cualquier proceso está limitado por una constante. [11]
En cuanto a los cálculos de procesos, el cálculo π permite definir la equivalencia de bisimulación. En el cálculo π , la definición de equivalencia de bisimulación (también conocida como bisimilaridad) puede basarse en la semántica de reducción o en la semántica de transición etiquetada.
Existen (al menos) tres formas diferentes de definir la equivalencia de bisimulación etiquetada en el cálculo π : bisimilaridad temprana, tardía y abierta. Esto se debe al hecho de que el cálculo π es un cálculo de proceso de paso de valores.
En el resto de esta sección, denotamos y procesos y denotamos relaciones binarias sobre procesos.
Tanto la bisimilaridad temprana como la tardía fueron formuladas por Milner, Parrow y Walker en su artículo original sobre el cálculo π . [12]
Una relación binaria sobre procesos es una bisimulación temprana si para cada par de procesos ,
Se dice que los procesos y son bisimilares tempranos, escritos si el par es para alguna bisimulación temprana .
En la bisimilitud tardía, la coincidencia de transición debe ser independiente del nombre que se transmite. Una relación binaria sobre procesos es una bisimulación tardía si para cada par de procesos ,
Se dice que los procesos y son bisimilares tardíos, escritos si el par corresponde a alguna bisimulación tardía .
Tanto y sufren del problema de que no son relaciones de congruencia en el sentido de que no se conservan en todos los constructos de proceso. Más precisamente, existen procesos y tales que pero . Se puede remediar este problema considerando las relaciones de congruencia máxima incluidas en y , conocidas como congruencia temprana y congruencia tardía , respectivamente.
Afortunadamente, es posible una tercera definición que evita este problema, a saber, la de bisimilaridad abierta , debida a Sangiorgi. [13]
Una relación binaria sobre procesos es una bisimulación abierta si para cada par de elementos y para cada sustitución de nombre y cada acción , siempre que exista algún tal que y .
Se dice que los procesos y son bisimilares abiertos, escrito si el par para alguna bisimulación abierta .
La bisimilaridad temprana, tardía y abierta son distintas. Las contenciones son propias, por lo que .
En ciertos subcálculos, como el cálculo pi asincrónico, se sabe que la bisimilitud tardía, temprana y abierta coinciden. Sin embargo, en este contexto, una noción más apropiada es la de bisimilitud asincrónica . En la literatura, el término bisimulación abierta generalmente se refiere a una noción más sofisticada, donde los procesos y las relaciones se indexan mediante relaciones de distinción; los detalles se encuentran en el artículo de Sangiorgi citado anteriormente.
Como alternativa, se puede definir la equivalencia de bisimulación directamente a partir de la semántica de reducción. Escribimos si el proceso permite inmediatamente una entrada o una salida en nombre .
Una relación binaria sobre procesos es una bisimulación con púas si es una relación simétrica que satisface que para cada par de elementos tenemos que
y
de tal manera que .
Decimos que y son bisimilares con púas si existe una bisimulación con púas donde .
Definiendo un contexto como un término π con un agujero [] decimos que dos procesos P y Q son congruentes en forma de púas , escrito , si para cada contexto tenemos que y son bisimilares en forma de púas. Resulta que la congruencia en forma de púas coincide con la congruencia inducida por la bisimilaridad temprana.
El cálculo π se ha utilizado para describir muchos tipos diferentes de sistemas concurrentes. De hecho, algunas de las aplicaciones más recientes se encuentran fuera del ámbito de la informática tradicional.
En 1997, Martin Abadi y Andrew Gordon propusieron una extensión del cálculo π , el cálculo Spi, como una notación formal para describir y razonar sobre protocolos criptográficos. El cálculo Spi extiende el cálculo π con primitivas para cifrado y descifrado. En 2001, Martin Abadi y Cedric Fournet generalizaron el manejo de protocolos criptográficos para producir el cálculo π aplicado . Actualmente existe una gran cantidad de trabajo dedicado a variantes del cálculo π aplicado , incluyendo una serie de herramientas de verificación experimental. Un ejemplo es la herramienta ProVerif [2] de Bruno Blanchet, basada en una traducción del cálculo π aplicado al marco de programación lógica de Blanchet. Otro ejemplo es Cryptyc [3], de Andrew Gordon y Alan Jeffrey, que utiliza el método de aserciones de correspondencia de Woo y Lam como base para sistemas de tipos que pueden verificar las propiedades de autenticación de los protocolos criptográficos.
Alrededor de 2002, Howard Smith y Peter Fingar se interesaron en que el cálculo π se convirtiera en una herramienta de descripción para modelar procesos de negocios. En julio de 2006, se comenzó a debatir en la comunidad sobre su utilidad. Más recientemente, el cálculo π ha formado la base teórica del lenguaje de modelado de procesos de negocios (BPML) y del XLANG de Microsoft. [14]
El cálculo π también ha despertado interés en la biología molecular. En 1999, Aviv Regev y Ehud Shapiro demostraron que se puede describir una vía de señalización celular (la denominada cascada RTK / MAPK ) y, en particular, el "lego" molecular que implementa estas tareas de comunicación en una extensión del cálculo π . [2] Tras este artículo seminal, otros autores describieron toda la red metabólica de una célula mínima. [15] En 2009, Anthony Nash y Sara Kalvala propusieron un marco de cálculo π para modelar la transducción de señales que dirige la agregación de Dictyostelium discoideum . [16]
El cálculo π fue desarrollado originalmente por Robin Milner , Joachim Parrow y David Walker en 1992, basándose en ideas de Uffe Engberg y Mogens Nielsen. [17] Puede verse como una continuación del trabajo de Milner sobre el cálculo de procesos CCS ( Cálculo de sistemas de comunicación ). En su conferencia de Turing, Milner describe el desarrollo del cálculo π como un intento de capturar la uniformidad de valores y procesos en los actores. [18]
Los siguientes lenguajes de programación implementan el cálculo π o una de sus variantes: