Unificação (ciência da computação) - Unification (computer science)

Na lógica e na ciência da computação , a unificação é um processo algorítmico de resolução de equações entre expressões simbólicas .

Dependendo de quais expressões (também chamadas de termos ) podem ocorrer em um conjunto de equações (também chamado de problema de unificação ), e quais expressões são consideradas iguais, várias estruturas de unificação são distinguidas. Se variáveis ​​de ordem superior, ou seja, variáveis ​​que representam funções , são permitidas em uma expressão, o processo é chamado de unificação de ordem superior , caso contrário, unificação de primeira ordem . Se uma solução é necessária para tornar ambos os lados de cada equação literalmente iguais, o processo é chamado de unificação sintática ou livre , caso contrário, unificação semântica ou equacional , ou unificação E , ou teoria do módulo de unificação .

A solução de um problema de unificação é denotada como substituição , ou seja, um mapeamento que atribui um valor simbólico a cada variável das expressões do problema. Um algoritmo de unificação deve calcular para um determinado problema um conjunto de substituição completo e mínimo , ou seja, um conjunto que cobre todas as suas soluções e não contém membros redundantes. Dependendo da estrutura, um conjunto de substituição completo e mínimo pode ter no máximo um, no máximo finitos muitos, ou possivelmente infinitos muitos membros, ou pode não existir de todo. Em algumas estruturas, geralmente é impossível decidir se existe alguma solução. Para a unificação sintática de primeira ordem, Martelli e Montanari forneceram um algoritmo que relata a insolubilidade ou calcula um conjunto de substituição de singleton completo e mínimo contendo o assim chamado unificador mais geral .

Por exemplo, usando x , y , z como variáveis, o conjunto de equações singleton { cons ( x , cons ( x , nil )) = cons (2, y )} é um problema de unificação sintática de primeira ordem que tem a substituição { x ↦ 2, ycons (2, nil )} como sua única solução. O problema de unificação sintática de primeira ordem { y = cons (2, y )} não tem solução sobre o conjunto de termos finitos ; entretanto, ele tem a única solução { ycons (2, cons (2, cons (2, ...)))} sobre o conjunto de árvores infinitas . O problema de unificação semântica de primeira ordem { ax = xa } tem cada substituição da forma { xa ⋅ ... ⋅ a } como uma solução em um semigrupo , ou seja, se (⋅) é considerado associativo ; o mesmo problema, visto em um grupo abeliano , onde (⋅) é considerado também comutativo , tem qualquer substituição como solução. O conjunto singleton { a = y ( x )} é um problema de unificação sintática de segunda ordem, uma vez que y é uma variável de função. Uma solução é { xa , y ↦ ( função de identidade )}; outro é { y ↦ ( função constante mapeando cada valor para a ), x(qualquer valor) }.

Um algoritmo de unificação foi descoberto por Jacques Herbrand , enquanto uma primeira investigação formal pode ser atribuída a John Alan Robinson , que usou a unificação sintática de primeira ordem como um bloco de construção básico de seu procedimento de resolução para lógica de primeira ordem, um grande passo em frente em tecnologia de raciocínio automatizado , pois eliminou uma fonte de explosão combinatória: a busca pela instanciação de termos. Hoje, o raciocínio automatizado ainda é a principal área de aplicação da unificação. A unificação sintática de primeira ordem é usada em programação lógica e implementação de sistema de tipo de linguagem de programação , especialmente em algoritmos de inferência de tipo baseados em Hindley-Milner . A unificação semântica é usada em resolvedores SMT , algoritmos de reescrita de termos e análise de protocolo criptográfico . A unificação de ordem superior é usada em assistentes de prova, por exemplo Isabelle e Twelf , e formas restritas de unificação de ordem superior (unificação de padrão de ordem superior ) são usadas em algumas implementações de linguagem de programação, como lambdaProlog , pois os padrões de ordem superior são expressivos , ainda assim, seu procedimento de unificação associado retém propriedades teóricas mais próximas da unificação de primeira ordem.

Definições formais comuns

Pré-requisitos

Formalmente, uma abordagem de unificação pressupõe

  • Um conjunto infinito de variáveis . Para unificação de ordem superior, é conveniente escolher disjunto do conjunto de variáveis ​​de limite de termo lambda .
  • Um conjunto de termos como esse . Para unificação de primeira ordem e unificação de ordem superior, geralmente é o conjunto de termos de primeira ordem (termos construídos a partir de símbolos de variáveis ​​e funções) e termos lambda (termos contendo algumas variáveis ​​de ordem superior), respectivamente.
  • Um mapeamento vars : , atribuindo a cada termo o conjunto de variáveis livres que ocorrem em .
  • Uma relação de equivalência em , indicando que os termos são considerados iguais. Para unificação de ordem superior, geralmente se e são equivalentes alfa . Para a unificação E de primeira ordem, reflete o conhecimento prévio sobre certos símbolos de função; por exemplo, se é considerado comutativo, se resulta da troca dos argumentos de algumas (possivelmente todas) ocorrências. Se não houver nenhum conhecimento prévio, apenas literal ou sintaticamente os termos idênticos são considerados iguais; neste caso, ≡ é chamada de teoria livre (porque é um objeto livre ), a teoria vazia (porque o conjunto de sentenças equacionais , ou o conhecimento de fundo, está vazio), a teoria das funções não interpretadas (porque a unificação é feita em termos não interpretados ) ou a teoria dos construtores (porque todos os símbolos de função apenas criam termos de dados, em vez de operar sobre eles).

Termo de primeira ordem

Dado um conjunto de símbolos variáveis, um conjunto de símbolos constantes e conjuntos de símbolos de função n -ary, também chamados de símbolos de operador, para cada número natural , o conjunto de termos (não classificados de primeira ordem) é definido recursivamente para ser o menor conjunto com as seguintes propriedades:

  • cada símbolo variável é um termo: ,
  • cada símbolo constante é um termo: ,
  • a partir de cada n termos e de cada símbolo de função n -ary , um termo maior pode ser construído.

Por exemplo, se é um símbolo de variável, é um símbolo de constante e é um símbolo de função binária, então , e (portanto) pela primeira, segunda e terceira regra de construção de termos, respectivamente. O último termo é geralmente escrito como , usando notação de infixo e o símbolo de operador mais comum + por conveniência.

Termo de ordem superior

Substituição

Uma substituição é um mapeamento de variáveis ​​para termos; a notação se refere a um mapeamento de substituição de cada variável para o termo , para e todas as outras variáveis ​​para si mesmo. A aplicação dessa substituição a um termo é escrita em notação pós-fixada como ; significa (simultaneamente) substituir todas as ocorrências de cada variável no termo por . O resultado da aplicação de uma substituição a um termo é chamado de instância desse termo . Como um exemplo de primeira ordem, aplicando a substituição { xh ( a , y ), zb } ao termo

rendimentos  

Generalização, especialização

Se um termo tem uma instância equivalente a um termo , isto é, se por alguma substituição , então é chamado de mais geral que , e é chamado de mais especial que, ou subsumido por ,. Por exemplo, é mais geral do que se ⊕ for comutativo , desde então .

Se ≡ for identidade literal (sintática) de termos, um termo pode ser mais geral e mais especial do que outro somente se ambos os termos diferirem apenas em seus nomes de variáveis, não em sua estrutura sintática; tais termos são chamados de variantes ou renomeações uns dos outros. Por exemplo, é uma variante de , uma vez que

e

.

No entanto, não é uma variante de , uma vez que nenhuma substituição pode transformar o último termo no primeiro. O último termo é, portanto, apropriadamente mais especial do que o anterior.

Para arbitrário , um termo pode ser mais geral e mais especial do que um termo estruturalmente diferente. Por exemplo, se ⊕ for idempotente , ou seja, se sempre , o termo é mais geral do que , e vice-versa, embora e sejam de estrutura diferente.

Uma substituição é mais especial do que, ou subsumida por, uma substituição se for mais especial do que para cada termo . Também dizemos que é mais geral do que . Por exemplo, é mais especial do que , mas não é, pois não é mais especial do que .

Problema de unificação, conjunto de soluções

Um problema unificação é um conjunto finito { l 1r 1 , ..., L nr n } de equações potenciais, onde l i , r iT . Uma substituição σ é uma solução desse problema se l i σ ≡ r i σ para . Essa substituição também é chamada de unificador do problema da unificação. Por exemplo, se ⊕ é associativo , o problema de unificação { xaax } tem as soluções { xa }, { xaa }, { xaaa }, etc., enquanto o problema { xaa } não tem solução.

Para um dado problema de unificação, um conjunto S de unificadores é denominado completo se cada substituição de solução é subsumida por alguma substituição σ ∈ S ; o conjunto S é denominado mínimo se nenhum de seus membros inclui outro.

Unificação sintática de termos de primeira ordem

Diagrama de triângulo esquemático de termos unificando sintaticamente t 1 e t 2 por uma substituição σ

A unificação sintática de termos de primeira ordem é a estrutura de unificação mais amplamente usada. Baseia-se em T sendo o conjunto de termos de primeira ordem (sobre um determinado conjunto V de variáveis, C de constantes e F n de símbolos de função n -ary) e em ≡ sendo igualdade sintática . Nesta estrutura, cada problema de unificação solucionável { l 1r 1 , ..., l nr n } tem um conjunto de soluções singleton completo e obviamente mínimo { σ } . Seu membro σ é chamado de unificador mais geral ( mgu ) do problema. Os termos nos lados esquerdo e direito de cada equação potencial tornam-se sintaticamente iguais quando o mgu é aplicado, isto é, l 1 σ = r 1 σ ∧ ... ∧ l n σ = r n σ . Qualquer unificador do problema é subsumido pelo mgu σ . O mgu é único até as variantes: se S 1 e S 2 são conjuntos de soluções completas e mínimas do mesmo problema de unificação sintática, então S 1 = { σ 1 } e S 2 = { σ 2 } para algumas substituições σ 1 e σ 2 , e 1 é uma variante do 2 para cada uma das variáveis X que ocorre no problema.

Por exemplo, o problema de unificação { xz , yf ( x )} tem um unificador { xz , yf ( z )}, porque

x { xz , yf ( z )} = z = z { xz , yf ( z )} , e
y { xz , yf ( z )} = f ( z ) = f ( x ) { xz , yf ( z )} .

Este também é o unificador mais geral. Outros unificadores para o mesmo problema são, por exemplo, { xf ( x 1 ), yf ( f ( x 1 )), zf ( x 1 )}, { xf ( f ( x 1 )), yf ( f ( f ( x 1 ))), zf ( f ( x 1 ))}, e assim por diante; existem infinitamente muitos unificadores semelhantes.

Como outro exemplo, o problema g ( x , x ) ≐ f ( y ) não tem solução com respeito a ≡ ser identidade literal, uma vez que qualquer substituição aplicada ao lado esquerdo e direito manterá o g e f mais externo , respectivamente, e termos com diferentes símbolos de função externa são sintaticamente diferentes.

Um algoritmo de unificação

Algoritmo de unificação de Robinson 1965

Os símbolos são ordenados de forma que as variáveis ​​precedam os símbolos de função. Os termos são ordenados aumentando o comprimento da escrita; termos igualmente longos são ordenados lexicograficamente . Para um conjunto T de termos, seu caminho de discordância p é o caminho menos lexicograficamente no qual dois termos membros de T diferem. Seu conjunto de discordância é o conjunto de subtermos iniciando em p , formalmente: { t | p  : }.

Algoritmo:

Dado um conjunto T de termos a serem unificados Deixe inicialmente ser a substituição de identidade

faça para sempre se for um conjunto único, então retorne fi

deixar D ser o conjunto de desacordo let s , t ser os dois termos lexicograficamente menos em D

se s não é uma variável ou s ocorre em t então retorna "NÃO UNIFICÁVEL" fi feito

O primeiro algoritmo fornecido por Robinson (1965) era bastante ineficiente; cf. caixa. O seguinte algoritmo mais rápido originou-se de Martelli, Montanari (1982). Este artigo também lista as tentativas anteriores de encontrar um algoritmo de unificação sintática eficiente e afirma que os algoritmos de tempo linear foram descobertos de forma independente por Martelli, Montanari (1976) e Paterson, Wegman (1978).

Dado um conjunto finito de equações potenciais, o algoritmo aplica regras para transformá-lo em um conjunto equivalente de equações da forma { x 1u 1 , ..., x mu m } onde x 1 , ..., x m são variáveis ​​distintas e u 1 , ..., u m são termos que não contêm nenhum dos x i . Um conjunto deste formulário pode ser lido como uma substituição. Se não houver solução, o algoritmo termina com ⊥; outros autores usam "Ω", "{}" ou " reprovado " nesse caso. A operação de substituição de todas as ocorrências da variável x no problema G pelo termo t é denotada por G { xt }. Para simplificar, os símbolos constantes são considerados símbolos de função com zero argumentos.

    excluir
    decompor
se ou     conflito
    troca
se e     eliminar
E se     Verifica

Ocorre verificação

Uma tentativa de unificar uma variável x com um termo contendo x como um subtermo estrito xf (..., x , ...) levaria a um termo infinito como solução para x , uma vez que x ocorreria como um subtermo de si mesmo . No conjunto de termos (finitos) de primeira ordem conforme definido acima, a equação xf (..., x , ...) não tem solução; portanto, a regra de eliminação só pode ser aplicada se xvars ( t ). Uma vez que essa verificação adicional, chamada de verificação ocorre , retarda o algoritmo, ela é omitida, por exemplo, na maioria dos sistemas Prolog. Do ponto de vista teórico, omitir o cheque equivale a resolver equações em árvores infinitas, veja abaixo .

Prova de rescisão

Para a prova de término do algoritmo, considere um triplo, onde n var é o número de variáveis ​​que ocorrem mais de uma vez no conjunto de equações, n lhs é o número de símbolos e constantes de função no lado esquerdo das equações potenciais e n eqn é o número de equações. Quando a regra de eliminação é aplicada, n var diminui, uma vez que x é eliminado de G e mantido apenas em { xt }. A aplicação de qualquer outra regra nunca pode aumentar n var novamente. Quando a regra decompõe , conflito ou troca é aplicada, n lhs diminui, já que pelo menos o f mais externo do lado esquerdo desaparece. Aplicar qualquer uma das regras restantes de exclusão ou verificação não pode aumentar n lhs , mas diminui n eqn . Portanto, qualquer aplicação de regra diminui o triplo em relação à ordem lexicográfica , o que só é possível um número finito de vezes.

Conor McBride observa que "ao expressar a estrutura que a unificação explora" em uma linguagem com tipos dependentes como Epigram , o algoritmo de Robinson pode se tornar recursivo no número de variáveis , caso em que uma prova de terminação separada torna-se desnecessária.

Exemplos de unificação sintática de termos de primeira ordem

Na convenção sintática do Prolog, um símbolo que começa com uma letra maiúscula é um nome de variável; um símbolo que começa com uma letra minúscula é um símbolo de função; a vírgula é usada como o operador lógico e . Para notação matemática, x, y, z são usados ​​como variáveis, f, g como símbolos de função e a, b como constantes.

Notação prólogo Notação matemática Substituição unificadora Explicação
a = a { a = a } {} Bem-sucedido. ( tautologia )
a = b { a = b } a e b não correspondem
X = X { x = x } {} Bem-sucedido. ( tautologia )
a = X { a = x } { xa } x é unificado com a constante a
X = Y { x = y } { xy } x e y têm aliases
f(a,X) = f(a,b) { f ( a , x ) = f ( a , b )} { xb } função e símbolos constantes coincidem, x é unificado com a constante b
f(a) = g(a) { f ( a ) = g ( a )} f e g não combinam
f(X) = f(Y) { f ( x ) = f ( y )} { xy } x e y têm aliases
f(X) = g(Y) { f ( x ) = g ( y )} f e g não combinam
f(X) = f(Y,Z) { f ( x ) = f ( y , z )} Falha. Os símbolos da função f têm aridade diferente
f(g(X)) = f(Y) { f ( g ( x )) = f ( y )} { yg ( x )} Unifica y com o termo
f(g(X),X) = f(Y,a) { f ( g ( x ), x ) = f ( y , a )} { xa , yg ( a )} Unifica x com constante um , e y com o termo
X = f(X) { x = f ( x )} deveria ser ⊥ Retorna ⊥ na lógica de primeira ordem e em muitos dialetos Prolog modernos (reforçados pela verificação de ocorrências ).

É bem-sucedido no Prolog tradicional e no Prolog II, unificando x com termo infinito x=f(f(f(f(...)))).

X = Y, Y = a { x = y , y = a } { xa , ya } Tanto x quanto y são unificados com a constante a
a = Y, X = Y { a = y , x = y } { xa , ya } Como acima (a ordem das equações no conjunto não importa)
X = a, b = X { x = a , b = x } Falha. a e b não correspondem, de modo que x não pode ser unificado com ambos
Dois termos com uma árvore exponencialmente maior para sua instância menos comum. Sua representação dag (mais à direita, parte laranja) ainda é de tamanho linear.

O unificador mais geral de um problema de unificação sintática de primeira ordem de tamanho n pode ter um tamanho de 2 n . Por exemplo, o problema tem o unificador mais geral , cf. foto. Para evitar complexidade de tempo exponencial causada por tal explosão, algoritmos de unificação avançados trabalham em grafos acíclicos direcionados (dags) ao invés de árvores.

Aplicação: unificação na programação lógica

O conceito de unificação é uma das principais ideias por trás da programação lógica , mais conhecida por meio da linguagem Prolog . Ele representa o mecanismo de vinculação do conteúdo de variáveis ​​e pode ser visto como um tipo de atribuição única. No Prolog, esta operação é denotada pelo símbolo de igualdade =, mas também é feita ao instanciar variáveis ​​(veja abaixo). Ele também é usado em outros idiomas pelo uso do símbolo de igualdade =, mas também em conjunto com muitas operações, incluindo +, -, *, /. Os algoritmos de inferência de tipo são normalmente baseados na unificação.

No Prolog:

  1. Uma variável não instanciada - isto é, nenhuma unificação anterior foi executada nela - pode ser unificada com um átomo, um termo ou outra variável não instanciada, tornando-se assim efetivamente seu apelido. Em muitos dialetos Prolog modernos e na lógica de primeira ordem , uma variável não pode ser unificada com um termo que a contém; esta é a chamada verificação de ocorrência .
  2. Dois átomos só podem ser unificados se forem idênticos.
  3. Da mesma forma, um termo pode ser unificado com outro termo se os símbolos de função superior e aridades dos termos forem idênticos e se os parâmetros puderem ser unificados simultaneamente. Observe que este é um comportamento recursivo.

Aplicação: inferência de tipo

A unificação é usada durante a inferência de tipo, por exemplo, na linguagem de programação funcional Haskell . Por um lado, o programador não precisa fornecer informações de tipo para todas as funções, por outro lado, é usado para detectar erros de digitação. A expressão Haskell True : ['x', 'y', 'z']não foi digitada corretamente. A função de construção de lista (:)é do tipo a -> [a] -> [a]e, para o primeiro argumento, Truea variável de tipo polimórfico adeve ser unificada com Trueo tipo de Bool,. O segundo argumento, ['x', 'y', 'z']é do tipo [Char], mas anão pode ser ao mesmo tempo Boole Char, ao mesmo tempo.

Como para Prolog, um algoritmo para inferência de tipo pode ser fornecido:

  1. Qualquer variável de tipo unifica-se com qualquer expressão de tipo e é instanciada para essa expressão. Uma teoria específica pode restringir esta regra com uma verificação de ocorrência.
  2. Duas constantes de tipo se unificam apenas se forem do mesmo tipo.
  3. Duas construções de tipo unificam apenas se forem aplicativos do mesmo construtor de tipo e todos os seus tipos de componente se unificar recursivamente.

Devido à sua natureza declarativa, a ordem em uma sequência de unificações (geralmente) não é importante.

Observe que, na terminologia da lógica de primeira ordem , um átomo é uma proposição básica e é unificado de forma semelhante a um termo Prolog.

Unificação ordenada por ordem

A lógica de ordenação permite atribuir uma classificação , ou tipo , a cada termo e declarar uma classificação s 1 uma subclassificação de outra classificação s 2 , comumente escrita como s 1 s 2 . Por exemplo, ao refletir sobre criaturas biológicas, é útil declarar um cão de classificaçãocomo uma subclasse de uma espécie de animal . Sempre que um termo de algum tipo s é necessário, um termo de qualquer subconjunto de s pode ser fornecido em seu lugar. Por exemplo, assumindo uma declaração de função mãe : animal animal , e uma declaração constante lassie : cachorro , o termo mãe ( moça ) é perfeitamente válido e tem o tipo animal . Para fornecer a informação de que a mãe de um cão é por sua vez um cão, pode ser emitidaoutra declaração mãe : cão cão ; isso é chamado de sobrecarga de função , semelhante à sobrecarga em linguagens de programação .

Walther deu um algoritmo de unificação de termos na lógica fim-ordenada, exigindo para quaisquer dois tipos declarados s 1 , s 2 a sua intersecção s 1s 2 a ser declarada, também: se x 1 e x 2 é uma variável do tipo s 1 e s 2 , respectivamente, a equação x 1x 2 tem a solução { x 1 = x , x 2 = x }, onde x : s 1s 2 . Depois de incorporar este algoritmo em um provador de teoremas automatizado baseado em cláusulas, ele poderia resolver um problema de benchmark traduzindo-o em lógica ordenada, assim reduzindo-o a uma ordem de magnitude, conforme muitos predicados unários se transformavam em tipos.

Smolka generalizou a lógica ordenada para permitir o polimorfismo paramétrico . Em sua estrutura, as declarações de subclassificação são propagadas para expressões de tipo complexo. Como um exemplo de programação, uma lista de classificação paramétrica ( X ) pode ser declarada (com X sendo um parâmetro de tipo como em um modelo C ++ ), e de uma declaração de subsorte intfloat a lista de relação ( int ) ⊆ lista ( float ) é automaticamente inferida, o que significa que cada lista de inteiros também é uma lista de floats.

Schmidt-Schauß generalizou a lógica ordenada para permitir declarações de termos. Como exemplo, assumindo declarações de subclassificação parint e ímparint , uma declaração de termo como ∀ i  : int . ( i + i ): permite ainda declarar uma propriedade de adição inteira que não poderia ser expressa por sobrecarga comum.

Unificação de termos infinitos

Plano de fundo em árvores infinitas:

  • B. Courcelle (1983). "Propriedades Fundamentais das Árvores Infinitas" (PDF) . Theoret. Comput. Sci . 25 (2): 95–169. doi : 10.1016 / 0304-3975 (83) 90059-2 . Arquivo do original (PDF) em 21/04/2014 . Página visitada em 28/06/2013 .
  • Michael J. Maher (julho de 1988). "Axiomatizações Completas das Álgebras de Árvores Finitas, Racionais e Infinitas". Proc. IEEE 3rd Annual Symp. on Logic in Computer Science, Edimburgo . pp. 348–357.
  • Joxan Jaffar; Peter J. Stuckey (1986). "Semântica de Programação Lógica de Árvore Infinita" . Ciência da Computação Teórica . 46 : 141–158. doi : 10.1016 / 0304-3975 (86) 90027-7 .

Algoritmo de unificação, Prolog II:

  • A. Colmerauer (1982). KL Clark; S.-A. Tarnlund (eds.). Árvores Prolog e Infinitas . Academic Press.
  • Alain Colmerauer (1984). "Equações e Inequações em Árvores Finitas e Infinitas". Em ICOT (ed.). Proc. Int. Conf. em sistemas de computador de quinta geração . pp. 85–99.

Formulários:

E-unificação

E-unificação é o problema de encontrar soluções para um determinado conjunto de equações , tendo em conta alguns equational conhecimento de fundo E . O último é dado como um conjunto de igualdades universais . Para alguns conjuntos específicos E , algoritmos de resolução de equações (também conhecidos como algoritmos de unificação E ) foram desenvolvidos; para outros, foi provado que nenhum desses algoritmos pode existir.

Por exemplo, se um e b são constantes distintas, a equação não tem uma solução no que diz respeito ao puramente unificação sintática , onde nada se sabe sobre o operador . No entanto, se o é conhecido como comutativo , então a substituição { xb , ya } resolve a equação acima, uma vez que

{ xb , ya }
= por aplicação de substituição
= por comutatividade de
= { xb , ya } por aplicação de substituição (inversa)

O conhecimento de fundo E poderia indicar a comutatividade de pela igualdade universal " para todos u , v ".

Conjunto de conhecimentos básicos específicos E

Usou convenções de nomenclatura
u , v , w : = UMA Associatividade de
u , v : = C Comutatividade de
u , v , w : = D l Distributividade esquerda de mais
u , v , w : = D r Distributividade certa de mais
u : = você eu Idempotência de
u : = você N l Elemento neutro esquerdo n em relação a
u : = você     N r     Elemento neutro direito n com respeito a

Diz-se que a unificação é decidível para uma teoria, se um algoritmo de unificação foi desenvolvido para ela que termina para qualquer problema de entrada. Diz-se que a unificação é semidecidível para uma teoria, se um algoritmo de unificação foi desenvolvido para ela que termina para qualquer problema de entrada solucionável , mas pode continuar procurando para sempre por soluções de um problema de entrada insolúvel.

A unificação é decidível para as seguintes teorias:

A unificação é semidecidível para as seguintes teorias:

Paramodulação unilateral

Se houver um sistema de reescrita de termo convergente R disponível para E , o algoritmo de paramodulação unilateral pode ser usado para enumerar todas as soluções de determinadas equações.

Regras de paramodulação unilateral
G ∪ { f ( s 1 , ..., s n ) ≐ f ( t 1 , ..., t n )} ; S G ∪ { s 1t 1 , ..., s nt n } ; S     decompor
G ∪ { xt } ; S G { xt } ; S { xt } ∪ { xt } se a variável x não ocorre em t     eliminar
G ∪ { f ( s 1 , ..., s n ) ≐ t } ; S G ∪ { s 1 ≐ u 1 , ..., s n ≐ u n , rt } ; S     se f ( u 1 , ..., u n ) → r é uma regra de R     mutação
G ∪ { f ( s 1 , ..., s n ) ≐ y } ; S G ∪ { s 1y 1 , ..., s ny n , yf ( y 1 , ..., y n )} ; S se y 1 , ..., y n são novas variáveis     imitar

Começando com G sendo o problema de unificação a ser resolvido e S sendo a substituição de identidade, as regras são aplicadas de forma não determinística até que o conjunto vazio apareça como o G real , caso em que o S real é uma substituição unificadora. Dependendo do fim das regras paramodulation são aplicadas, sobre a escolha da equação real a partir de L , e sobre a escolha de R ' regras s em mutação , diferentes caminhos computações são possíveis. Apenas alguns levam a uma solução, enquanto outros terminam em um G ≠ {} onde nenhuma regra adicional é aplicável (por exemplo, G = { f (...) ≐ g (...)}).

Exemplo de sistema de reescrita de termo R
1 app ( nulo , z ) z
2     app ( x . y , z ) x . app ( y , z )

Por exemplo, um termo sistema de reescrita R é usado definindo o operador de acréscimo de listas construídas a partir de cons e nil ; onde cons ( x , y ) é escrito em notação infixa como x . y por brevidade; por exemplo, app ( a . b . nulo , c . d . nulo ) → a . app ( b . nulo , c . d . nulo ) → a . b . app ( nulo , c . d . nulo ) → a . b . c . d . nil demonstra a concatenação das listas a . b . nulo e c . d . nil , empregando a regra de reescrita 2,2, e 1. A teoria equacional E correspondente a R é o fechamento de congruência de R , ambos vistos como relações binárias em termos. Por exemplo, app ( a . B . Nula , c . D . Nil ) ≡ um . b . c . d . nuloapp ( a . b . c . d . nulo , nulo ). O algoritmo paramodulation enumera soluções para as equações com respeito ao que E , quando alimentado com o exemplo I .

Um exemplo de caminho de computação bem-sucedido para o problema de unificação { app ( x , app ( y , x )) ≐ a . a . nil } é mostrado abaixo. Para evitar conflitos de nomes de variáveis, as regras de reescrita são renomeadas consistentemente todas as vezes antes de serem usadas por mutação de regra ; v 2 , v 3 , ... são nomes de variáveis ​​gerados por computador para esse propósito. Em cada linha, a equação escolhida de G é destacada em vermelho. Cada vez que a regra de mutação é aplicada, a regra de reescrita escolhida ( 1 ou 2 ) é indicada entre parênteses. Da última linha, a substituição unificadora S = { ynil , xa . nil } pode ser obtido. Na verdade, app ( x , app ( y , x )) { ynil , xa . nil } = app ( a . nil , app ( nil , a . nil )) ≡ app ( a . nil , a . nil ) ≡ a . app ( nulo , a . nulo ) ≡ a . a . nil resolve o problema fornecido. Um segundo caminho de computação bem-sucedido, obtido escolhendo "mutate (1), mutate (2), mutate (2), mutate (1)" leva à substituição S = { ya . a . nulo , xnulo }; não é mostrado aqui. Nenhum outro caminho leva ao sucesso.

Exemplo de computação unificadora
Regra usada G S
{ app ( x , app ( y , x )) ≐ a . a . nulo } {}
mutate (2) { xv 2 . v 3 , app ( y , x ) ≐ v 4 , v 2 . app ( v 3 , v 4 ) ≐ a . a . nulo } {}
decompor { xv 2 . v 3 , app ( y , x ) ≐ v 4 , v 2a , app ( v 3 , v 4 ) ≐ a . nulo } {}
eliminar { App ( y , v 2 . V 3 ) ≐ v 4 , v 2um , app ( v 3 , v 4 ) ≐ um . nulo } { xv 2 . v 3 }
eliminar { app ( y , a . v 3 ) ≐ v 4 , app ( v 3 , v 4 ) ≐ a . nulo } { xa . v 3 }
mutate (1) { ynulo , a . v 3v 5 , v 5v 4 , app ( v 3 , v 4 ) ≐ a . nulo } { xa . v 3 }
eliminar { ynulo , a . v 3v 4 , app ( v 3 , v 4 ) ≐ a . nulo } { xa . v 3 }
eliminar { a . v 3v 4 , app ( v 3 , v 4 ) ≐ a . nulo } { ynulo , xa . v 3 }
mutate (1) { a . v 3v 4 , v 3nulo , v 4v 6 , v 6a . nulo } { ynulo , xa . v 3 }
eliminar { a . v 3v 4 , v 3nulo , v 4a . nulo } { ynulo , xa . v 3 }
eliminar { a . nilv 4 , v 4a . nulo } { ynulo , xa . nulo }
eliminar { a . nila . nulo } { ynulo , xa . nulo }
decompor { aa , nilnil } { ynulo , xa . nulo }
decompor { nulonulo } { ynulo , xa . nulo }
decompor     ⇒     {} { ynulo , xa . nulo }

Estreitando

Diagrama de triângulo da etapa de estreitamento st na posição p no termo s , com substituição unificadora σ (linha inferior), usando uma regra de reescrita lr (linha superior)

Se R é um sistema de reescrita de termo convergente para E , uma alternativa de abordagem à seção anterior consiste na aplicação sucessiva de " etapas de estreitamento "; isso irá eventualmente enumerar todas as soluções de uma dada equação. Uma etapa de estreitamento (cf. imagem) consiste em

  • escolher um subtermo não variável do termo atual,
  • unificando sintaticamente com o lado esquerdo de uma regra de R , e
  • substituindo o lado direito da regra instanciada no termo instanciado.

Formalmente, se lr é uma cópia renomeada de uma regra de reescrita de R , não tendo variáveis ​​em comum com um termo s , e o subtermo s | p não é uma variável e é unificável com l via mgu σ , então s pode ser reduzido ao termo t = [ ] p , ou seja, ao termo , com o subtermo em p substituído por . A situação em que s pode ser reduzida a t é comumente denotada como st . Intuitivamente, uma sequência de etapas de estreitamento t 1t 2 ↝ ... ↝ t n pode ser pensada como uma sequência de etapas de reescrita t 1t 2 → ... → t n , mas com o termo inicial t 1 sendo cada vez mais instanciado, conforme necessário para tornar cada uma das regras utilizadas aplicável.

O cálculo de paramodulação do exemplo acima corresponde à seguinte sequência de estreitamento ("↓" indicando instanciação aqui):

app ( x , app ( y , x ))
xv 2 . v 3
app ( v 2 . v 3 , app ( y , v 2 . v 3 )) v 2 . aplicativo ( v 3 , aplicativo ( y , v 2 . v 3 ))
ynil
v 2 . aplicativo ( v 3 , aplicativo ( nada , v 2 . v 3 )) v 2 . app ( v 3 , v 2 . v 3 )
v 3nulo
v 2 . app ( nada , v 2 . nada ) v 2 . v 2 . nada

O último termo, v 2 . v 2 . nil pode ser sintaticamente unificado com o termo original do lado direito a . a . nulo .

O lema de estreitamento garante que sempre que uma instância de um termo s pode ser reescrito para um termo t por um sistema de reescrita de termo convergente, então s e t podem ser estreitados e reescritos para um termo s e t , respectivamente, de modo que t é uma instância de s .

Formalmente: sempre que t vale para alguma substituição σ, então existem termos s , t tais que s s e t t ' e s ' τ = t ' para alguns τ substituição.

Unificação de ordem superior

Muitos aplicativos requerem que se considere a unificação de termos lambda digitados em vez de termos de primeira ordem. Essa unificação é freqüentemente chamada de unificação de ordem superior . Um ramo bem estudado da unificação de ordem superior é o problema de unificar termos lambda simplesmente digitados modulo a igualdade determinada por conversões αβη. Esses problemas de unificação não têm os unificadores mais gerais. Enquanto a unificação de ordem superior é indecidível , Gérard Huet deu um algoritmo de unificação semidecidível (pré-) que permite uma busca sistemática do espaço de unificadores (generalizando o algoritmo de unificação de Martelli-Montanari com regras para termos contendo variáveis ​​de ordem superior) que parece funcionar suficientemente bem na prática. Huet e Gilles Dowek escreveram artigos sobre esse tópico.

Dale Miller descreveu o que agora é chamado de unificação de padrões de ordem superior . Este subconjunto de unificação de ordem superior é decidível e os problemas de unificação solucionáveis ​​têm unificadores mais gerais. Muitos sistemas de computador que contêm unificação de ordem superior, como as linguagens de programação lógica de ordem superior λProlog e Twelf , geralmente implementam apenas o fragmento de padrão e não a unificação completa de ordem superior.

Na linguística computacional, uma das teorias mais influentes da elipse é que as elipses são representadas por variáveis ​​livres cujos valores são então determinados usando a Unificação de Ordem Superior (HOU). Por exemplo, a representação semântica de "Jon gosta de Mary e Peter também" é como ( j , m ) ∧ R ( p ) e o valor de R (a representação semântica da elipse) é determinado pela equação como ( j , m ) = R ( j ) . O processo de resolução de tais equações é chamado de Unificação de Ordem Superior.

Por exemplo, o problema de unificação { f ( a , b , a ) ≐ d ( b , a , c )}, onde a única variável é f , tem as soluções { f ↦ λ xyz . d ( y , x , c )}, { f ↦ λ xyz . d ( y , z , c )}, { f ↦ λ xyz . d ( y , a , c )}, { f ↦ λ xyz . d ( b , x , c )}, { f ↦ λ xyz . d ( b , z , c )} e { f ↦ λ xyz . d ( b , a , c )}.

Wayne Snyder deu uma generalização da unificação de ordem superior e da unificação E, ou seja, um algoritmo para unificar o módulo de termos lambda e uma teoria equacional.

Veja também

Notas

Referências

Leitura adicional