From 3cb3cab5dd23423dfc70e911499d33ffa819a94f Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 19 Oct 2026 00:13:35 -0300 Subject: [PATCH 01/20] feat(Composition): add the chapter skeleton for CSwFP/7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add CSwL/Composition.lean with the headings of 7.1–7.7, wire it into Book.lean, and map chapter 7's sections and 28 exercises in CSwFP.yaml, flagging the overlaps with InfEngine, IntroL and ModelChecking. Record in the style guides the :::terse/:::full pattern from sf-in-lean, starting with this chapter, and that a :::terse cue may be drafted by AI and approved by a human. This change was prepared with the assistance of Claude Code (Anthropic); all edits were reviewed by the author. --- Book.lean | 2 ++ CSwFP.yaml | 50 +++++++++++++++++++++++++++++++++- CSwL/Composition.lean | 62 ++++++++++++++++++++++++++++++++++++++++++ DEVIATIONS.md | 11 ++++++-- README.md | 2 +- STYLE-CODE.md | 12 ++++++++ STYLE-WRITING.md | 5 ++++ scripts/check-cswfp.py | 3 +- 8 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 CSwL/Composition.lean diff --git a/Book.lean b/Book.lean index 76f2ecf..8f9478a 100644 --- a/Book.lean +++ b/Book.lean @@ -9,6 +9,7 @@ import CSwL.SeaBattle import CSwL.Morphology import CSwL.InfEngine import CSwL.ModelChecking +import CSwL.Composition import VersoManual @@ -35,3 +36,4 @@ set_option verso.code.warnLineLength 80 {include CSwL.Morphology} {include CSwL.InfEngine} {include CSwL.ModelChecking} +{include CSwL.Composition} diff --git a/CSwFP.yaml b/CSwFP.yaml index 40d7f5a..dbf9945 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -129,6 +129,36 @@ exercises: 6.6 (p. 146): TODO, goes with 6.5 to Logic/FOL 6.7 (p. 147): check-sentence + CSwFP/7: + 7.1 (p. 158): TODO + 7.2 (p. 158): TODO + 7.3 (p. 158): TODO + 7.4 (p. 161): TODO + 7.5 (p. 161): TODO + 7.6 (p. 161): TODO + 7.7 (p. 162): TODO + 7.8 (p. 162): TODO + 7.9 (p. 162): TODO + 7.10 (p. 162): TODO + 7.11 (p. 163): TODO + 7.12 (p. 164): TODO + 7.13 (p. 165): TODO + 7.14 (p. 165): TODO + 7.15 (p. 166): TODO + 7.16 (p. 166): TODO + 7.17 (p. 166): TODO + 7.18 (p. 166): TODO + 7.19 (p. 168): TODO + 7.20 (p. 170): TODO + 7.21 (p. 170): TODO + 7.22 (p. 172): TODO + 7.23 (p. 173): TODO + 7.24 (p. 175): TODO + 7.25 (p. 179): TODO + 7.26 (p. 180): TODO + 7.27 (p. 181): TODO + 7.28 (p. 182): TODO + original: IntroL.lean: [sum-of-squares, sum-to, sum-list, count-zeros] Logic/Proof.lean: @@ -267,7 +297,25 @@ sections: `[0..]` becomes a theorem, since Lean is not lazy. 6.6 Further Reading: omitted - CSwFP/7 The Composition of Meaning in Natural Language: not yet taken up + CSwFP/7: + 7.1 Rules of the Game: Composition + 7.2 Quantification: + to: Composition + why: TODO, its Aristotle-to-Frege opening retells what InfEngine + already presents with the syllogisms. + 7.3 The Language of Typed Logic and Its Semantics: + to: Composition + why: TODO, it overlaps the lambda calculus that IntroL takes from 2.4. + 7.4 Reducing Expressions of Typed Logic: + to: Composition + why: TODO, it overlaps the lambda calculus that IntroL takes from 2.4. + 7.5 Typed Meanings for Natural Language: Composition + 7.6 Implementing Semantic Interpretation: Composition + 7.7 Handling Ambiguity: + to: Composition + why: TODO, its exercises build on the prepositional phrases that + ModelChecking adds to the fragment. + 7.8 Further Reading: omitted CSwFP/8 Extension and Intension: not yet taken up CSwFP/9 Parsing: not yet taken up CSwFP/10 Handling Relations and Scoping: not yet taken up diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean new file mode 100644 index 0000000..4a5785a --- /dev/null +++ b/CSwL/Composition.lean @@ -0,0 +1,62 @@ +import CSwLMeta +import Bib +import CSwL.ModelChecking + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "A composição do significado na língua natural" => +%%% +tag := "Composition" +htmlSplit := .never +file := "Composition" +%%% + +```lean +namespace Composition +``` + +:::dev NOW +Skeleton: the headings follow CSwFP/7.1–7.7 (7.8, further reading, is +omitted). Each section is to be translated into `:::full` blocks, with a +`:::terse` cue before each `lean` block (see `STYLE-CODE.md`). +::: + +# As regras do jogo +%%% +tag := "comp-rules" +%%% + +# Quantificação +%%% +tag := "comp-quantification" +%%% + +# A linguagem da lógica tipada e sua semântica +%%% +tag := "comp-typed-logic" +%%% + +# Redução de expressões da lógica tipada +%%% +tag := "comp-reduction" +%%% + +# Significados tipados para a língua natural +%%% +tag := "comp-typed-meanings" +%%% + +# Implementando a interpretação semântica +%%% +tag := "comp-interpretation" +%%% + +# Tratando a ambiguidade +%%% +tag := "comp-ambiguity" +%%% + +```lean +end Composition +``` diff --git a/DEVIATIONS.md b/DEVIATIONS.md index cb7822c..9724927 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -129,7 +129,12 @@ decisions inside the chapters. `FInterp`; and names and argument order agree with the translation, which in the Haskell source they do not. -## Beyond CSwFP/6 +### `Composition` -Not planned yet. CSwFP/7 continues the fragment of `ModelChecking` and builds on the -same syntax, so it comes after `ModelChecking`. +CSwFP/7 continues the fragment of `ModelChecking` and builds on the same +syntax and model, so it comes after `ModelChecking`. Being written; no +departures recorded yet. + +## Beyond CSwFP/7 + +Not planned yet. diff --git a/README.md b/README.md index 7b66a21..3c0835a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ adapts — see [DEVIATIONS.md](DEVIATIONS.md) for why. [`CSwL/Morphology/`](CSwL/Morphology)) - [~] An inference engine — [source](CSwL/InfEngine.lean) - [~] Model checking with first-order logic — [source](CSwL/ModelChecking.lean) -- [ ] The composition of meaning +- [~] The composition of meaning — [source](CSwL/Composition.lean) - [ ] Extension and intension - [ ] Parsing - [ ] Relations and scope diff --git a/STYLE-CODE.md b/STYLE-CODE.md index 9785565..877d799 100644 --- a/STYLE-CODE.md +++ b/STYLE-CODE.md @@ -266,6 +266,18 @@ Prose can be routed to a variant: - `:::suppressPreviousHeaderWhenTerse` — drops the preceding heading in the `terse` build, where the prose under it is gone and the heading would dangle. +The standard pattern, as in sf-in-lean, is a `:::terse` cue followed by the +`:::full` prose it stands in for, followed by the shared ```` ```lean ```` block. +The cue is one or two sentences for the instructor at the keyboard, about what +the Lean code does and how; the `:::full` block holds the narrative a reader +needs on their own, including any prose translated from CSwFP. Code, exercises, +quizzes and `:::dev` notes stay outside both, so every variant has them. Prose +that serves both audiences equally can stay outside both too. + +`Composition` is the first chapter written this way. The chapters before it +have no `:::terse` cues yet, so their `terse` variant carries the full prose; +each gets its cues when it is next revised. + ### Notes and commentary - `:::dev` — an internal note to the authors, rendered under the heading diff --git a/STYLE-WRITING.md b/STYLE-WRITING.md index e585bc5..e2a7326 100644 --- a/STYLE-WRITING.md +++ b/STYLE-WRITING.md @@ -122,6 +122,11 @@ The book is in Brazilian Portuguese. Where AI is used to translate, the translation is as literal as the target language allows, produced as a draft for a human to revise. Prose is never invented, expanded, or restructured on the AI's initiative — see `CLAUDE.md`. + +A `:::terse` cue (see `STYLE-CODE.md`) is the one exception: it is new text by +nature, not a translation, since CSwFP has no lecture cut. AI may draft a cue, +one block at a time, and a human approves or rewrites each one. The `:::full` +prose next to it keeps the rule above. The failure mode this section guards against is the systematic one: a translation that is fluent, plausible, and consistently wrong about a term. diff --git a/scripts/check-cswfp.py b/scripts/check-cswfp.py index f3fe56d..237c535 100755 --- a/scripts/check-cswfp.py +++ b/scripts/check-cswfp.py @@ -30,7 +30,8 @@ # How many exercises each CSwFP chapter has. COUNTS = {"CSwFP/1": 3, "CSwFP/2": 17, "CSwFP/3": 19, - "CSwFP/4": 24, "CSwFP/5": 32, "CSwFP/6": 7} + "CSwFP/4": 24, "CSwFP/5": 32, "CSwFP/6": 7, + "CSwFP/7": 28} EXERCISE = re.compile(r'^:+exercise\b.*\(name := "([^"]+)"\)') CITATION = re.compile(r"CSwFP|página \d+|\(p\. \d+|§\s*\d|exemplo \(\d+\.\d+\)" From 76821ee633370149bd35fd02859813e45ba412f8 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 19 Oct 2026 00:31:09 -0300 Subject: [PATCH 02/20] feat(Composition): translate the chapter opening and 7.1 Translate the chapter summary as the opening, with Lean in place of Haskell as the lambda-calculus engine of ModelChecking, and 7.1, all in :::full blocks; 7.1 has no code, so its heading is dropped from the terse variant. This change was prepared with the assistance of Claude Code (Anthropic); all edits were reviewed by the author. --- CSwL/Composition.lean | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 4a5785a..bada22d 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -16,6 +16,13 @@ file := "Composition" namespace Composition ``` +:::full +Em {ref "ModelChecking"}[Verificação de modelos com lógica de primeira ordem] demos uma interpretação indireta para o nosso fragmento do inglês. Traduzimos sentenças para formas lógicas e depois avaliamos essas formas lógicas em relação a um modelo. As formas lógicas eram fórmulas da lógica de predicados, construídas a partir de expressões da lógica tipada. +Usamos o Lean como implementação do cálculo lambda para esse procedimento de construção. Isso funcionou muito bem, mas tem a desvantagem de que o Lean esconde os detalhes de como as expressões da lógica tipada são simplificadas. + +Neste capítulo, vamos demonstrar que a composição do significado pode ser realizada sem uma linguagem de formas lógicas como nível intermediário de representação. Daremos instruções diretas para ligar expressões da língua natural ao "mundo" fora da língua (representado por um modelo). Mostraremos como modelos da lógica de predicados podem ser estendidos a modelos da lógica tipada, e como a lógica tipada fornece representações de significado apropriadas para os itens lexicais de fragmentos de língua natural e oferece os meios para construir significados de modo composicional. Mas antes de nos dedicarmos a isso, precisamos nos concentrar num ingrediente-chave da semântica da língua natural: os quantificadores. +::: + :::dev NOW Skeleton: the headings follow CSwFP/7.1–7.7 (7.8, further reading, is omitted). Each section is to be translated into `:::full` blocks, with a @@ -27,6 +34,44 @@ omitted). Each section is to be translated into `:::full` blocks, with a tag := "comp-rules" %%% +:::suppressPreviousHeaderWhenTerse +::: + +:::full +Pedir a alguém que traduza para uma lógica as sentenças de um fragmento de uma linguagem natural como o inglês, definido por um conjunto de regras gramaticais, pressupõe duas coisas: (i) que essa pessoa compreenda o significado das fórmulas da linguagem lógica, e (ii) que compreenda o significado das sentenças do fragmento do inglês. O primeiro tipo de conhecimento pode ser formulado de modo totalmente explícito; essa é justamente a função das definições semânticas de verdade das linguagens lógicas. Aliás, os exercícios de tradução desse tipo, comuns nos livros de lógica, servem para mostrar ao leitor o poder expressivo da linguagem de representação, ao pedir que ele exprima nesse novo meio uma mensagem que (intuitivamente) já compreende bem. Como essas traduções pressupõem que a +mensagem original já foi compreendida, elas não podem contar como uma explicação do conceito de significado para a língua natural. + +Como vimos em {ref "english-lf"}[FOL como linguagem de representação], é +possível tornar plenamente explícito o conhecimento do significado de um +fragmento de língua natural. O que demos lá é um procedimento de tradução da +língua natural para a lógica de predicados que pode contar como uma explicação +do conceito de significado para a língua natural. O procedimento não pressupõe +o conhecimento do significado de sentenças completas da língua natural. Em vez +disso, ele especifica como os significados das sentenças são derivados dos +significados de blocos de construção menores. Os significados de expressões +complexas são construídos de maneira sistemática a partir dos significados dos +menores blocos de construção que ocorrem nessas expressões. O significado +desses menores blocos de construção é tomado como dado. Supomos que eles são +dados por instruções que ligam palavras individuais à realidade fora da +língua. No nosso exemplo, essas ligações são feitas pelas instruções de +interpretação dos símbolos de relação e de função num modelo da lógica de +predicados. A semântica computacional tem pouco ou nada a dizer sobre a +interpretação dos átomos semânticos. Tem bastante a dizer, no entanto, sobre o +processo de compor significados complexos de maneira sistemática a partir dos +significados dos componentes. A intuição de que isso é sempre possível pode ser +enunciada de modo um pouco mais preciso; ela se chama Princípio da +Composicionalidade, que já encontramos em {ref "IntroCS"}[O estudo formal da +língua natural]: + +> O significado de uma expressão é uma função dos significados de seus +> componentes sintáticos imediatos e de seu modo sintático de composição. + +O princípio da composicionalidade está implícito na obra de Frege sobre a +filosofia da linguagem, e foi tornado plenamente explícito na abordagem de +Richard Montague à semântica da língua natural. Outro elemento-chave na +semântica ao estilo de Montague é o tratamento dos quantificadores. +::: + # Quantificação %%% tag := "comp-quantification" From 95047b3a3172b49dd3b1d864a00d71f3ea0753a6 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 19 Oct 2026 11:57:14 -0300 Subject: [PATCH 03/20] feat(Composition): translate the opening of 7.2 and the relational view Translate the opening of 7.2, cutting to a reminder the two paragraphs that ModelChecking's english-form already covers, and the subsection on the relational view of quantifiers, with `every` as the chapter's first Lean code. Add Mostowski (1957) and Barwise and Cooper (1981) to Bib, record "escopo" for both scope and body in the term list, and record the departures in DEVIATIONS.md. This change was prepared with the assistance of Claude Code (Anthropic); all edits were reviewed by the author. --- Bib.lean | 18 ++++ CSwL/Composition.lean | 242 ++++++++++++++++++++++++++++++++++++++++++ DEVIATIONS.md | 16 ++- STYLE-WRITING.md | 2 + 4 files changed, 276 insertions(+), 2 deletions(-) diff --git a/Bib.lean b/Bib.lean index 501cbc7..a3ec26e 100644 --- a/Bib.lean +++ b/Bib.lean @@ -153,4 +153,22 @@ def FAA2025 : Article where number := inlines!"" url := "https://github.com/sorrachai/FAA2025" +def mostowski1957 : Article where + title := inlines!"On a generalization of quantifiers" + authors := #[inlines!"Andrzej Mostowski"] + journal := inlines!"Fundamenta Mathematicae" + year := 1957 + month := none + volume := inlines!"44" + number := inlines!"" + +def barwise1981 : Article where + title := inlines!"Generalized quantifiers and natural language" + authors := #[inlines!"Jon Barwise", inlines!"Robin Cooper"] + journal := inlines!"Linguistics and Philosophy" + year := 1981 + month := none + volume := inlines!"4" + number := inlines!"" + end Bib diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index bada22d..996f5ad 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -14,6 +14,8 @@ file := "Composition" ```lean namespace Composition + +open ModelChecking ``` :::full @@ -77,6 +79,246 @@ semântica ao estilo de Montague é o tratamento dos quantificadores. tag := "comp-quantification" %%% +::::full +Um objetivo importante da semântica computacional é dar conta do processo de tirar inferências na língua natural. Um papel-chave nesse processo cabe aos quantificadores, e por isso a quantificação é um tópico de interesse central na semântica computacional. O primeiro tratamento sistemático da quantificação é o de Aristóteles; veja {ref "InfEngine"}[Um motor de inferência]. Por impressionante que seja, a teoria aristotélica da quantificação tem dois defeitos lógicos: + +1. Combinações de quantificadores não são tratadas; só se permite um + quantificador por sentença. +2. Quantificadores como *most*, *half of*, *at least five*, não são cobertos. + +Um defeito adicional, menor, é a suposição da pressuposição existencial. No +raciocínio matemático, e às vezes também no raciocínio cotidiano, queremos +poder afirmar enunciados universalmente quantificados sem o incômodo de antes +ter de fornecer provas de existência. + +O primeiro desses defeitos foi removido por Frege. A teoria da quantificação de +Frege é basicamente o que hoje chamamos de lógica de predicados. Ela se baseia +na introdução de variáveis individuais ligadas pelos quantificadores ∀ ("para +todo") e ∃ ("existe"). Os quantificadores, com suas variáveis associadas, podem +se combinar com fórmulas arbitrariamente complexas da lógica de predicados para +formar novas fórmulas da lógica de predicados, de modo que uma fórmula pode +conter um número arbitrário de quantificadores. + +Os quantificadores ∀ e ∃ são chamados de quantificadores padrão. Esses dois +quantificadores são interdefiníveis com a ajuda da negação: *Algo fede* +significa o mesmo que *Não é o caso que, para todo x, x não fede*, e *Tudo está +bem* significa o mesmo que *Não é o caso que existe uma coisa x com a +propriedade de que x não está bem*. Mais formalmente: $`\exists x\, P x` é +verdadeira se e somente se $`\neg \forall x\, \neg P x` é verdadeira, e +$`\forall x\, P x` é verdadeira se e somente se $`\neg \exists x\, \neg P x` é +verdadeira. + +Se convenientemente esquecermos as pressuposições existenciais, os +quantificadores aristotélicos do quadrado das oposições (veja +{ref "InfEngine"}[Um motor de inferência]) podem ser expressos em termos dos +quantificadores padrão de Frege da seguinte maneira (com ⇝ para "traduz-se +como"): + +:::table +* * Todo A é B + * $`\forall x (A x \to B x)` +* * Algum A é B + * $`\exists x (A x \land B x)` +* * Nenhum A é B + * $`\forall x (A x \to \neg B x)` +* * Nem todo A é B + * $`\neg \forall x (A x \to B x)` +::: + +Algo a notar é que diferentes maneiras de exprimir um quantificador +aristotélico na lógica de Frege podem ser equivalentes. Outra tradução possível +para *Nenhum A é B* é $`\neg \exists x (A x \land B x)`. Não há o que escolher +entre as duas traduções, porque em toda situação em que a primeira é verdadeira +a segunda também é, e vice-versa. + +Usando os quantificadores padrão e a igualdade, também é possível exprimir +restrições numéricas como *Pelo menos dois A são B*: + +$$`\exists x \exists y (x \neq y \land A x \land A y \land B x \land B y).` + +Não é difícil ver que todas as disjunções e conjunções de quantificadores das +formas *pelo menos n* e *no máximo m* podem ser expressas em termos dos +quantificadores padrão e da igualdade. + +Para ilustrar a afirmação de que a lógica de primeira ordem não tem dificuldade +com combinações de quantificadores, considere a tradução da sentença a seguir. + +*Every prince sang a ballad.* ("Todo príncipe cantou uma balada.") + +$$`\forall x (\mathit{Prince}\, x \to \exists y (\mathit{Ballad}\, y \land \mathit{Sing}\, x\, y)).` + +Como vimos em {ref "english-form"}[Formas linguísticas e traduções para +lógica], a tradução não contém expressões correspondentes aos sintagmas +nominais *every prince* e *a ballad*: na lógica de primeira ordem, os +sintagmas nominais quantificados desaparecem. + +O próximo exemplo, com as duas traduções possíveis listadas abaixo dele, pode +servir para ilustrar mais alguns pontos. + +*A ballad was sung by every prince.* ("Uma balada foi cantada por todo +príncipe.") + +$$`\exists y (\mathit{Ballad}\, y \land \forall x (\mathit{Prince}\, x \to \mathit{Sing}\, x\, y))` + +$$`\forall x (\mathit{Prince}\, x \to \exists y (\mathit{Ballad}\, y \land \mathit{Sing}\, x\, y))` + +O fato de ambas as traduções serem apropriadas para essa sentença mostra que +ela é ambígua. Mostra também que a tradução para a lógica de primeira ordem +pode ser usada para desambiguar sentenças da língua natural. Em casos assim, +diz-se que as diferentes traduções exprimem diferentes leituras da sentença +original. + +A visão fregeana dos quantificadores é um enorme avanço em relação à visão +aristotélica. Restavam três áreas com espaço para melhorias: (i) encontrar +linguagens lógicas de representação que permitam preservar os sintagmas +nominais como constituintes separados, (ii) encontrar procedimentos de tradução +da língua natural para representações lógicas que não sejam ad hoc, e (iii) +encontrar maneiras de tratar quantificadores não padrão como *most*, de +preferência num arcabouço uniforme junto com os quantificadores padrão. +:::: + +## A visão relacional dos quantificadores +%%% +tag := "comp-relational" +%%% + +::::full +Na perspectiva relacional dos quantificadores, proposta pela primeira vez por +Mostowski {citep Bib.mostowski1957}[], um quantificador é visto como uma +relação binária sobre o conjunto das partes de um domínio de discurso (ou +universo) $`E` que satisfaz certos requisitos. (Você pode ler $`E` como um +mnemônico para o conjunto das entidades, por exemplo.) O conjunto das partes de +um conjunto $`E`, notação $`\mathcal{P}(E)`, é o conjunto de todos os +subconjuntos de $`E`. Uma relação binária sobre $`\mathcal{P}(E)` é um conjunto +de pares de subconjuntos de $`E`. A perspectiva relacional da quantificação +está implícita na gramática de Montague. Ela foi aplicada sistematicamente à +análise da língua natural pela primeira vez por Barwise e Cooper +{citep Bib.barwise1981}[]. Mostraremos a seguir que a visão relacional pode ser +usada para remediar os defeitos tanto da teoria aristotélica quanto da +fregeana. Ela cobre quantificadores não padrão, permite combinações de +quantificadores de complexidade arbitrária, não elimina sintaticamente os +sintagmas nominais quantificados e pode ser usada como um dos ingredientes de +um procedimento de tradução não ad hoc da língua natural para uma linguagem de +representações lógicas. + +Essa relação já apareceu, sem esse nome, em {ref "english-lf"}[FOL como +linguagem de representação]: lá a tradução de um determinante tomava dois +argumentos, a restrição e o escopo, e com eles construía uma fórmula com ∀ ou +∃, na qual o sintagma nominal desaparecia. Na visão relacional o determinante +não constrói fórmula nenhuma: ele relaciona diretamente o conjunto das +entidades que satisfazem a restrição com o conjunto das entidades que +satisfazem o escopo. + +Começaremos demonstrando que, na perspectiva relacional moderna, a sugestão de +forma enganosa desaparece. Duas sentenças de exemplo simples vão ilustrar que +uma linguagem de representação com expressões de quantificadores generalizados +(expressões que denotam relações binárias entre conjuntos) e uma notação para a +abstração lambda é eminentemente adequada para a análise composicional de +sentenças da língua natural com sintagmas nominais quantificados. Considere +primeiro a sentença a seguir. + +*Every princess laughed.* ("Toda princesa riu.") + +Essa sentença é composta de um sintagma nominal *every princess*, composto por +sua vez de um determinante *every* e de um substantivo *princess*, e de um +sintagma verbal *laughed*. O determinante *every* se traduz numa expressão +$`\mathbf{every}` que denota uma função de propriedades para uma função de +propriedades para valores de verdade. Mais precisamente, $`\mathbf{every}` +denota a função que leva uma propriedade $`P` à função característica do +conjunto de todas as propriedades que têm $`P` como subconjunto. O substantivo +*princess* se traduz em $`\lambda x \mapsto \mathit{Princess}\, x`, ou +simplesmente $`\mathit{Princess}`. O sintagma verbal *laughed* se traduz em +$`\lambda y \mapsto \mathit{Laugh}\, y`, ou simplesmente $`\mathit{Laugh}`. O +sintagma nominal *every princess* se traduz em +$`\mathbf{every}\ \mathit{Princess}` e, finalmente, a sentença inteira na +expressão $`(\mathbf{every}\ \mathit{Princess})\ \mathit{Laugh}`. Essa +expressão resulta verdadeira caso a propriedade de ser princesa esteja incluída +na propriedade de rir, e falsa caso contrário. Veja a tabela a seguir. + +:::table +header +* * expressão + * tradução + * tipo +* * *every* + * $`\mathbf{every}` + * $`(e \to t) \to ((e \to t) \to t)` +* * *princess* + * $`\mathit{Princess}` + * $`e \to t` +* * *every princess* + * $`\mathbf{every}\ \mathit{Princess}` + * $`(e \to t) \to t` +* * *laughed* + * $`\mathit{Laugh}` + * $`e \to t` +* * *every princess laughed* + * $`(\mathbf{every}\ \mathit{Princess})\ \mathit{Laugh}` + * $`t` +::: +:::: + +:::terse +Com `Bool` no lugar de $`t` e `Entity` no lugar de $`e`, o determinante é uma +função de duas propriedades: `every p q` verifica que toda entidade com `p` tem +`q`. +::: + +```lean +def every (p q : OnePlacePred) : Bool := + entities.all (fun x => !p x || q x) +``` + +```lean (name := everyPrincessLaughed) +#eval every princess laugh +``` + +::::full +Para ver como as combinações de quantificadores são tratadas de modo +composicional, considere o exemplo a seguir. + +*Every mermaid hummed a song.* ("Toda sereia cantarolou uma canção.") + +O truque é encontrar a tradução certa para o verbo transitivo. Ela acaba sendo +a expressão lambda $`\lambda X \lambda y \mapsto X\, (\lambda z \mapsto +\mathit{Hum}\, y\, z)`, onde $`X` é uma variável sobre expressões do tipo de +sintagma nominal. A tradução do verbo é do tipo certo para tomar a tradução do +sintagma nominal objeto como argumento; isso dá a primeira das traduções abaixo +para o sintagma verbal, que se reduz à segunda. Em +{ref "comp-reduction"}[Redução de expressões da lógica tipada] diremos mais +sobre esse processo de redução. + +$$`(\lambda X \lambda y \mapsto X\, (\lambda z \mapsto \mathit{Hum}\, y\, z))\, (\mathbf{a}\ \mathit{Song})` + +$$`\lambda y \mapsto (\mathbf{a}\ \mathit{Song})\, (\lambda z \mapsto \mathit{Hum}\, y\, z)` + +Aqui $`\mathbf{a}` denota a função que leva toda propriedade $`P` ao (à função +característica do) conjunto de todas as propriedades que têm interseção não +vazia com $`P`. Dando a segunda delas como argumento à expressão +$`\mathbf{every}\ \mathit{Mermaid}`, a tradução do sujeito, obtém-se a seguinte +tradução para a sentença inteira. + +$$`(\mathbf{every}\ \mathit{Mermaid})\, (\lambda y \mapsto ((\mathbf{a}\ \mathit{Song})\, (\lambda z \mapsto \mathit{Hum}\, y\, z)))` + +Podemos resumir esses passos assim: + +```display +Every mermaid hummed a song +(every Mermaid) (λy ↦ (a Song) (λz ↦ Hum y z)) +├── every mermaid +│ (every Mermaid) +└── hummed a song + λy ↦ (a Song) (λz ↦ Hum y z) + ├── hummed + │ λXλy ↦ X (λz ↦ Hum y z) + └── a song + (a Song) +``` + +Dissemos no início que vemos os quantificadores como relações binárias sobre o +conjunto das partes de algum domínio $`E`, que satisfazem certos requisitos. +Vejamos agora, então, esses requisitos. +:::: + # A linguagem da lógica tipada e sua semântica %%% tag := "comp-typed-logic" diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 9724927..8fdb2eb 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -132,8 +132,20 @@ decisions inside the chapters. ### `Composition` CSwFP/7 continues the fragment of `ModelChecking` and builds on the same -syntax and model, so it comes after `ModelChecking`. Being written; no -departures recorded yet. +syntax and model, so it comes after `ModelChecking`. Being written. + +- The chapter summary is translated as the chapter's opening, with Lean in + place of Haskell as the lambda-calculus engine of `ModelChecking`. +- In the opening of 7.2, the paragraph observing that the translation of + *Every prince sang a ballad* has no sub-expression for its noun phrases, and + the one on quantified noun phrases as "systematically misleading + expressions", are cut to a one-sentence reminder: `ModelChecking`'s + `english-form` already makes both points, at more length. +- The relational view of 7.2 gains a paragraph tying it back to `lfDET` in + `ModelChecking`, whose two arguments are the restriction and the scope of + the same relation. +- 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 + called it its *scope*. Both translate as "escopo". ## Beyond CSwFP/7 diff --git a/STYLE-WRITING.md b/STYLE-WRITING.md index e2a7326..5cfc427 100644 --- a/STYLE-WRITING.md +++ b/STYLE-WRITING.md @@ -146,6 +146,8 @@ entry until something contradicts them. What the sweep found instead: verb means *to take on*, and the false friend is the commonest translation error in this material) - "avaliar" / "rodar" (for `#eval`) +- "escopo" / "corpo" (for the second argument of a determiner; CSwFP says + *scope* in its chapter 6 and *body* in chapter 7, for the same thing) ### Code and prose From d4af6550923da2e9765cbe2eb8248d79bb567723 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 19 Oct 2026 11:57:14 -0300 Subject: [PATCH 04/20] wip(ModelChecking): add a step-by-step example from syntax to FOL The example needs ToString (Formula Term), which Logic/FOL does not have yet; the build is broken until that lands from main. --- CSwL/ModelChecking.lean | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/CSwL/ModelChecking.lean b/CSwL/ModelChecking.lean index 5ef8aa3..a31b88e 100644 --- a/CSwL/ModelChecking.lean +++ b/CSwL/ModelChecking.lean @@ -540,11 +540,7 @@ def lfDV : DV → Term → Term → Term → LF ## Variáveis novas -A tradução de um determinante toma dois argumentos de tipo `Term → LF` — formas lógicas com um buraco de termo dentro — e produz uma forma lógica. No caso dos quantificadores, o primeiro argumento é a *restrição* e o segundo o *escopo*. - -```display -lfDET : DET → (Term → LF) → (Term → LF) → LF -``` +A tradução de um determinante toma dois argumentos de tipo `Term → LF`, formas lógicas obtidas a partir de um termo, e produz uma forma lógica. No caso dos quantificadores, o primeiro argumento é a *restrição* e o segundo o *escopo*. Falaremos disso em {ref "comp-relational"}[A visão relacional dos quantificadores]. A tradução dos determinantes precisa ser feita com algum cuidado, porque envolve construir uma forma lógica em que uma variável fica ligada. Para garantir a ligação correta, temos de nos assegurar de que a variável recém-introduzida não seja capturada por um quantificador já presente na forma lógica. Mas, se refletirmos sobre como as variáveis são introduzidas, veremos que elas sempre aparecem junto de quem as liga, e que nenhuma ligação é vazia. Basta então colher os índices das ocorrências ligadas. @@ -666,13 +662,39 @@ end A tradução do adjetivo em `rcnAdj` é a conjunção: um *happy wizard* é alguém que é feliz e é mago. Isso está certo para *happy* e para *evil*, e está errado para *fake*: um *fake wizard* justamente não é um mago. Adjetivos desse tipo pedem uma semântica que a lógica de predicados não alcança, e o fragmento os traduz assim porque em Lean uma função tem de estar definida em todos os casos — a tradução existe, mas não é uma boa tradução. -Vejamos três exemplos. +Vejamos um primeiro exemplo passo-a-passo. ```lean -def lf1 : LF := - lfSent (.sent (.npDet .some .dwarf) - (.vpTrans .defeated (.npDet .some .giant))) +def s1 := + Sent.sent (.npDet .every .dwarf) + (.vpTrans .defeated (.npDet .some .giant)) + +#eval toString s1 + +open FOL in +def l0 := + let x : Variable := ⟨"x", [2]⟩ + let y : Variable := ⟨"x", [1]⟩ + let dwarf := λ x ↦ Formula.atom "dwarf" [Term.var x] + let giant := λ x ↦ Formula.atom "giant" [Term.var x] + let defeat := λ x y ↦ Formula.atom "defeat" + [(Term.var x),(Term.var y)] + Formula.forall_ x (Formula.impl + (dwarf x) + (Formula.exists_ y (Formula.conj (giant y) (defeat x y)))) + +#eval toString l0 + +open FOL in +example : lfSent s1 = l0 := by + unfold s1 l0 + simp [lfSent, lfNP, lfDET, lfCN, lfVP, lfCN, freshVar, + freshIndex, lfTV, boundIndices] +``` +Outros dois exemplos de fórmulas. + +``` def lf2 : LF := lfSent (.sent (.npDetRel .the (.rcnObj .wizard .that .dorothy .admired)) @@ -683,6 +705,7 @@ def lf3 : LF := (.rcnSubj .princess .that (.vpTrans .helped .alice))) .shuddered) + ``` From 11bfac909ba513717710c1edad2899fd818e94c8 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Tue, 20 Oct 2026 18:45:22 -0300 Subject: [PATCH 05/20] style(PL): separate Formula.impl and Formula.iff with a blank line --- CSwL/Logic/PL.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/CSwL/Logic/PL.lean b/CSwL/Logic/PL.lean index be36d6f..3b27dea 100644 --- a/CSwL/Logic/PL.lean +++ b/CSwL/Logic/PL.lean @@ -158,6 +158,7 @@ Nem todos os conectivos precisam ser definidos como "primitivos". Como vimos na ```lean def Formula.impl (f g : Formula) : Formula := .disj (.neg f) g + def Formula.iff (f g : Formula) : Formula := .conj (Formula.impl f g) (Formula.impl g f) ``` From b143f624328a4a2ea4058343db6a67bea0b84598 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Tue, 20 Oct 2026 18:45:22 -0300 Subject: [PATCH 06/20] refactor(Composition): write the chapter terse first Sections are now written terse first: AI-drafted :::terse cues and the Lean code come first, and each :::full block holds only a pending translation note until its prose is translated under review. The chapter's translated prose is cleared for consistency; the draft remains in the history. STYLE-CODE.md and STYLE-WRITING.md record the workflow. The dev note at the top of the chapter now holds the plan for the whole of CSwFP/7. In 7.2, "Every mermaid hummed a song" becomes "Every dwarf defeated a giant", which the ModelChecking model can evaluate, with `a` and `defeated` defined to compute it. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the style-guide changes; all of it was reviewed by a human author. --- CSwL/Composition.lean | 397 +++++++++++++++--------------------------- DEVIATIONS.md | 6 +- STYLE-CODE.md | 21 ++- STYLE-WRITING.md | 7 +- 4 files changed, 166 insertions(+), 265 deletions(-) diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 996f5ad..81c2ad6 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -18,163 +18,104 @@ namespace Composition open ModelChecking ``` -:::full -Em {ref "ModelChecking"}[Verificação de modelos com lógica de primeira ordem] demos uma interpretação indireta para o nosso fragmento do inglês. Traduzimos sentenças para formas lógicas e depois avaliamos essas formas lógicas em relação a um modelo. As formas lógicas eram fórmulas da lógica de predicados, construídas a partir de expressões da lógica tipada. -Usamos o Lean como implementação do cálculo lambda para esse procedimento de construção. Isso funcionou muito bem, mas tem a desvantagem de que o Lean esconde os detalhes de como as expressões da lógica tipada são simplificadas. +:::dev NOW +Plan. The headings follow CSwFP/7.1–7.7 (7.8, further reading, is omitted). +Sections are written `terse` first (see `STYLE-CODE.md`). Code comes in the +section that presents each idea, not only in 7.6: + +- 7.2: `every` and `a` (also `some`, `no`, `most`) as relations between + predicates; EXT, CONS and ISOM as `Prop`s over `Set`; the tree of numbers + and the numeric quantifiers; ex. 7.7–7.10 as monotonicity theorems; ex. + 7.11 with Mathlib's `DFA` (optional). +- 7.3: Lean's types are the typed logic (`Entity` for e, `Bool` for t); no + deep embedding, since CSwFP/8 needs intensional types. +- 7.4: `#reduce` shows the β-reductions; free variables and substitution + from CSLib's `Named.Untyped`; confluence and normal forms only cited. +- 7.5: the semantic rules as Lean functions. +- 7.6: `intSent` and friends over `ModelChecking`'s `Sent`, with `intDET` + built from the 7.2 definitions; a theorem that the direct interpretation + agrees with `checkSentence`, if it turns out feasible. +- 7.7: ex. 7.26–7.27 over `ModelChecking`'s `SentPP`; ex. 7.28. + +The chapter's key point for the cues: direct interpretation admits +quantifiers, such as *most*, that first-order logic cannot express. + +A first draft translation of the chapter opening, 7.1 and 7.2 up to the +conditions on quantifier relations is in commits `76821ee` and `95047b3`. +::: -Neste capítulo, vamos demonstrar que a composição do significado pode ser realizada sem uma linguagem de formas lógicas como nível intermediário de representação. Daremos instruções diretas para ligar expressões da língua natural ao "mundo" fora da língua (representado por um modelo). Mostraremos como modelos da lógica de predicados podem ser estendidos a modelos da lógica tipada, e como a lógica tipada fornece representações de significado apropriadas para os itens lexicais de fragmentos de língua natural e oferece os meios para construir significados de modo composicional. Mas antes de nos dedicarmos a isso, precisamos nos concentrar num ingrediente-chave da semântica da língua natural: os quantificadores. +:::terse +- Em {ref "ModelChecking"}[Verificação de modelos com lógica de primeira + ordem] o caminho era indireto: sentença, depois fórmula, depois avaliação no + modelo. +- Agora o caminho é direto: cada expressão da língua é ligada ao modelo, sem + fórmula intermediária. +- Os modelos da lógica de predicados se estendem à lógica tipada, que dá os + significados das palavras e o modo de compô-los. +- O ganho central: quantificadores como *most*, que a lógica de primeira ordem + não exprime, passam a ter interpretação direta. ::: -:::dev NOW -Skeleton: the headings follow CSwFP/7.1–7.7 (7.8, further reading, is -omitted). Each section is to be translated into `:::full` blocks, with a -`:::terse` cue before each `lean` block (see `STYLE-CODE.md`). +::::full +:::dev BeforeNextRelease +TODO: translate the CSwFP/7 summary, with Lean in place of Haskell as the +lambda-calculus engine of `ModelChecking`. ::: +:::: # As regras do jogo %%% tag := "comp-rules" %%% -:::suppressPreviousHeaderWhenTerse +:::terse +- Traduzir sentenças para uma lógica pressupõe entender as fórmulas e as + sentenças. Por isso a tradução não explica o significado das sentenças. +- O procedimento de {ref "english-lf"}[FOL como linguagem de representação] + explica: o significado do todo é construído a partir dos significados das + partes. Os significados das palavras vêm do modelo. +- Princípio da Composicionalidade, já visto em {ref "IntroCS"}[O estudo formal + da língua natural]: o significado de uma expressão é uma função dos + significados de seus componentes imediatos e do modo de composição. +- Frege, depois Montague. Em Montague, outro ingrediente-chave: os + quantificadores. ::: -:::full -Pedir a alguém que traduza para uma lógica as sentenças de um fragmento de uma linguagem natural como o inglês, definido por um conjunto de regras gramaticais, pressupõe duas coisas: (i) que essa pessoa compreenda o significado das fórmulas da linguagem lógica, e (ii) que compreenda o significado das sentenças do fragmento do inglês. O primeiro tipo de conhecimento pode ser formulado de modo totalmente explícito; essa é justamente a função das definições semânticas de verdade das linguagens lógicas. Aliás, os exercícios de tradução desse tipo, comuns nos livros de lógica, servem para mostrar ao leitor o poder expressivo da linguagem de representação, ao pedir que ele exprima nesse novo meio uma mensagem que (intuitivamente) já compreende bem. Como essas traduções pressupõem que a -mensagem original já foi compreendida, elas não podem contar como uma explicação do conceito de significado para a língua natural. - -Como vimos em {ref "english-lf"}[FOL como linguagem de representação], é -possível tornar plenamente explícito o conhecimento do significado de um -fragmento de língua natural. O que demos lá é um procedimento de tradução da -língua natural para a lógica de predicados que pode contar como uma explicação -do conceito de significado para a língua natural. O procedimento não pressupõe -o conhecimento do significado de sentenças completas da língua natural. Em vez -disso, ele especifica como os significados das sentenças são derivados dos -significados de blocos de construção menores. Os significados de expressões -complexas são construídos de maneira sistemática a partir dos significados dos -menores blocos de construção que ocorrem nessas expressões. O significado -desses menores blocos de construção é tomado como dado. Supomos que eles são -dados por instruções que ligam palavras individuais à realidade fora da -língua. No nosso exemplo, essas ligações são feitas pelas instruções de -interpretação dos símbolos de relação e de função num modelo da lógica de -predicados. A semântica computacional tem pouco ou nada a dizer sobre a -interpretação dos átomos semânticos. Tem bastante a dizer, no entanto, sobre o -processo de compor significados complexos de maneira sistemática a partir dos -significados dos componentes. A intuição de que isso é sempre possível pode ser -enunciada de modo um pouco mais preciso; ela se chama Princípio da -Composicionalidade, que já encontramos em {ref "IntroCS"}[O estudo formal da -língua natural]: - -> O significado de uma expressão é uma função dos significados de seus -> componentes sintáticos imediatos e de seu modo sintático de composição. - -O princípio da composicionalidade está implícito na obra de Frege sobre a -filosofia da linguagem, e foi tornado plenamente explícito na abordagem de -Richard Montague à semântica da língua natural. Outro elemento-chave na -semântica ao estilo de Montague é o tratamento dos quantificadores. +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.1. ::: +:::: # Quantificação %%% tag := "comp-quantification" %%% -::::full -Um objetivo importante da semântica computacional é dar conta do processo de tirar inferências na língua natural. Um papel-chave nesse processo cabe aos quantificadores, e por isso a quantificação é um tópico de interesse central na semântica computacional. O primeiro tratamento sistemático da quantificação é o de Aristóteles; veja {ref "InfEngine"}[Um motor de inferência]. Por impressionante que seja, a teoria aristotélica da quantificação tem dois defeitos lógicos: - -1. Combinações de quantificadores não são tratadas; só se permite um - quantificador por sentença. -2. Quantificadores como *most*, *half of*, *at least five*, não são cobertos. - -Um defeito adicional, menor, é a suposição da pressuposição existencial. No -raciocínio matemático, e às vezes também no raciocínio cotidiano, queremos -poder afirmar enunciados universalmente quantificados sem o incômodo de antes -ter de fornecer provas de existência. - -O primeiro desses defeitos foi removido por Frege. A teoria da quantificação de -Frege é basicamente o que hoje chamamos de lógica de predicados. Ela se baseia -na introdução de variáveis individuais ligadas pelos quantificadores ∀ ("para -todo") e ∃ ("existe"). Os quantificadores, com suas variáveis associadas, podem -se combinar com fórmulas arbitrariamente complexas da lógica de predicados para -formar novas fórmulas da lógica de predicados, de modo que uma fórmula pode -conter um número arbitrário de quantificadores. - -Os quantificadores ∀ e ∃ são chamados de quantificadores padrão. Esses dois -quantificadores são interdefiníveis com a ajuda da negação: *Algo fede* -significa o mesmo que *Não é o caso que, para todo x, x não fede*, e *Tudo está -bem* significa o mesmo que *Não é o caso que existe uma coisa x com a -propriedade de que x não está bem*. Mais formalmente: $`\exists x\, P x` é -verdadeira se e somente se $`\neg \forall x\, \neg P x` é verdadeira, e -$`\forall x\, P x` é verdadeira se e somente se $`\neg \exists x\, \neg P x` é -verdadeira. - -Se convenientemente esquecermos as pressuposições existenciais, os -quantificadores aristotélicos do quadrado das oposições (veja -{ref "InfEngine"}[Um motor de inferência]) podem ser expressos em termos dos -quantificadores padrão de Frege da seguinte maneira (com ⇝ para "traduz-se -como"): - -:::table -* * Todo A é B - * $`\forall x (A x \to B x)` -* * Algum A é B - * $`\exists x (A x \land B x)` -* * Nenhum A é B - * $`\forall x (A x \to \neg B x)` -* * Nem todo A é B - * $`\neg \forall x (A x \to B x)` +:::terse +- Aristóteles ({ref "InfEngine"}[Um motor de inferência]): um quantificador + por sentença, nada de *most* ou *at least five*, e a pressuposição + existencial. +- Frege: ∀ e ∃ com variáveis, em combinações arbitrárias. Os dois são + interdefiníveis com a negação. +- O quadrado das oposições em primeira ordem; *pelo menos dois A são B* com a + igualdade. +- *Every prince sang a ballad* ("Todo príncipe cantou uma balada"): na + fórmula, os sintagmas nominais desaparecem. +- *A ballad was sung by every prince* ("Uma balada foi cantada por todo + príncipe"): duas fórmulas, duas leituras. A lógica de primeira ordem + desambigua. +- O que falta: manter os sintagmas nominais como constituintes, uma tradução + que não seja ad hoc, e quantificadores não padrão como *most*. ::: -Algo a notar é que diferentes maneiras de exprimir um quantificador -aristotélico na lógica de Frege podem ser equivalentes. Outra tradução possível -para *Nenhum A é B* é $`\neg \exists x (A x \land B x)`. Não há o que escolher -entre as duas traduções, porque em toda situação em que a primeira é verdadeira -a segunda também é, e vice-versa. - -Usando os quantificadores padrão e a igualdade, também é possível exprimir -restrições numéricas como *Pelo menos dois A são B*: - -$$`\exists x \exists y (x \neq y \land A x \land A y \land B x \land B y).` - -Não é difícil ver que todas as disjunções e conjunções de quantificadores das -formas *pelo menos n* e *no máximo m* podem ser expressas em termos dos -quantificadores padrão e da igualdade. - -Para ilustrar a afirmação de que a lógica de primeira ordem não tem dificuldade -com combinações de quantificadores, considere a tradução da sentença a seguir. - -*Every prince sang a ballad.* ("Todo príncipe cantou uma balada.") - -$$`\forall x (\mathit{Prince}\, x \to \exists y (\mathit{Ballad}\, y \land \mathit{Sing}\, x\, y)).` - -Como vimos em {ref "english-form"}[Formas linguísticas e traduções para -lógica], a tradução não contém expressões correspondentes aos sintagmas -nominais *every prince* e *a ballad*: na lógica de primeira ordem, os -sintagmas nominais quantificados desaparecem. - -O próximo exemplo, com as duas traduções possíveis listadas abaixo dele, pode -servir para ilustrar mais alguns pontos. - -*A ballad was sung by every prince.* ("Uma balada foi cantada por todo -príncipe.") - -$$`\exists y (\mathit{Ballad}\, y \land \forall x (\mathit{Prince}\, x \to \mathit{Sing}\, x\, y))` - -$$`\forall x (\mathit{Prince}\, x \to \exists y (\mathit{Ballad}\, y \land \mathit{Sing}\, x\, y))` - -O fato de ambas as traduções serem apropriadas para essa sentença mostra que -ela é ambígua. Mostra também que a tradução para a lógica de primeira ordem -pode ser usada para desambiguar sentenças da língua natural. Em casos assim, -diz-se que as diferentes traduções exprimem diferentes leituras da sentença -original. - -A visão fregeana dos quantificadores é um enorme avanço em relação à visão -aristotélica. Restavam três áreas com espaço para melhorias: (i) encontrar -linguagens lógicas de representação que permitam preservar os sintagmas -nominais como constituintes separados, (ii) encontrar procedimentos de tradução -da língua natural para representações lógicas que não sejam ad hoc, e (iii) -encontrar maneiras de tratar quantificadores não padrão como *most*, de -preferência num arcabouço uniforme junto com os quantificadores padrão. +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from the start to "…in a uniform framework with +standard quantifiers." The two paragraphs on the noun phrases of (7.1) and on +"systematically misleading expressions" are cut to a reminder of +`english-form` (see `DEVIATIONS.md`). +::: :::: ## A visão relacional dos quantificadores @@ -182,86 +123,28 @@ preferência num arcabouço uniforme junto com os quantificadores padrão. tag := "comp-relational" %%% -::::full -Na perspectiva relacional dos quantificadores, proposta pela primeira vez por -Mostowski {citep Bib.mostowski1957}[], um quantificador é visto como uma -relação binária sobre o conjunto das partes de um domínio de discurso (ou -universo) $`E` que satisfaz certos requisitos. (Você pode ler $`E` como um -mnemônico para o conjunto das entidades, por exemplo.) O conjunto das partes de -um conjunto $`E`, notação $`\mathcal{P}(E)`, é o conjunto de todos os -subconjuntos de $`E`. Uma relação binária sobre $`\mathcal{P}(E)` é um conjunto -de pares de subconjuntos de $`E`. A perspectiva relacional da quantificação -está implícita na gramática de Montague. Ela foi aplicada sistematicamente à -análise da língua natural pela primeira vez por Barwise e Cooper -{citep Bib.barwise1981}[]. Mostraremos a seguir que a visão relacional pode ser -usada para remediar os defeitos tanto da teoria aristotélica quanto da -fregeana. Ela cobre quantificadores não padrão, permite combinações de -quantificadores de complexidade arbitrária, não elimina sintaticamente os -sintagmas nominais quantificados e pode ser usada como um dos ingredientes de -um procedimento de tradução não ad hoc da língua natural para uma linguagem de -representações lógicas. - -Essa relação já apareceu, sem esse nome, em {ref "english-lf"}[FOL como -linguagem de representação]: lá a tradução de um determinante tomava dois -argumentos, a restrição e o escopo, e com eles construía uma fórmula com ∀ ou -∃, na qual o sintagma nominal desaparecia. Na visão relacional o determinante -não constrói fórmula nenhuma: ele relaciona diretamente o conjunto das -entidades que satisfazem a restrição com o conjunto das entidades que -satisfazem o escopo. - -Começaremos demonstrando que, na perspectiva relacional moderna, a sugestão de -forma enganosa desaparece. Duas sentenças de exemplo simples vão ilustrar que -uma linguagem de representação com expressões de quantificadores generalizados -(expressões que denotam relações binárias entre conjuntos) e uma notação para a -abstração lambda é eminentemente adequada para a análise composicional de -sentenças da língua natural com sintagmas nominais quantificados. Considere -primeiro a sentença a seguir. - -*Every princess laughed.* ("Toda princesa riu.") - -Essa sentença é composta de um sintagma nominal *every princess*, composto por -sua vez de um determinante *every* e de um substantivo *princess*, e de um -sintagma verbal *laughed*. O determinante *every* se traduz numa expressão -$`\mathbf{every}` que denota uma função de propriedades para uma função de -propriedades para valores de verdade. Mais precisamente, $`\mathbf{every}` -denota a função que leva uma propriedade $`P` à função característica do -conjunto de todas as propriedades que têm $`P` como subconjunto. O substantivo -*princess* se traduz em $`\lambda x \mapsto \mathit{Princess}\, x`, ou -simplesmente $`\mathit{Princess}`. O sintagma verbal *laughed* se traduz em -$`\lambda y \mapsto \mathit{Laugh}\, y`, ou simplesmente $`\mathit{Laugh}`. O -sintagma nominal *every princess* se traduz em -$`\mathbf{every}\ \mathit{Princess}` e, finalmente, a sentença inteira na -expressão $`(\mathbf{every}\ \mathit{Princess})\ \mathit{Laugh}`. Essa -expressão resulta verdadeira caso a propriedade de ser princesa esteja incluída -na propriedade de rir, e falsa caso contrário. Veja a tabela a seguir. - -:::table +header -* * expressão - * tradução - * tipo -* * *every* - * $`\mathbf{every}` - * $`(e \to t) \to ((e \to t) \to t)` -* * *princess* - * $`\mathit{Princess}` - * $`e \to t` -* * *every princess* - * $`\mathbf{every}\ \mathit{Princess}` - * $`(e \to t) \to t` -* * *laughed* - * $`\mathit{Laugh}` - * $`e \to t` -* * *every princess laughed* - * $`(\mathbf{every}\ \mathit{Princess})\ \mathit{Laugh}` - * $`t` +:::terse +- Um quantificador é uma relação binária entre subconjuntos de um domínio + $`E` (Mostowski {citep Bib.mostowski1957}[]; Barwise e Cooper + {citep Bib.barwise1981}[]). +- A relação já apareceu em {ref "english-lf"}[FOL como linguagem de + representação]: os dois argumentos de `lfDET` são a restrição e o escopo. + Lá, porém, o determinante construía uma fórmula. Aqui ele relaciona + diretamente dois conjuntos de entidades. +- *Every princess laughed* ("Toda princesa riu"): o determinante é uma função + de duas propriedades, `every : OnePlacePred → OnePlacePred → Bool`. + `every p q` verifica que toda entidade com `p` tem `q`. +- Os tipos acompanham a composição: `every princess : OnePlacePred → Bool`, + e a sentença `every princess laugh : Bool`. ::: -:::: -:::terse -Com `Bool` no lugar de $`t` e `Entity` no lugar de $`e`, o determinante é uma -função de duas propriedades: `every p q` verifica que toda entidade com `p` tem -`q`. +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "The relational view of quantifiers", from the +start to the table after (7.3). Decide whether the table keeps the types +e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. ::: +:::: ```lean def every (p q : OnePlacePred) : Bool := @@ -272,58 +155,60 @@ def every (p q : OnePlacePred) : Bool := #eval every princess laugh ``` -::::full -Para ver como as combinações de quantificadores são tratadas de modo -composicional, considere o exemplo a seguir. - -*Every mermaid hummed a song.* ("Toda sereia cantarolou uma canção.") - -O truque é encontrar a tradução certa para o verbo transitivo. Ela acaba sendo -a expressão lambda $`\lambda X \lambda y \mapsto X\, (\lambda z \mapsto -\mathit{Hum}\, y\, z)`, onde $`X` é uma variável sobre expressões do tipo de -sintagma nominal. A tradução do verbo é do tipo certo para tomar a tradução do -sintagma nominal objeto como argumento; isso dá a primeira das traduções abaixo -para o sintagma verbal, que se reduz à segunda. Em -{ref "comp-reduction"}[Redução de expressões da lógica tipada] diremos mais -sobre esse processo de redução. - -$$`(\lambda X \lambda y \mapsto X\, (\lambda z \mapsto \mathit{Hum}\, y\, z))\, (\mathbf{a}\ \mathit{Song})` - -$$`\lambda y \mapsto (\mathbf{a}\ \mathit{Song})\, (\lambda z \mapsto \mathit{Hum}\, y\, z)` - -Aqui $`\mathbf{a}` denota a função que leva toda propriedade $`P` ao (à função -característica do) conjunto de todas as propriedades que têm interseção não -vazia com $`P`. Dando a segunda delas como argumento à expressão -$`\mathbf{every}\ \mathit{Mermaid}`, a tradução do sujeito, obtém-se a seguinte -tradução para a sentença inteira. - -$$`(\mathbf{every}\ \mathit{Mermaid})\, (\lambda y \mapsto ((\mathbf{a}\ \mathit{Song})\, (\lambda z \mapsto \mathit{Hum}\, y\, z)))` - -Podemos resumir esses passos assim: - -```display -Every mermaid hummed a song -(every Mermaid) (λy ↦ (a Song) (λz ↦ Hum y z)) -├── every mermaid -│ (every Mermaid) -└── hummed a song - λy ↦ (a Song) (λz ↦ Hum y z) - ├── hummed - │ λXλy ↦ X (λz ↦ Hum y z) - └── a song - (a Song) +```leanOutput everyPrincessLaughed +true ``` -Dissemos no início que vemos os quantificadores como relações binárias sobre o -conjunto das partes de algum domínio $`E`, que satisfazem certos requisitos. -Vejamos agora, então, esses requisitos. +:::terse +- *Every dwarf defeated a giant* ("Todo anão derrotou um gigante"): uma + sentença com dois quantificadores. +- `a p q` verifica que alguma entidade tem `p` e `q`: a interseção dos dois + conjuntos não é vazia. +- Um sintagma nominal como `a giant` tem tipo `OnePlacePred → Bool`: espera a + propriedade do escopo. O verbo transitivo `defeated` toma esse sintagma como + argumento e devolve uma propriedade do sujeito. +- A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: + o `#eval` consulta o modelo diretamente. +- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura + fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To see how quantifier combinations…" to the +summary tree, with *Every dwarf defeated a giant* in place of (7.4) (see +`DEVIATIONS.md`). +::: :::: +```lean +def a (p q : OnePlacePred) : Bool := + entities.any (fun x => p x && q x) + +def defeated (X : OnePlacePred → Bool) : OnePlacePred := + fun y => X (fun z => defeat y z) +``` + +```lean (name := everyDwarfDefeatedAGiant) +#eval every dwarf (defeated (a giant)) +``` + +```leanOutput everyDwarfDefeatedAGiant +true +``` + # A linguagem da lógica tipada e sua semântica %%% tag := "comp-typed-logic" %%% +:::terse +- A linguagem de tipos da lógica tipada: $`e` para entidades, $`t` para + valores de verdade, e $`\tau_1 \to \tau_2` para funções. +- No nosso modelo, $`e` é `Entity` e $`t` é `Bool`; os tipos de + {ref "comp-relational"}[A visão relacional dos quantificadores] são esses. +::: + # Redução de expressões da lógica tipada %%% tag := "comp-reduction" diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 8fdb2eb..c0071fc 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -141,9 +141,9 @@ syntax and model, so it comes after `ModelChecking`. Being written. the one on quantified noun phrases as "systematically misleading expressions", are cut to a one-sentence reminder: `ModelChecking`'s `english-form` already makes both points, at more length. -- The relational view of 7.2 gains a paragraph tying it back to `lfDET` in - `ModelChecking`, whose two arguments are the restriction and the scope of - the same relation. +- Example (7.4), *Every mermaid hummed a song*, becomes *Every dwarf defeated + a giant*: mermaids, songs and humming are not in `ModelChecking`'s fragment + or model, and the new sentence can be evaluated there with `#eval`. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". diff --git a/STYLE-CODE.md b/STYLE-CODE.md index ac65a63..c8b9cc7 100644 --- a/STYLE-CODE.md +++ b/STYLE-CODE.md @@ -268,12 +268,27 @@ Prose can be routed to a variant: The standard pattern, as in sf-in-lean, is a `:::terse` cue followed by the `:::full` prose it stands in for, followed by the shared ```` ```lean ```` block. -The cue is one or two sentences for the instructor at the keyboard, about what -the Lean code does and how; the `:::full` block holds the narrative a reader -needs on their own, including any prose translated from CSwFP. Code, exercises, +The cue is for the instructor at the keyboard: a few short points on what the +section is about, what matters most in it, and what to explain about the Lean +code that follows. The `:::full` block holds the narrative a reader needs on +their own, including any prose translated from CSwFP. Code, exercises, quizzes and `:::dev` notes stay outside both, so every variant has them. Prose that serves both audiences equally can stay outside both too. +A section is written **`terse` first**. The cues and the code come first; the +`:::full` prose follows later, step by step, under human review. Until then the +`:::full` block holds only a pending note, so that the gap shows in every +variant but `student`: + +``` +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Abstracting from the domain…" to "…the +logical representation of quantifiers." +::: +:::: +``` + `Composition` is the first chapter written this way. The chapters before it have no `:::terse` cues yet, so their `terse` variant carries the full prose; each gets its cues when it is next revised. diff --git a/STYLE-WRITING.md b/STYLE-WRITING.md index 5cfc427..78e426c 100644 --- a/STYLE-WRITING.md +++ b/STYLE-WRITING.md @@ -124,9 +124,10 @@ language allows, produced as a draft for a human to revise. Prose is never invented, expanded, or restructured on the AI's initiative — see `CLAUDE.md`. A `:::terse` cue (see `STYLE-CODE.md`) is the one exception: it is new text by -nature, not a translation, since CSwFP has no lecture cut. AI may draft a cue, -one block at a time, and a human approves or rewrites each one. The `:::full` -prose next to it keeps the rule above. +nature, not a translation, since CSwFP has no lecture cut. AI drafts the cues +of a section, together with its code, and a human approves or rewrites each +one. The `:::full` prose next to it keeps the rule above, and is translated +afterwards, a step at a time, from the pending notes the cues leave behind. The failure mode this section guards against is the systematic one: a translation that is fluent, plausible, and consistently wrong about a term. From 2525872de42278e337219401233ad6a395fc9486 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Wed, 21 Oct 2026 00:18:10 -0300 Subject: [PATCH 07/20] feat(Composition): add quantifier conditions, numerical trees and logical representations Continue CSwFP/7.2 in terse-first form: - Conditions on quantifier relations: namespace GQ with Det, all, some, no, only, the conditions Ext, Cons and Isom, and exercises no-cons, only-not-cons, many-not-ext, the-quant and poss-not-isom. Terse cues distinguish the syntactic category DET from GQ.Det and explain in which sense the articles a and the are quantifiers. - Numerical trees: row, showTree and Figure 7.6 computed, with exercises tree-of-numbers (7.1) and gen-tree (7.3). - Logical representations for quantifiers: NumQuant, allNum, atLeastNum, notNum, andNum, orNum, with exercise tree-patterns (7.2). CSwFP.yaml maps the new exercises, DEVIATIONS.md records the finite tree of numbers, the argument order of Quant and the computed Figure 7.6, and STYLE-CODE.md adds the Composition row to the ledger. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the exercises; all of it was reviewed by a human author. --- CSwFP.yaml | 16 +- CSwL/Composition.lean | 908 ++++++++++++++++++++++++++++++++++++++++-- DEVIATIONS.md | 7 + STYLE-CODE.md | 1 + 4 files changed, 904 insertions(+), 28 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index dbf9945..12aa1c8 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -130,9 +130,9 @@ exercises: 6.7 (p. 147): check-sentence CSwFP/7: - 7.1 (p. 158): TODO - 7.2 (p. 158): TODO - 7.3 (p. 158): TODO + 7.1 (p. 158): tree-of-numbers + 7.2 (p. 158): tree-patterns + 7.3 (p. 158): gen-tree 7.4 (p. 161): TODO 7.5 (p. 161): TODO 7.6 (p. 161): TODO @@ -190,12 +190,22 @@ original: Morphology/Phonemes.lean: [append-suffix-text] Morphology/SwedishPlural.lean: [swedish-plural] InfEngine.lean: [inconsistent-kb, ferio] + Composition.lean: + - at-most-two # from the prose on "At least two A are B" in 7.2 + - at-least-n # from the prose on "at least n" and "at most m" in 7.2 + - subalternation # from the prose on existential presuppositions in 7.2 + - no-cons # from the prose on CONS in 7.2 + - only-not-cons # from the prose on (7.8), "Only dwarfs sing during work" + - many-not-ext # from the prose on EXT in 7.2, "many in the sense of relatively many" + - the-quant # from the prose on ISOM in 7.2 and the Russellian `the` of 7.5 + - poss-not-isom # from the prose on ISOM in 7.2: EXT and CONS do not imply ISOM depends: bangu-proof: bangu-form pl-consequence: implies-from-list ex-fol-entails: ex-fol-implies-from-list help-defeat: check-sentence + gen-tree: tree-of-numbers sections: diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 81c2ad6..2f4aaee 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -1,6 +1,8 @@ import CSwLMeta import Bib import CSwL.ModelChecking +import Mathlib.Data.Set.Function +import Mathlib.Data.Set.Card open Verso.Genre Manual open CSwLMeta @@ -74,6 +76,8 @@ tag := "comp-rules" - O procedimento de {ref "english-lf"}[FOL como linguagem de representação] explica: o significado do todo é construído a partir dos significados das partes. Os significados das palavras vêm do modelo. +- A semântica computacional tem pouco ou nada a dizer sobre a interpretação dos + átomos semânticos (a interpretação dos átomos no modelo de primeira ordem); tem muito a dizer sobre o processo de compor sistematicamente significados complexos a partir dos significados dos componentes. - Princípio da Composicionalidade, já visto em {ref "IntroCS"}[O estudo formal da língua natural]: o significado de uma expressão é uma função dos significados de seus componentes imediatos e do modo de composição. @@ -93,26 +97,173 @@ tag := "comp-quantification" %%% :::terse -- Aristóteles ({ref "InfEngine"}[Um motor de inferência]): um quantificador - por sentença, nada de *most* ou *at least five*, e a pressuposição - existencial. -- Frege: ∀ e ∃ com variáveis, em combinações arbitrárias. Os dois são - interdefiníveis com a negação. -- O quadrado das oposições em primeira ordem; *pelo menos dois A são B* com a +- O objetivo da seção é comparar a visão aristotélica e a visão fregeana dos + quantificadores. A de Frege é muito superior, mas deixa três problemas em + aberto, e o resto do capítulo trata deles. +- A teoria da quantificação de Aristóteles, que vimos em + {ref "InfEngine"}[Um motor de inferência], tem dois defeitos lógicos e uma + falha menor: + 1. ela não trata combinações de quantificadores, pois só admite um + quantificador por sentença; + 2. ela não cobre quantificadores "não padrão", como *most*, *half of* e + *at least five*; + 3. ela supõe a pressuposição existencial. +- Frege remove o primeiro defeito. Os quantificadores ∀ e ∃ ligam variáveis + e se combinam com fórmulas arbitrárias, de modo que uma fórmula pode ter + quantos quantificadores quiser. O segundo defeito continua. +- ∀ e ∃ se definem um pelo outro com a negação: $`\exists x P x` vale se e + somente se $`\neg \forall x \neg P x` vale. +- Os quatro quantificadores do quadrado das oposições se escrevem com ∀ e ∃: + "todo A é B" é $`\forall x (Ax \to Bx)`, "algum A é B" é + $`\exists x (Ax \land Bx)`, e assim por diante. +- Por que "esquecer" a pressuposição existencial: a questão não é o domínio + (em FOL ele é não vazio), mas a extensão de `A`. Se nenhum elemento satisfaz + `A`, então $`\forall x (Ax \to Bx)` é vacuamente verdadeira e + $`\exists x (Ax \land Bx)` é falsa. +- Com `A` vazio, só as diagonais (contraditórias) sobrevivem. Caem as + contrárias ("todo A é B" e "nenhum A é B" ambas verdadeiras), as + subcontrárias e a subalternação. Ex.: *Darapti* não vale em FOL. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from the start to "…in terms of standard +quantifiers and equality." +::: +:::: + +:::terse +- Com a igualdade, a lógica de primeira ordem exprime também quantificadores + numéricos. "Pelo menos dois A são B" é + $`\exists x \exists y (x \neq y \land Ax \land Ay \land Bx \land By)`. +- A fórmula de "pelo menos dois A são B" em Lean é um valor do tipo `LF`, o + mesmo de {ref "ModelChecking"}[Model checking]. Os predicados `a` e `b` são + parâmetros, e a função devolve uma fórmula para cada par de predicados. +- `.neg (.eq tx ty)` é $`x \neq y`. A igualdade já é um construtor de + `Formula` desde {ref "FOL"}[FOL]. +- No modelo do capítulo há três pessoas que riem e só duas meninas que riem. +::: + +```lean +open FOL in +def atLeastTwo (a b : String) : LF := + .exists_ x (.exists_ y (.conjs + [.neg (.eq tx ty), .atom a [tx], .atom a [ty], + .atom b [tx], .atom b [ty]])) + +def check (f : LF) : Bool := + f.eval entities intFairy ass0 (FOL.liftAssign fintFairy) + +#eval check (atLeastTwo "person" "laugh") +``` + +::::exercise (rating := 1) (name := "at-most-two") + +Seguindo o modelo de {name}`atLeastTwo`, defina a fórmula de "no máximo dois +A são B". Dica: se três elementos são A e B, dois deles são iguais. + +```lean +open FOL in +def atMostTwo (a b : String) : LF := + solution!( + .forall_ x (.forall_ y (.forall_ z (.impl + (.conjs [.atom a [tx], .atom a [ty], .atom a [tz], + .atom b [tx], .atom b [ty], .atom b [tz]]) + (.disjs [.eq tx ty, .eq tx tz, .eq ty tz]))))) + +theorem atMostTwo_girl : + check (atMostTwo "girl" "laugh") = true := + solution!(by native_decide) + +theorem atMostTwo_person : + check (atMostTwo "person" "laugh") = false := + solution!(by native_decide) +``` + +:::: + +:::terse +- {name}`atLeastTwo` e `atMostTwo` são funções que *geram* fórmulas. A + função é escrita em Lean, a metalinguagem; o que ela devolve é uma fórmula + de FOL, a linguagem objeto. +- Todas as disjunções e conjunções de quantificadores das formas *pelo menos + n* e *no máximo m* podem ser expressas com os quantificadores padrão e a igualdade. +- O que a lógica de primeira ordem consegue contar: só números fixos e + finitos, com uma fórmula diferente para cada `n`. +- Não existe uma única fórmula que expresse "pelo menos n" para `n` + arbitrário. Cada fórmula tem um número fixo de quantificadores, e isso + limita até onde ela consegue contar. +- Em Lean, porém, podemos escrever uma única *função* `atLeast n` que, para + cada `n`, gera a fórmula correspondente. As `n` variáveis distintas saem do + índice de `Variable`: `⟨"x", [i]⟩` é a variável `xi`. +::: + +::::exercise (rating := 3) (name := "at-least-n") + +Defina `atLeast n a b`, a fórmula de "pelo menos n A são B", e +`atMost n a b`, a de "no máximo n A são B". Dica: "no máximo n" é a negação +de "pelo menos n + 1". Para `atLeast`, uma função auxiliar recursiva pode +carregar a lista dos termos já quantificados, para exigir que cada nova +variável seja diferente de todos eles. + +```lean +open FOL in +def atLeastFrom (a b : String) (n : Nat) (ts : List Term) : + LF := + solution!( + match n with + | 0 => .top + | n + 1 => + let v : Variable := ⟨"x", [n]⟩ + let t : Term := .var v + .exists_ v (.conjs ([.atom a [t], .atom b [t]] ++ + ts.map (fun s => .neg (.eq s t)) ++ + [atLeastFrom a b n (t :: ts)]))) + +def atLeast (n : Nat) (a b : String) : LF := + solution!(atLeastFrom a b n []) + +def atMost (n : Nat) (a b : String) : LF := + solution!(.neg (atLeast (n + 1) a b)) + +theorem atLeast_person : + check (atLeast 3 "person" "laugh") = true ∧ + check (atLeast 4 "person" "laugh") = false := + solution!(by native_decide) + +theorem atMost_girl : + check (atMost 2 "girl" "laugh") = true ∧ + check (atMost 1 "girl" "laugh") = false := + solution!(by native_decide) +``` + +:::: + +:::terse - *Every prince sang a ballad* ("Todo príncipe cantou uma balada"): na fórmula, os sintagmas nominais desaparecem. - *A ballad was sung by every prince* ("Uma balada foi cantada por todo príncipe"): duas fórmulas, duas leituras. A lógica de primeira ordem desambigua. -- O que falta: manter os sintagmas nominais como constituintes, uma tradução - que não seja ad hoc, e quantificadores não padrão como *most*. +- A visão fregeana deixa três problemas em aberto: + 1. encontrar uma linguagem de representação que preserve os sintagmas + nominais como constituintes; + 2. encontrar um procedimento de tradução da língua natural que não seja + ad hoc; + 3. tratar quantificadores não padrão como *most*, de preferência junto com + os quantificadores padrão. +- O resto desta seção, a partir da visão relacional, responde aos problemas + 1 e 3: *every dwarf* vira uma função, e *most* é uma relação entre + conjuntos como *every*. A lógica tipada e o cálculo lambda, nas próximas + seções, respondem ao problema 2. ::: ::::full :::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from the start to "…in a uniform framework with -standard quantifiers." The two paragraphs on the noun phrases of (7.1) and on +TODO: translate CSwFP/7.2, from "To illustrate the claim that first-order +logic has no difficulty…" to "…in a uniform framework with standard +quantifiers." The two paragraphs on the noun phrases of (7.1) and on "systematically misleading expressions" are cut to a reminder of `english-form` (see `DEVIATIONS.md`). ::: @@ -124,6 +275,10 @@ tag := "comp-relational" %%% :::terse +- O objetivo da subseção é apresentar a visão relacional dos quantificadores + e mostrar, em dois exemplos, que com ela os sintagmas nominais continuam + sendo constituintes, inclusive quando há dois quantificadores na mesma + sentença. - Um quantificador é uma relação binária entre subconjuntos de um domínio $`E` (Mostowski {citep Bib.mostowski1957}[]; Barwise e Cooper {citep Bib.barwise1981}[]). @@ -149,14 +304,28 @@ e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. ```lean def every (p q : OnePlacePred) : Bool := entities.all (fun x => !p x || q x) -``` -```lean (name := everyPrincessLaughed) -#eval every princess laugh +#eval (every princess) laugh ``` -```leanOutput everyPrincessLaughed -true +:::terse +- Lembre de {ref "Sets"}[Conjuntos e Relações]: a função característica de + um conjunto responde, para cada elemento, se ele pertence ao conjunto. + `princess : Entity → Bool` é a função característica do conjunto das + princesas. +- `every princess` aplica a mesma ideia um nível acima. Ele tem tipo + `OnePlacePred → Bool`, logo é a função característica de um conjunto de + *propriedades*: as que toda princesa tem, isto é, as `q` com + $`\textit{princess} \subseteq q`. +- O `#eval` a seguir mostra esse conjunto, restrito a três propriedades. O + resultado é `["laugh"]`: das três propriedades, só "rir" é de toda + princesa. +::: + +```lean (name := everyPrincessEval) +#eval [("laugh", laugh), ("cheer", cheer), + ("shudder", shudder)] + |>.filter (fun (_, q) => every princess q) |>.map (·.1) ``` :::terse @@ -164,13 +333,6 @@ true sentença com dois quantificadores. - `a p q` verifica que alguma entidade tem `p` e `q`: a interseção dos dois conjuntos não é vazia. -- Um sintagma nominal como `a giant` tem tipo `OnePlacePred → Bool`: espera a - propriedade do escopo. O verbo transitivo `defeated` toma esse sintagma como - argumento e devolve uma propriedade do sujeito. -- A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: - o `#eval` consulta o modelo diretamente. -- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura - fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. ::: ::::full @@ -184,18 +346,714 @@ summary tree, with *Every dwarf defeated a giant* in place of (7.4) (see ```lean def a (p q : OnePlacePred) : Bool := entities.any (fun x => p x && q x) +``` + +:::terse +- Há três nomes para `defeated`, em três níveis: + - `TV.defeated` é a palavra, um construtor da gramática; + - `defeat : Entity → Entity → Bool` é a relação no modelo; + - `defeated`, que definimos agora, é a tradução do verbo. +- Lembre que `OnePlacePred` é uma abreviação (`abbrev`) de `Entity → Bool`, + o tipo das propriedades. O objeto `a giant` tem tipo + `OnePlacePred → Bool`: ele espera uma propriedade. Mas `defeat` tem dois + argumentos e não é uma propriedade. +- O truque é fixar o sujeito `y`. `fun z => defeat y z` é a propriedade "ser + derrotado por `y`", e `X (fun z => defeat y z)` diz que `y` derrotou `X`. + Abstraindo `y`, obtemos uma propriedade do sujeito. +- Por isso `defeated` toma o significado de um sintagma nominal, + `X : OnePlacePred → Bool`, e devolve o de um VP, um `OnePlacePred`. A avaliação da lista as entidades com essa propriedade, as que derrotaram um + gigante: `[B, R]`, que são justamente os dois anões do modelo. +::: +```lean (name := defeatedEval) def defeated (X : OnePlacePred → Bool) : OnePlacePred := fun y => X (fun z => defeat y z) + +#eval entities.filter (defeated (a giant)) ``` -```lean (name := everyDwarfDefeatedAGiant) +:::terse +- A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: + a avaliação consulta o modelo diretamente. +- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura + fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. +::: + +```lean +#eval (every dwarf) (defeated (a giant)) #eval every dwarf (defeated (a giant)) ``` -```leanOutput everyDwarfDefeatedAGiant -true + +## Condições sobre as relações quantificadoras +%%% +tag := "comp-conditions" +%%% + +::::terse +O objetivo da subseção é dizer quais relações entre conjuntos são +quantificadores. É uma definição, *quantificador* é o nome de uma relação que satisfaz EXT, CONS e ISOM. Uma relação qualquer entre conjuntos pode depender de coisas que um quantificador ignora, e cada uma das três condições exclui um desses casos: + +:::table +header +* + * Condição + * O que garante + * O que exclui +* + * EXT + * O resultado não depende do tamanho do universo $`E`, só de + $`A \cup B`. + * *Many* no sentido de "relativamente muitos", que depende de quantas + coisas existem no total. +* + * CONS + * Nada fora da restrição $`A` importa. + * *Only*: em *Only dwarfs sing during work*, acrescentar não anões que + cantam torna a sentença falsa. +* + * ISOM + * Importa quantos elementos há, e não quais. + * Determinantes que falam de um indivíduo, como o possessivo *Alice's*: + em *Alice's daggers are sharp*, o que importa é quem é o dono, e não + quantas adagas há. +::: + +- EXT e CONS valem para quase todos os determinantes da língua natural. + ISOM separa, entre eles, os que exprimem quantidade. +- Juntas, as três condições reduzem o valor de `D E A B` a dois números, + $`|A - B|` e $`|A \cap B|`. É isso que permite a árvore de números de + {ref "comp-trees"}[Árvores numéricas]. +- Para enunciar as condições, saímos de `Bool` e passamos a `Prop` sobre + `Set`, como em {ref "Sets"}[Conjuntos]: `D E A B` diz que o determinante + `D` relaciona a *restrição* `A` e o *escopo* `B` no universo `E`. +- O tipo `GQ.Det α` é só uma abreviação para `Set α → Set α → Set α → Prop`. + Nada no tipo diz que `A` e `B` estão dentro de `E`, como na Figura 7.2. + Essa exigência aparece como as hipóteses `A ⊆ E` e `B ⊆ E` em cada uma das + três condições. +- Não confundir `DET` com `GQ.Det`. `DET` é a categoria sintática de + {ref "ModelChecking"}[Model checking], com as palavras *a*, *the*, + *every*, …. `GQ.Det` é o tipo dos significados dessas palavras. O tipo é + amplo de propósito: todo quantificador é um `GQ.Det`, mas nem todo + `GQ.Det` é um quantificador. +:::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Conditions on Quantifier Relations", from the +start to Figure 7.2. +::: +:::: + +```lean +namespace GQ + +abbrev Det (α : Type) := Set α → Set α → Set α → Prop + +def all {α} : Det α := fun _ A B => A ⊆ B +def some {α} : Det α := fun _ A B => ∃ x, x ∈ A ∧ x ∈ B +def no {α} : Det α := fun _ A B => ∀ x, x ∈ A → x ∉ B +def only {α} : Det α := fun _ A B => B ⊆ A +``` + +:::terse +- {lean}`GQ.all` é a contraparte de {lean}`every` em conjuntos: `every p q` é `true` + exatamente quando o conjunto das entidades com `p` está contido no das + entidades com `q`. +- A prova usa {lean}`mem_entities`: toda entidade está na lista `entities`. +::: + +```lean +theorem every_iff_all (p q : OnePlacePred) : + every p q = true ↔ + all Set.univ {x | p x = true} {x | q x = true} := by + unfold every all + constructor + · intro h x hx + have hx' := List.all_eq_true.mp h x (mem_entities x) + simp_all + · intro h + apply List.all_eq_true.mpr + intro x _ + by_cases hp : p x = true + · have hq : q x = true := h hp + simp [hq] + · simp [hp] +``` + +::::exercise (rating := 2) (name := "subalternation") + +Em {ref "comp-quantification"}[Quantificação] vimos que, sem a pressuposição +existencial, "todo A é B" não implica "algum A é B". Prove as duas coisas: a +subalternação vale quando `A` tem um elemento, e falha em geral. + +```lean +theorem all_imp_some {α : Type} (E A B : Set α) + (hA : ∃ x, x ∈ A) (h : all E A B) : some E A B := by + solution! + obtain ⟨x, hx⟩ := hA + exact ⟨x, hx, h hx⟩ + +theorem all_not_imp_some : + ¬ ∀ (A B : Set Entity), + all Set.univ A B → some Set.univ A B := by + solution! + intro h + obtain ⟨x, hx, _⟩ := h ∅ ∅ (fun _ hx => hx) + exact hx +``` +:::: + +:::terse +- *EXT*: o resultado não muda quando o universo cresce; só importa $`A \cup B`. +- *CONS*: tudo o que está fora da restrição é irrelevante, `D E A B` equivale a + `D E A (A ∩ B)`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Not all two-place relations on sets of +individuals…" to "…A − B and A ∩ B." +::: +:::: + +```lean +def Ext {α : Type} (D : Det α) : Prop := + ∀ E E' A B, A ⊆ E → B ⊆ E → E ⊆ E' → (D E A B ↔ D E' A B) + +def Cons {α : Type} (D : Det α) : Prop := + ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E A (A ∩ B)) +``` + +:::terse +- Para *all* e *some*, as duas condições valem e as provas são curtas. +- As provas de EXT são só `rfl`: as definições começam com `fun _ A B`, isto + é, ignoram o universo `E`, e os dois lados do `↔` são a mesma proposição. +::: + +```lean +theorem all_ext {α : Type} : Ext (all : Det α) := by + intro E E' A B _ _ _ + rfl + +theorem all_cons {α : Type} : Cons (all : Det α) := by + intro E A B _ _ + constructor + · intro h x hx + exact ⟨hx, h hx⟩ + · intro h x hx + exact (h hx).2 + +theorem some_ext {α : Type} : Ext (some : Det α) := by + intro E E' A B _ _ _ + rfl + +theorem some_cons {α : Type} : Cons (some : Det α) := by + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hA, hA, hB⟩ + · intro h + obtain ⟨x, hA, _, hB⟩ := h + exact ⟨x, hA, hB⟩ +``` + +::::exercise (rating := 2) (name := "no-cons") +Prove que *no* é conservativo. + +```lean +theorem no_cons {α : Type} : Cons (no : Det α) := by + solution! + intro E A B _ _ + constructor + · intro h x hA hAB + exact h x hA hAB.2 + · intro h x hA hB + exact h x hA ⟨hA, hB⟩ +``` +:::: + +:::terse +- *Many*, no sentido de "relativamente muitos", não satisfaz EXT. Uma versão + simples: "muitos A são B" quando os A que são B são mais da metade do + universo `E`. Com um universo maior, a mesma sentença pode ficar falsa. +- `Set.ncard` é o número de elementos de um conjunto finito, a $`|A|` da + notação matemática. Ela vem de `Mathlib.Data.Set.Card`. +::: + +```lean +def many {α : Type} : Det α := + fun E A B => E.ncard < 2 * (A ∩ B).ncard +``` + +::::exercise (rating := 2) (name := "many-not-ext") +Prove que `many` não satisfaz EXT. Basta um universo `E` em que a relação +vale e um universo maior `E'` em que ela deixa de valer. + +```lean +theorem many_not_ext : ¬ Ext (many : Det Nat) := by + solution! + intro h + have h1 : (many : Det Nat) {0} {0} {0} := by + simp [many] + have h2 := (h {0} {0, 1} {0} {0} le_rfl le_rfl + (by simp)).1 h1 + simp [many] at h1 + simp [many] at h2 ``` +:::: + +:::terse +*Only*, como em *Only dwarfs sing during work*, não é conservativo. +::: + +::::exercise (rating := 2) (name := "only-not-cons") +Prove que *only* não é conservativo. Basta escolher uma restrição e um escopo +para os quais as duas leituras da definição de `Cons` dão resultados +diferentes. + +```lean +theorem only_not_cons : ¬ Cons (only : Det Entity) := by + solution! + intro h + have hcons : + (only : Det Entity) Set.univ ∅ (∅ ∩ Set.univ) := by + intro x hx + exact hx.1 + have hS : Entity.S ∈ (∅ : Set Entity) := + (h Set.univ ∅ Set.univ (Set.empty_subset _) + (Set.subset_univ _)).2 hcons (Set.mem_univ Entity.S) + exact hS +``` +:::: + +:::terse +- *ISOM*: só importam as quantidades. Se `f` leva `E` bijetivamente em `E'`, + então `D E A B` implica `D E' (f '' A) (f '' B)`. +- `f '' A` é a imagem de `A` por `f`, o conjunto dos `f x` com `x ∈ A`. + `Set.BijOn f E E'` diz que `f` é uma bijeção de `E` em `E'`. +- Um quantificador é uma relação que satisfaz EXT, CONS e ISOM. O valor de + `D E A B` depende então só de $`|A - B|` e $`|A \cap B|`. +- Os artigos também são quantificadores no sentido técnico desta seção. *a* + tem o mesmo significado que *some*: vale quando $`|A \cap B| \geq 1`. *the*, + na leitura russelliana de {ref "ModelChecking"}[Model checking], vale + quando $`|A \cap B| = 1` e $`|A - B| = 0`. A gramática tradicional, porém, + não vê *the* como expressão de quantidade, e sim como um modo de identificar + um referente. Quantificador, aqui, é uma propriedade semântica; determinante + é uma categoria sintática. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Next, the relational perspective +suggests…" to "…the logical representation of quantifiers." +::: +:::: + +```lean +def Isom {α : Type} (D : Det α) : Prop := + ∀ (f : α → α) E E' A B, A ⊆ E → B ⊆ E → + Set.BijOn f E E' → D E A B → D E' (f '' A) (f '' B) + +theorem all_isom {α : Type} : Isom (all : Det α) := by + intro f E E' A B _ _ _ h + exact Set.image_mono h + +theorem some_isom {α : Type} : Isom (some : Det α) := by + intro f E E' A B _ _ _ h + obtain ⟨x, hA, hB⟩ := h + exact ⟨f x, ⟨x, hA, rfl⟩, ⟨x, hB, rfl⟩⟩ +``` + +::::exercise (rating := 2) (name := "the-quant") + +Na leitura de {ref "ModelChecking"}[Model checking], *The dwarf laughed* +diz que há exatamente um anão e que ele riu. Como relação entre conjuntos, +`the E A B` diz que `A` tem um único elemento e que ele está em `B`. Mostre +que `the` satisfaz EXT, CONS e ISOM. Assim, o artigo *the* é, no sentido +técnico desta seção, um quantificador. + +```lean +def the {α : Type} : Det α := + fun _ A B => ∃ x, A = {x} ∧ x ∈ B + +theorem the_ext {α : Type} : Ext (the : Det α) := by + solution! + intro E E' A B _ _ _ + rfl + +theorem the_cons {α : Type} : Cons (the : Det α) := by + solution! + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hA, by rw [hA]; rfl, hB⟩ + · intro h + obtain ⟨x, hA, _, hB⟩ := h + exact ⟨x, hA, hB⟩ + +theorem the_isom {α : Type} : Isom (the : Det α) := by + solution! + intro f E E' A B _ _ _ h + obtain ⟨x, hA, hB⟩ := h + refine ⟨f x, ?_, ⟨x, hB, rfl⟩⟩ + rw [hA, Set.image_singleton] +``` + +:::: + +::::exercise (rating := 3) (name := "poss-not-isom") + +O possessivo *Alice's*, como em *Alice's daggers are sharp*, ocupa a posição +de um determinante: `poss owns a A B` diz que todo `A` que `a` possui é `B`. +A relação de posse `owns` é um parâmetro. Mostre que `poss` satisfaz EXT e +CONS, mas não ISOM. Assim, as três condições são independentes: EXT e CONS +não bastam para fazer de um determinante um quantificador. + +Dica: para ISOM, basta um exemplo pequeno em `Bool`, em que `false` possui +só `true`, e a bijeção `not`. + +```lean +def poss {α : Type} (owns : α → α → Prop) (a : α) : Det α := + fun _ A B => ∀ x, x ∈ A → owns a x → x ∈ B + +theorem poss_ext {α : Type} (owns : α → α → Prop) (a : α) : + Ext (poss owns a) := by + solution! + intro E E' A B _ _ _ + rfl + +theorem poss_cons {α : Type} (owns : α → α → Prop) (a : α) : + Cons (poss owns a) := by + solution! + intro E A B _ _ + constructor + · intro h x hA ho + exact ⟨hA, h x hA ho⟩ + · intro h x hA ho + exact (h x hA ho).2 + +theorem poss_not_isom : + ¬ Isom (poss (fun _ x => x = true) false) := by + solution! + intro h + have hb : Set.BijOn not Set.univ Set.univ := by + refine ⟨fun _ _ => trivial, ?_, ?_⟩ + · intro x _ y _ hxy + cases x <;> cases y <;> simp_all + · intro y _ + exact ⟨!y, trivial, by simp⟩ + have h1 : poss (fun _ x => x = true) false + Set.univ {false} ∅ := by + intro x hx ho + simp_all + have h2 := h not Set.univ Set.univ {false} ∅ + (Set.subset_univ _) (Set.subset_univ _) hb h1 + obtain ⟨_, hx, _⟩ := h2 true ⟨false, rfl, rfl⟩ rfl + exact hx +``` + +:::: + +```lean +end GQ +``` + +## Árvores numéricas +%%% +tag := "comp-trees" +%%% + +:::terse +- Um quantificador `Q` com restrição `A` e escopo `B` é um subconjunto da + *árvore de números*. A linha `k` da árvore tem os pares `(m, n)` com + `m + n = k`, isto é, $`|A| = k`, onde `m` é $`|A - B|` e `n` é + $`|A \cap B|`. +- `row k` gera a linha `k`, da esquerda para a direita: `m` diminui e `n` + aumenta. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has +A as a first…" to "…both of these objects have property B.", with Figure 7.5. +::: +:::: + +```lean (name := rowEval) +def row (k : Nat) : List (Nat × Nat) := + (List.range (k + 1)).map fun x => (k - x, x) + +#eval (List.range 4).map row +``` + +```leanOutput rowEval +[[(0, 0)], [(1, 0), (0, 1)], [(2, 0), (1, 1), (0, 2)], [(3, 0), (2, 1), (1, 2), (0, 3)]] +``` + +:::terse +- Em Haskell, a árvore é uma lista infinita, e `take 10` pega o começo dela. + Lean não é preguiçoso: uma `List` é sempre finita. Por isso + `treeOfNumbers k` devolve só as linhas de `0` a `k`. +::: + +::::exercise (rating := 1) (name := "tree-of-numbers") + +Defina `treeOfNumbers k`, a lista dos pares da árvore de números da linha `0` +até a linha `k`, percorrida de cima para baixo e da esquerda para a direita. + +```lean +def treeOfNumbers (k : Nat) : List (Nat × Nat) := + solution!((List.range (k + 1)).flatMap row) + +theorem treeOfNumbers_three : + treeOfNumbers 3 = + [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), + (3, 0), (2, 1), (1, 2), (0, 3)] := + solution!(by rfl) +``` + +:::: + +:::terse +- O padrão de um quantificador na árvore marca com `+` as posições `(m, n)` + em que ele é verdadeiro, e com `-` as outras. +- Aqui o quantificador é dado direto como uma função de `m` e `n`. + `showTree q` desenha as seis primeiras linhas do padrão de `q`. +- Os três padrões da Figura 7.6: *pelo menos três* ($`n \geq 3`), *menos da + metade* ($`2n < m + n`) e *um número par* ($`n` par). +::: + +```lean +def showRow (q : Nat → Nat → Bool) (k : Nat) : String := + let cells := (row k).map fun (m, n) => + if q m n then "+" else "-" + String.ofList (List.replicate (5 - k) ' ') ++ + String.intercalate " " cells + +def showTree (q : Nat → Nat → Bool) : String := + String.intercalate "\n" ((List.range 6).map (showRow q)) +``` + +```lean (name := atLeastThreeTree) +#eval IO.println <| showTree fun _ n => n ≥ 3 +``` + +```leanOutput atLeastThreeTree + - + - - + - - - + - - - + + - - - + + +- - - + + + +``` + +```lean (name := lessThanHalfTree) +#eval IO.println <| showTree fun m n => 2 * n < m + n +``` + +```leanOutput lessThanHalfTree + - + + - + + - - + + + - - + + + - - - ++ + + - - - +``` + +```lean (name := evenTree) +#eval IO.println <| showTree fun _ n => n % 2 == 0 +``` + +```leanOutput evenTree + + + + - + + - + + + - + - + + - + - + ++ - + - + - +``` + +:::terse +- No exercício seguinte, o quantificador é dado como em Haskell: uma função + que recebe um universo (uma lista) e uma propriedade. `List.all` e + `List.any` já têm esse tipo, e são *all* e *some*. +- Para a posição `(m, n)`, o universo é `[1, …, m + n]`, e a propriedade vale + para exatamente `n` de seus elementos. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To get used to these representations…" to +the end of Exercise 7.3, without the exercises themselves. +::: +:::: + +::::exercise (rating := 2) (name := "gen-tree") + +Defina `genTree q k`, a lista dos pares `(m, n)` de `treeOfNumbers k` para os +quais `q` é verdadeiro num universo de `m + n` objetos dos quais exatamente +`n` têm a propriedade. Por exemplo, `(0, 4)` está na lista de `List.all`, +porque se todos os A são B, os 4 objetos de um domínio A de 4 objetos têm a +propriedade B. + +```lean +abbrev Quant := List Nat → (Nat → Bool) → Bool + +def genTree (q : Quant) (k : Nat) : List (Nat × Nat) := + solution!( + (treeOfNumbers k).filter fun (m, n) => + q (List.range' 1 (m + n)) (fun x => 0 < x && x ≤ n)) + +theorem genTree_all : + genTree List.all 3 = [(0, 0), (0, 1), (0, 2), (0, 3)] := + solution!(by rfl) + +theorem genTree_any : + genTree List.any 3 = + [(0, 1), (1, 1), (0, 2), (2, 1), (1, 2), (0, 3)] := + solution!(by rfl) + +theorem genTree_no : + genTree (fun dom p => !dom.any p) 3 = + [(0, 0), (1, 0), (2, 0), (3, 0)] := + solution!(by rfl) +``` + +:::: + +## Representações lógicas para quantificadores +%%% +tag := "comp-num-repr" +%%% + +:::terse +- O objetivo desta subseção é representar cada quantificador por uma + expressão aritmética em `m` e `n`. Isso é possível porque, com EXT, CONS e + ISOM, o valor de `Q A B` depende só de $`m = |A - B|` e $`n = |A \cap B|`. +- Alguns exemplos: *at least two* é `n ≥ 2`, *all* é `m = 0` e *no* é + `n = 0`. +- `NumQuant` é o tipo `Nat → Nat → Bool`, o mesmo do argumento de `showTree`. + Por isso todo `NumQuant` pode ser desenhado como árvore. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from +"The pairs of cardinals that characterize…" to the definitions of `allNum`, +`noNum`, `atleastNum` and `atmostNum`. +::: +:::: + +```lean +abbrev NumQuant := Nat → Nat → Bool + +def allNum : NumQuant := fun m _ => m = 0 +def noNum : NumQuant := fun _ n => n = 0 + +def atLeastNum (k : Nat) : NumQuant := fun _ n => n ≥ k +def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k +``` + +:::terse +- As operações lógicas sobre quantificadores viram operações sobre essas + expressões. *Not Q* nega a expressão de `Q`. *Q₁ and Q₂* e *Q₁ or Q₂* + combinam as duas expressões com `&&` e `||`. +- Na árvore, a negação troca `+` por `-` em todas as posições. A conjunção + marca com `+` só as posições marcadas nas duas árvores, e a disjunção, as + marcadas em pelo menos uma. +- O exemplo do livro é *at least two but not all*, que fica `n ≥ 2` e não + `m = 0`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Logical operations on quantifiers can now be +handled compositionally…" to the definition of `atleast2butnotall`. +::: +:::: + +```lean (name := atLeast2ButNotAllTree) +def notNum (q : NumQuant) : NumQuant := + fun m n => !q m n + +def andNum (q₁ q₂ : NumQuant) : NumQuant := + fun m n => q₁ m n && q₂ m n + +def orNum (q₁ q₂ : NumQuant) : NumQuant := + fun m n => q₁ m n || q₂ m n + +def atLeast2ButNotAll : NumQuant := + andNum (atLeastNum 2) (notNum allNum) + +#eval IO.println <| showTree atLeast2ButNotAll +``` + +```leanOutput atLeast2ButNotAllTree + - + - - + - - - + - - + - + - - + + - +- - + + + - +``` + +::::exercise (rating := 3) (name := "tree-patterns") + +Defina `someNum`, `notAllNum` e `exactlyNum k`, as expressões de *some*, +*not all* e *exactly k*. Use `showTree` para ver os padrões de *all*, *some*, +*no* e *not all*, e os de *at least three*, *at most three* e *exactly +three*. Depois, prove as relações entre eles: *some* é a negação de *no*, +*not all* é a negação de *all*, *exactly k* é a conjunção de *at least k* e +*at most k*, e *at most k* é a negação de *at least k + 1*. + +Dica: depois de `funext m n`, `rw [Bool.eq_iff_iff]` transforma a igualdade +entre dois `Bool` numa equivalência entre proposições. Em seguida, `simp` +com as definições simplifica a meta, e `omega` resolve o que sobrar de +aritmética. + +```lean +def someNum : NumQuant := + solution!(fun _ n => n > 0) + +def notAllNum : NumQuant := + solution!(fun m _ => m > 0) + +def exactlyNum (k : Nat) : NumQuant := + solution!(fun _ n => n = k) + +theorem someNum_eq : someNum = notNum noNum := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [someNum, notNum, noNum] + omega + +theorem notAllNum_eq : notAllNum = notNum allNum := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [notAllNum, notNum, allNum] + omega + +theorem exactlyNum_eq (k : Nat) : + exactlyNum k = andNum (atLeastNum k) (atMostNum k) := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [exactlyNum, andNum, atLeastNum, atMostNum] + omega + +theorem atMostNum_eq (k : Nat) : + atMostNum k = notNum (atLeastNum (k + 1)) := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [atMostNum, notNum, atLeastNum] +``` + +:::: # A linguagem da lógica tipada e sua semântica %%% diff --git a/DEVIATIONS.md b/DEVIATIONS.md index c0071fc..3175d8e 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -144,6 +144,13 @@ syntax and model, so it comes after `ModelChecking`. Being written. - Example (7.4), *Every mermaid hummed a song*, becomes *Every dwarf defeated a giant*: mermaids, songs and humming are not in `ModelChecking`'s fragment or model, and the new sentence can be evaluated there with `#eval`. +- The tree of numbers is not an infinite list, since Lean is not lazy: + `treeOfNumbers k` (exercise 7.1) gives the rows `0` to `k`, and `genTree` + (exercise 7.3) takes the same bound. +- `Quant` takes the universe before the property, `List Nat → (Nat → Bool) → + Bool`, so that `List.all` and `List.any` have the type as they are. +- Figure 7.6 is computed: `showTree` draws a pattern from a quantifier given as + a function of `m` and `n`. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". diff --git a/STYLE-CODE.md b/STYLE-CODE.md index c8b9cc7..049eb50 100644 --- a/STYLE-CODE.md +++ b/STYLE-CODE.md @@ -83,6 +83,7 @@ this way is usually a mistake; see "Known gaps." | `Morphology` | `open` of constructor namespaces (`open Attr Value`) | `match e₁, e₂ with` (first use outside a solution), `mapM` over `Option` **(solution only)** | *(none new)* | | `InfEngine` | `let rec` | `do`-notation | — | | `ModelChecking` | `mutual` over `inductive` types (`Logic/FOL` only uses it over `def`) | guillemet identifiers (`«with»`), pattern-matching `fun \| … => …` (first use outside a solution) | *(none new)* | +| `Composition` | — | image `f '' A`, `Set.BijOn`, `Set.ncard` | *(none new)* | `ModelChecking` is where `abbrev` and `ToString` instances become the dominant idiom, but both arrive earlier; what is genuinely new there is the mutually From 081d02002d111484b5ff6bf065b58fb1053cf64e Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Fri, 23 Oct 2026 01:09:22 -0300 Subject: [PATCH 08/20] refactor(Composition): rebuild numerical trees around tree k and three quantifier forms Rework "Numerical Trees" and the start of "Logical Representations for Quantifiers" in CSwFP/7.2: - The tree of numbers is built from `tree k`, the list of rows 0 to k. `labelTree` and `drawTree` draw it; `numberTree` labels it with the pairs and `patternTree` (formerly `showTree`) with `+` and `-`. `treeOfNumbers` (exercise 7.1) flattens it. - Exercise gen-tree (7.3) is written over `tree`, so it no longer depends on the solution of tree-of-numbers. - CSwFP's `Quant` becomes `ListQuant`, in parallel with `NumQuant`. `toNum` turns one into the other, and two theorems compare the patterns of `List.all` and *no* with `allNum` and `noNum`. - Both subsections use one cast of example quantifiers, announced at the start; `atleast2butnotall` becomes `atLeast3ButNotAll`. - Terse cues no longer refer to Haskell, to CSwFP's figures, or to what the next exercise asks. - AI-drafted explanations are kept as dev notes next to the pending translation notes. CSwFP.yaml drops the gen-tree dependency, and DEVIATIONS.md records the shared `tree`, the computed figures, `ListQuant`/`toNum` and the single cast. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the dev notes; all of it was reviewed by a human author. --- CSwFP.yaml | 1 - CSwL/Composition.lean | 310 ++++++++++++++++++++++++++---------------- DEVIATIONS.md | 23 +++- 3 files changed, 209 insertions(+), 125 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 12aa1c8..22dd84a 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -205,7 +205,6 @@ depends: pl-consequence: implies-from-list ex-fol-entails: ex-fol-implies-from-list help-defeat: check-sentence - gen-tree: tree-of-numbers sections: diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 2f4aaee..e8caef6 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -151,9 +151,11 @@ def atLeastTwo (a b : String) : LF := [.neg (.eq tx ty), .atom a [tx], .atom a [ty], .atom b [tx], .atom b [ty]])) + def check (f : LF) : Bool := f.eval entities intFairy ass0 (FOL.liftAssign fintFairy) +#eval toString <| atLeastTwo "person" "laugh" #eval check (atLeastTwo "person" "laugh") ``` @@ -237,7 +239,6 @@ theorem atMost_girl : check (atMost 1 "girl" "laugh") = false := solution!(by native_decide) ``` - :::: :::terse @@ -303,7 +304,7 @@ e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. ```lean def every (p q : OnePlacePred) : Bool := - entities.all (fun x => !p x || q x) + entities.all (fun x => p x → q x) #eval (every princess) laugh ``` @@ -345,7 +346,7 @@ summary tree, with *Every dwarf defeated a giant* in place of (7.4) (see ```lean def a (p q : OnePlacePred) : Bool := - entities.any (fun x => p x && q x) + entities.any (fun x => p x ∧ q x) ``` :::terse @@ -427,7 +428,7 @@ quantificadores. É uma definição, *quantificador* é o nome de uma relação `Set`, como em {ref "Sets"}[Conjuntos]: `D E A B` diz que o determinante `D` relaciona a *restrição* `A` e o *escopo* `B` no universo `E`. - O tipo `GQ.Det α` é só uma abreviação para `Set α → Set α → Set α → Prop`. - Nada no tipo diz que `A` e `B` estão dentro de `E`, como na Figura 7.2. + Nada no tipo diz que `A` e `B` estão dentro de `E`. Essa exigência aparece como as hipóteses `A ⊆ E` e `B ⊆ E` em cada uma das três condições. - Não confundir `DET` com `GQ.Det`. `DET` é a categoria sintática de @@ -766,46 +767,98 @@ tag := "comp-trees" %%% :::terse -- Um quantificador `Q` com restrição `A` e escopo `B` é um subconjunto da - *árvore de números*. A linha `k` da árvore tem os pares `(m, n)` com - `m + n = k`, isto é, $`|A| = k`, onde `m` é $`|A - B|` e `n` é - $`|A \cap B|`. -- `row k` gera a linha `k`, da esquerda para a direita: `m` diminui e `n` - aumenta. +- Com EXT, CONS e ISOM, o valor de `Q A B` depende só de dois números: + quantos A não são B ($`m = |A - B|`) e quantos A são B ($`n = |A \cap B|`). + Cada caso possível é um par `(m, n)`. +- Por EXT e CONS, nem o universo nem $`B - A` importam. +- Nesta seção e na seguinte, os exemplos são sempre os mesmos + quantificadores: *all*, *some*, *no* e *not all*; *at least three*, *at + most three* e *exactly three*; *less than half*; e *an even number of*. + Combinando-os, aparece também *at least three but not all*. + +Organizar os pares numa árvore ajuda. Cada linha `row k` reúne os casos em que `A` tem `k` elementos, isto é, os pares com `m + n = k`. Da esquerda para a direita: `m` diminui e `n` aumenta. Na ponta esquerda, nenhum A é B; na direita, todo A é B. ::: ::::full +Em uma frase como *Todo aluno passou*, o determinante relaciona a restrição `A` +(os alunos) e o escopo `B` (quem passou). EXT, CONS e ISOM juntas garantem que +o valor de `Q A B` depende só de dois números: `m`, quantos A não são B, e +`n`, quantos A são B. Cada condição elimina uma informação. Por CONS, o que +está fora de `A` não importa (quem passou sem ser aluno é irrelevante). Por +EXT, o tamanho do universo não importa. Por ISOM, não importa quem são os +objetos, só quantos são. + +Se só o par `(m, n)` importa, basta listar todos os pares e marcar em quais o +quantificador é verdadeiro. A árvore de números organiza os pares por linha. +A linha `k` reúne os casos com $`|A| = m + n = k`. Da esquerda para a +direita, `n` cresce. Assim, a borda esquerda é "nenhum A é B" e a borda +direita é "todo A é B". Para ler uma posição, tome `(1, 2)` na linha 3: há +três alunos, um não passou e dois passaram. Se o quantificador tem `+` ali, a +frase é verdadeira nessa situação. + :::dev BeforeNextRelease TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has A as a first…" to "…both of these objects have property B.", with Figure 7.5. ::: + +:::dev "Claude Opus 5.5" (year := 2026) +Texto gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: :::: -```lean (name := rowEval) +```lean def row (k : Nat) : List (Nat × Nat) := (List.range (k + 1)).map fun x => (k - x, x) - -#eval (List.range 4).map row ``` -```leanOutput rowEval -[[(0, 0)], [(1, 0), (0, 1)], [(2, 0), (1, 1), (0, 2)], [(3, 0), (2, 1), (1, 2), (0, 3)]] +:::terse +- A árvore é a lista das suas linhas: `tree k` tem as linhas `0` a `k`. A + árvore não tem fim, mas uma `List` é sempre finita; por isso o limite `k`. +::: + +```lean +def tree (k : Nat) : List (List (Nat × Nat)) := + (List.range (k + 1)).map row + +#eval tree 3 ``` :::terse -- Em Haskell, a árvore é uma lista infinita, e `take 10` pega o começo dela. - Lean não é preguiçoso: uma `List` é sempre finita. Por isso - `treeOfNumbers k` devolve só as linhas de `0` a `k`. +- Para desenhar a árvore, `labelTree k cell` troca cada par `(m, n)` de + `tree k` pelo texto `cell m n`, e `drawTree w` desenha as linhas de textos, + cada um com largura `w`. +- `numberTree k` é a *árvore de números*: em cada posição, o próprio par. Até + a linha `9`, todo par cabe em três caracteres. ::: -::::exercise (rating := 1) (name := "tree-of-numbers") +```lean +def labelTree (k : Nat) (cell : Nat → Nat → String) : + List (List String) := + (tree k).map fun r => r.map fun (m, n) => cell m n + +def drawTree (w : Nat) (rows : List (List String)) : + String := + let last := rows.length - 1 + let lines := rows.mapIdx fun k cells => + let indent := (last - k) * (w + 1) / 2 + String.ofList (List.replicate indent ' ') ++ + String.intercalate " " cells + String.intercalate "\n" lines + +def numberTree (k : Nat) : String := + drawTree 3 (labelTree k fun m n => s!"{m},{n}") + +#eval IO.println <| numberTree 3 +``` -Defina `treeOfNumbers k`, a lista dos pares da árvore de números da linha `0` -até a linha `k`, percorrida de cima para baixo e da esquerda para a direita. +::::exercise (rating := 1) (name := "tree-of-numbers") +Defina `treeOfNumbers k`, a lista dos pares de `tree k`, percorrida de cima +para baixo e da esquerda para a direita. ```lean def treeOfNumbers (k : Nat) : List (Nat × Nat) := - solution!((List.range (k + 1)).flatMap row) + solution!((tree k).flatten) theorem treeOfNumbers_three : treeOfNumbers 3 = @@ -813,98 +866,80 @@ theorem treeOfNumbers_three : (3, 0), (2, 1), (1, 2), (0, 3)] := solution!(by rfl) ``` - :::: :::terse -- O padrão de um quantificador na árvore marca com `+` as posições `(m, n)` - em que ele é verdadeiro, e com `-` as outras. -- Aqui o quantificador é dado direto como uma função de `m` e `n`. - `showTree q` desenha as seis primeiras linhas do padrão de `q`. -- Os três padrões da Figura 7.6: *pelo menos três* ($`n \geq 3`), *menos da - metade* ($`2n < m + n`) e *um número par* ($`n` par). +- Um quantificador escolhe alguns pares da árvore: aqueles em que ele é + verdadeiro. Aqui o quantificador é dado direto como uma função de `m` e + `n`. +- Para saber se `q` vale num caso, basta saber se o par foi escolhido. Então + a árvore de pares vira uma árvore de `+` e `-`. A função `patternTree k q` + é o par de `numberTree k`: o mesmo `labelTree`, trocando cada par por `+`, + se `q` vale nele, ou por `-`. Essa árvore é o *padrão* de `q`. +- Três exemplos de padrão: *at least three* ($`n \geq 3`), *less than + half* ($`2n < m + n`) e *an even number of* ($`n` par). ::: ```lean -def showRow (q : Nat → Nat → Bool) (k : Nat) : String := - let cells := (row k).map fun (m, n) => - if q m n then "+" else "-" - String.ofList (List.replicate (5 - k) ' ') ++ - String.intercalate " " cells - -def showTree (q : Nat → Nat → Bool) : String := - String.intercalate "\n" ((List.range 6).map (showRow q)) -``` - -```lean (name := atLeastThreeTree) -#eval IO.println <| showTree fun _ n => n ≥ 3 -``` - -```leanOutput atLeastThreeTree - - - - - - - - - - - - - + - - - - + + -- - - + + + -``` - -```lean (name := lessThanHalfTree) -#eval IO.println <| showTree fun m n => 2 * n < m + n -``` - -```leanOutput lessThanHalfTree - - - + - - + - - - + + - - - + + - - - -+ + + - - - +def patternTree (k : Nat) (q : Nat → Nat → Bool) : + String := + drawTree 1 (labelTree k fun m n => + if q m n then "+" else "-") ``` -```lean (name := evenTree) -#eval IO.println <| showTree fun _ n => n % 2 == 0 -``` - -```leanOutput evenTree - + - + - - + - + - + - + - - + - + - + -+ - + - + - +```lean +#eval IO.println <| patternTree 5 fun _ n => n ≥ 3 +#eval IO.println <| patternTree 5 fun m n => 2 * n < m + n +#eval IO.println <| patternTree 5 fun _ n => n % 2 == 0 ``` :::terse -- No exercício seguinte, o quantificador é dado como em Haskell: uma função - que recebe um universo (uma lista) e uma propriedade. `List.all` e - `List.any` já têm esse tipo, e são *all* e *some*. -- Para a posição `(m, n)`, o universo é `[1, …, m + n]`, e a propriedade vale - para exatamente `n` de seus elementos. +- Um quantificador também pode ser dado como uma função que recebe um + universo (uma lista) e uma propriedade: o tipo `ListQuant`. {lean}`List.all` + e {lean}`List.any` já têm esse tipo, e são *all* e *some*. *No* é + `fun dom p => !dom.any p`: nenhum elemento de `dom` tem `p`. +- Um `ListQuant` é um determinante depois de CONS: o universo é o próprio `A` + e a propriedade é `B`. Pode ser assim porque, por CONS, nada fora de `A` + importa. ::: ::::full +Alguns padrões. *All* ($`m = 0`) tem `+` só na borda direita, porque nenhum A +fica fora de B. *No* ($`n = 0`) tem `+` só na borda esquerda. *Less than half* +($`n < m`) tem, na linha 2, `+` em `(2, 0)`, `-` em `(1, 1)` e `(0, 2)`. + +O exercício `genTree` liga a árvore ao quantificador dado como uma função de +um universo e uma propriedade. Para cada `(m, n)`, ele monta um +universo concreto `[1, …, m + n]` em que exatamente `n` elementos têm a +propriedade, e pergunta ao quantificador. Qualquer universo +com essas contagens serve (ISOM). + :::dev BeforeNextRelease TODO: translate CSwFP/7.2, from "To get used to these representations…" to the end of Exercise 7.3, without the exercises themselves. ::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: :::: -::::exercise (rating := 2) (name := "gen-tree") +```lean +abbrev ListQuant := List Nat → (Nat → Bool) → Bool +``` -Defina `genTree q k`, a lista dos pares `(m, n)` de `treeOfNumbers k` para os -quais `q` é verdadeiro num universo de `m + n` objetos dos quais exatamente -`n` têm a propriedade. Por exemplo, `(0, 4)` está na lista de `List.all`, -porque se todos os A são B, os 4 objetos de um domínio A de 4 objetos têm a -propriedade B. +::::exercise (rating := 2) (name := "gen-tree") +Defina `genTree q k`, a lista dos pares `(m, n)` de `tree k` para os quais `q` +é verdadeiro num universo de `m + n` objetos dos quais exatamente `n` têm a +propriedade. Por exemplo, `(0, 3)` está na lista de `List.all`, porque se +todos os A são B, os 3 objetos de um A de 3 objetos têm a propriedade B. ```lean -abbrev Quant := List Nat → (Nat → Bool) → Bool - -def genTree (q : Quant) (k : Nat) : List (Nat × Nat) := +def genTree (q : ListQuant) (k : Nat) : List (Nat × Nat) := solution!( - (treeOfNumbers k).filter fun (m, n) => - q (List.range' 1 (m + n)) (fun x => 0 < x && x ≤ n)) + (tree k).flatten.filter fun (m, n) => + q (List.range' 1 (m + n)) (fun x => x ≤ n)) theorem genTree_all : genTree List.all 3 = [(0, 0), (0, 1), (0, 2), (0, 3)] := @@ -920,7 +955,6 @@ theorem genTree_no : [(0, 0), (1, 0), (2, 0), (3, 0)] := solution!(by rfl) ``` - :::: ## Representações lógicas para quantificadores @@ -932,39 +966,74 @@ tag := "comp-num-repr" - O objetivo desta subseção é representar cada quantificador por uma expressão aritmética em `m` e `n`. Isso é possível porque, com EXT, CONS e ISOM, o valor de `Q A B` depende só de $`m = |A - B|` e $`n = |A \cap B|`. -- Alguns exemplos: *at least two* é `n ≥ 2`, *all* é `m = 0` e *no* é - `n = 0`. -- `NumQuant` é o tipo `Nat → Nat → Bool`, o mesmo do argumento de `showTree`. - Por isso todo `NumQuant` pode ser desenhado como árvore. +- Os padrões de {ref "comp-trees"}[Árvores numéricas] já eram desenhados a + partir de funções de `m` e `n`, como `fun _ n => n ≥ 3`: é o tipo do + argumento de `patternTree`. `NumQuant` dá um nome a esse tipo. Por isso + todo `NumQuant` pode ser desenhado como árvore. ::: ::::full +Esta subseção tira a conclusão da anterior. Um padrão na árvore é um +subconjunto dos pares de naturais. Por isso, o próprio quantificador pode ser +escrito como uma expressão aritmética em `m` e `n`, sem conjuntos e sem +listas: *all* é $`m = 0`, *no* é $`n = 0`, *at least k* é $`n \geq k` e *at +most k* é $`n \leq k`. Em Lean, essa expressão tem o tipo `NumQuant`, que é +justamente o tipo do argumento de `patternTree`. Por isso todo `NumQuant` pode +ser desenhado. + :::dev BeforeNextRelease TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from "The pairs of cardinals that characterize…" to the definitions of `allNum`, `noNum`, `atleastNum` and `atmostNum`. ::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: :::: ```lean abbrev NumQuant := Nat → Nat → Bool def allNum : NumQuant := fun m _ => m = 0 -def noNum : NumQuant := fun _ n => n = 0 - +def noNum : NumQuant := fun _ n => n = 0 def atLeastNum (k : Nat) : NumQuant := fun _ n => n ≥ k -def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k +def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k +``` + +:::terse +- Um `ListQuant` também vira um `NumQuant`: na posição `(m, n)`, `toNum q` + aplica `q` a um universo de `m + n` objetos, `[1, …, m + n]`, com uma + propriedade que vale para exatamente `n` deles, "ser no máximo `n`". +- Qualquer universo com essas contagens daria a mesma resposta: é ISOM. +- Assim podemos comparar as duas formas: o padrão de `List.all` é o de + `allNum`, e o de *no* é o de `noNum`. +::: + +```lean +def toNum (q : ListQuant) : NumQuant := + fun m n => q (List.range' 1 (m + n)) (fun x => x ≤ n) + +theorem toNum_all : + patternTree 5 (toNum List.all) = + patternTree 5 allNum := by + rfl + +theorem toNum_no : + patternTree 5 (toNum fun dom p => !dom.any p) = + patternTree 5 noNum := by + rfl ``` :::terse - As operações lógicas sobre quantificadores viram operações sobre essas - expressões. *Not Q* nega a expressão de `Q`. *Q₁ and Q₂* e *Q₁ or Q₂* - combinam as duas expressões com `&&` e `||`. + expressões. `Not Q` nega a expressão de `Q`. `Q₁ && Q₂` e `Q₁ || Q₂` + combinam as duas expressões. - Na árvore, a negação troca `+` por `-` em todas as posições. A conjunção marca com `+` só as posições marcadas nas duas árvores, e a disjunção, as marcadas em pelo menos uma. -- O exemplo do livro é *at least two but not all*, que fica `n ≥ 2` e não - `m = 0`. +- Um exemplo é *at least three but not all*, que fica `n ≥ 3` e não `m = 0`. ::: ::::full @@ -972,9 +1041,26 @@ def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k TODO: translate CSwFP/7.2, from "Logical operations on quantifiers can now be handled compositionally…" to the definition of `atleast2butnotall`. ::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. + +O ganho é a composicionalidade. As operações lógicas entre quantificadores +viram operações ponto a ponto nas expressões, e cada uma tem uma leitura na +árvore. *Not Q* troca `+` por `-` em todas as posições. *Q₁ and Q₂* marca +`+` só onde as duas árvores têm `+`. *Q₁ or Q₂* marca `+` onde pelo menos +uma tem. O padrão de *at least three but not all* é o de *at least three* sem a +borda direita. Ninguém precisou pensar em conjuntos: o significado da +expressão composta saiu do significado das partes. + +A subseção seguinte usa essas árvores para perguntas como "se `Q` é +reflexivo, como é o seu padrão?". As árvores transformam propriedades +lógicas dos quantificadores em propriedades geométricas fáceis de ver. +::: :::: -```lean (name := atLeast2ButNotAllTree) +```lean def notNum (q : NumQuant) : NumQuant := fun m n => !q m n @@ -984,25 +1070,16 @@ def andNum (q₁ q₂ : NumQuant) : NumQuant := def orNum (q₁ q₂ : NumQuant) : NumQuant := fun m n => q₁ m n || q₂ m n -def atLeast2ButNotAll : NumQuant := - andNum (atLeastNum 2) (notNum allNum) +def atLeast3ButNotAll : NumQuant := + andNum (atLeastNum 3) (notNum allNum) -#eval IO.println <| showTree atLeast2ButNotAll -``` - -```leanOutput atLeast2ButNotAllTree - - - - - - - - - - - - + - - - - + + - -- - + + + - +#eval IO.println <| patternTree 5 atLeast3ButNotAll ``` ::::exercise (rating := 3) (name := "tree-patterns") Defina `someNum`, `notAllNum` e `exactlyNum k`, as expressões de *some*, -*not all* e *exactly k*. Use `showTree` para ver os padrões de *all*, *some*, +*not all* e *exactly k*. Use `patternTree` para ver os padrões de *all*, *some*, *no* e *not all*, e os de *at least three*, *at most three* e *exactly three*. Depois, prove as relações entre eles: *some* é a negação de *no*, *not all* é a negação de *all*, *exactly k* é a conjunção de *at least k* e @@ -1052,7 +1129,6 @@ theorem atMostNum_eq (k : Nat) : rw [Bool.eq_iff_iff] simp [atMostNum, notNum, atLeastNum] ``` - :::: # A linguagem da lógica tipada e sua semântica diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 3175d8e..4ec5f55 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -144,13 +144,22 @@ syntax and model, so it comes after `ModelChecking`. Being written. - Example (7.4), *Every mermaid hummed a song*, becomes *Every dwarf defeated a giant*: mermaids, songs and humming are not in `ModelChecking`'s fragment or model, and the new sentence can be evaluated there with `#eval`. -- The tree of numbers is not an infinite list, since Lean is not lazy: - `treeOfNumbers k` (exercise 7.1) gives the rows `0` to `k`, and `genTree` - (exercise 7.3) takes the same bound. -- `Quant` takes the universe before the property, `List Nat → (Nat → Bool) → - Bool`, so that `List.all` and `List.any` have the type as they are. -- Figure 7.6 is computed: `showTree` draws a pattern from a quantifier given as - a function of `m` and `n`. +- The tree of numbers is not an infinite list, since Lean is not lazy: `tree + k` is the list of rows `0` to `k`, and `treeOfNumbers k` (exercise 7.1) and + `genTree q k` (exercise 7.3) take the same bound. Both are written over + `tree`, so exercise 7.3 does not depend on the solution of 7.1. +- Figures 7.5 and 7.6 are computed: `numberTree` and `patternTree` label the + same `tree k`, one with the pairs and one with `+` and `-`. +- Subsections "Numerical Trees" and "Logical Representations for + Quantifiers" keep one cast of examples, the quantifiers of exercise 7.2 and + Figure 7.6, announced at the start. So CSwFP's `atleast2butnotall` becomes + `atLeast3ButNotAll`, *at least three but not all*. +- CSwFP's `Quant` is `ListQuant`, in parallel with `NumQuant`, and takes the + universe before the property, `List Nat → (Nat → Bool) → Bool`, so that + `List.all` and `List.any` have the type as they are. `toNum` turns a + `ListQuant` into a `NumQuant` at the start of "Logical Representations for + Quantifiers", which CSwFP leaves implicit, so that the patterns of + `List.all` and `allNum` can be compared. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". From b152f2d9fe60ed51137791e3b225532be1959558 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Fri, 23 Oct 2026 01:29:37 -0300 Subject: [PATCH 09/20] feat(Composition): add relational properties of quantifiers Add the subsection "Relational Properties" of CSwFP/7.2 in terse-first form. Each property is defined over sets and over the tree pattern: - Reflexivity: GQ.Refl and ReflNum, with exercise some-not-refl and a quiz on irreflexivity. *Some* is not reflexive: the empty set, at the top of the tree, fails it. - Symmetry: GQ.Symm, with exercise symm-pattern (7.4). - Monotonicity in the scope: GQ.MonUp, GQ.MonDown, MonUpNum and MonDownNum, with exercises no-mon-down and even-not-mon, and exercises 7.5 and 7.6 as quizzes. - Negation, conjunction and disjunction: exercises mon-not (7.7), mon-and (7.8), mon-or (7.9) and mon-up-down (7.10). - Monotonicity in the restriction: exercise left-mon-pattern. The comp-conditions cue no longer cites a CSwFP figure. CSwFP.yaml maps exercises 7.4 to 7.10 and the new original exercises, and DEVIATIONS.md records the reflexivity of *some*, the two versions of each property, and why 7.5 and 7.6 became quizzes. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code, the exercises and the quizzes; all of it was reviewed by a human author. --- CSwFP.yaml | 18 +- CSwL/Composition.lean | 445 ++++++++++++++++++++++++++++++++++++++++++ DEVIATIONS.md | 12 ++ 3 files changed, 468 insertions(+), 7 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 22dd84a..27d4bf3 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -133,13 +133,13 @@ exercises: 7.1 (p. 158): tree-of-numbers 7.2 (p. 158): tree-patterns 7.3 (p. 158): gen-tree - 7.4 (p. 161): TODO - 7.5 (p. 161): TODO - 7.6 (p. 161): TODO - 7.7 (p. 162): TODO - 7.8 (p. 162): TODO - 7.9 (p. 162): TODO - 7.10 (p. 162): TODO + 7.4 (p. 161): symm-pattern + 7.5 (p. 161): turned into a quiz + 7.6 (p. 161): turned into a quiz + 7.7 (p. 162): mon-not + 7.8 (p. 162): mon-and + 7.9 (p. 162): mon-or + 7.10 (p. 162): mon-up-down 7.11 (p. 163): TODO 7.12 (p. 164): TODO 7.13 (p. 165): TODO @@ -199,6 +199,10 @@ original: - many-not-ext # from the prose on EXT in 7.2, "many in the sense of relatively many" - the-quant # from the prose on ISOM in 7.2 and the Russellian `the` of 7.5 - poss-not-isom # from the prose on ISOM in 7.2: EXT and CONS do not imply ISOM + - some-not-refl # from the prose on reflexive quantifiers in 7.2 + - no-mon-down # from the prose on MON↓ in 7.2 + - even-not-mon # from the prose on "an even number of" in 7.2, neither MON↑ nor MON↓ + - left-mon-pattern # from the prose on ↑MON and ↓MON in 7.2, "left to the reader" depends: bangu-proof: bangu-form diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index e8caef6..28585cf 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -1131,6 +1131,451 @@ theorem atMostNum_eq (k : Nat) : ``` :::: +## Propriedades relacionais +%%% +tag := "comp-rel-props" +%%% + +:::terse +- Quantificadores são relações entre conjuntos, então podemos estudar as + propriedades dessas relações: reflexividade, simetria e monotonicidade. +- Cada propriedade tem dois lados. Nos conjuntos, é uma `Prop` sobre + `GQ.Det`, como EXT, CONS e ISOM. Na árvore, é uma forma do padrão, uma + `Prop` sobre `NumQuant`. +- A pergunta que se repete: se `Q` tem a propriedade, como é o seu padrão? +- `Q` é *reflexivo* se `Q A A` vale para todo `A`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Relational Properties", from "As quantifiers are +relations…" to "…the quantifiers no and not all are not." CSwFP calls *some* +reflexive; with its own definition it is not, because of the empty set (see +`DEVIATIONS.md`). +::: +:::: + +```lean +namespace GQ + +def Refl {α : Type} (D : Det α) : Prop := + ∀ E A, A ⊆ E → D E A A + +theorem all_refl {α : Type} : Refl (all : Det α) := by + intro E A _ x hx + exact hx +``` + +::::exercise (rating := 1) (name := "some-not-refl") +Prove que *some* não é reflexivo. + +```lean +theorem some_not_refl : ¬ Refl (some : Det Entity) := by + solution! + intro h + obtain ⟨x, hx, _⟩ := h Set.univ ∅ (Set.empty_subset _) + exact hx +``` +:::: + +:::terse +- Na árvore, `Q A A` é a posição `(0, n)`, com $`n = |A|`: nenhum A fica fora + de A. Então `Q` é reflexivo quando a borda direita do padrão é toda `+`. +- A borda inclui o topo, `(0, 0)`, o caso em que `A` é vazio. É ali que + *some* falha. +::: + +```lean +def ReflNum (q : NumQuant) : Prop := + ∀ n, q 0 n + +theorem allNum_refl : ReflNum allNum := by + intro n + rfl + +#eval IO.println <| patternTree 5 allNum +#eval IO.println <| patternTree 5 (notNum noNum) +``` + +::::quiz +Se a borda direita do padrão de `Q` é toda `-`, que propriedade `Q` tem? +Qual quantificador do nosso elenco tem esse padrão? E *no*, tem? + +:::quizSolution +`Q A A` é falso para todo `A`: `Q` é *irreflexivo*. *Not all* é irreflexivo, +porque na borda direita `m = 0`. *No* não é: no topo, com `A` vazio, +"nenhum A é A" é verdadeiro. *No* não é reflexivo nem irreflexivo. +::: +:::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "One can now study questions about tree +patterns…" to "…which relational property of Q does this reflect?" +::: +:::: + +:::terse +- `Q` é *simétrico* se `Q A B` e `Q B A` sempre têm o mesmo valor. *Some* + é simétrico: "algum A é B" e "algum B é A" dizem a mesma coisa. +- Os quantificadores simétricos são exatamente os que cabem na posição `Q` + de *There are Q*: *There are some dwarfs*, mas não *There are all dwarfs*. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "A relational property with linguistic +interest is symmetry…" to the end of the paragraph after Exercise 7.4, +"…(sentences of the form There are Q)", without the exercise itself. +::: +:::: + +```lean +def Symm {α : Type} (D : Det α) : Prop := + ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E B A) + +theorem some_symm {α : Type} : Symm (some : Det α) := by + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hB, hA⟩ + · intro h + obtain ⟨x, hB, hA⟩ := h + exact ⟨x, hA, hB⟩ +``` + +::::exercise (rating := 2) (name := "symm-pattern") +Defina `SymmNum q`, a forma do padrão de um quantificador simétrico. Depois, +prove que *no* e *at least three* têm essa forma, e que *all* não tem. + +Dica: em `Q A B`, `m` conta os A que não são B; em `Q B A`, conta os B que +não são A. O que muda entre os dois é só `m`. + +```lean +def SymmNum (q : NumQuant) : Prop := + solution!(∀ m m' n, q m n = q m' n) + +theorem noNum_symm : SymmNum noNum := by + solution! + intro m m' n + rfl + +theorem atLeastNum_symm : SymmNum (atLeastNum 3) := by + solution! + intro m m' n + rfl + +theorem allNum_not_symm : ¬ SymmNum allNum := by + solution! + intro h + have h' := h 0 1 0 + simp [allNum] at h' +``` +:::: + +:::terse +- `Q` é *MON↑* (monótono para cima no escopo) se `Q A B` continua + verdadeiro quando `B` cresce. *All*, *some* e *at least three* são MON↑. +- `Q` é *MON↓* se `Q A B` continua verdadeiro quando `B` diminui. *No* e + *not all* são MON↓. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Another example of a relational property…" +to "…Examples are not all and no.", without Exercises 7.5 and 7.6, which +became the quizzes below. CSwFP's example *at least five* is *at least +three* here, as in the rest of the cast. +::: +:::: + +```lean +def MonUp {α : Type} (D : Det α) : Prop := + ∀ E A B B', A ⊆ E → B ⊆ B' → B' ⊆ E → + D E A B → D E A B' + +def MonDown {α : Type} (D : Det α) : Prop := + ∀ E A B B', A ⊆ E → B' ⊆ B → B ⊆ E → + D E A B → D E A B' + +theorem all_monUp {α : Type} : MonUp (all : Det α) := by + intro E A B B' _ hB _ h x hx + exact hB (h hx) +``` + +::::exercise (rating := 1) (name := "no-mon-down") +Prove que *no* é MON↓. + +```lean +theorem no_monDown {α : Type} : MonDown (no : Det α) := by + solution! + intro E A B B' _ hB _ h x hA hB' + exact h x hA (hB hB') +``` +:::: + +```lean +end GQ +``` + +::::quiz +Compare os padrões de *all* e de *at least three*, que são MON↑. Que forma +tem o padrão de um quantificador MON↑? E o de um MON↓? + +:::quizSolution +Acrescentar a `B` um elemento de `A` tira esse elemento de $`A - B` e o põe +em $`A \cap B`: a posição passa de `(m + 1, n)` para `(m, n + 1)`, uma casa à +direita na mesma linha. Então, num padrão MON↑, à direita de um `+` na mesma +linha só há `+`. Num padrão MON↓, o mesmo vale à esquerda. +::: +:::: + +:::terse +- As duas formas, escritas sobre `NumQuant`: `MonUpNum` e `MonDownNum`. +- *An even number of* não é nem MON↑ nem MON↓: no padrão, `+` e `-` + alternam em cada linha. +::: + +```lean +def MonUpNum (q : NumQuant) : Prop := + ∀ m n, q (m + 1) n → q m (n + 1) + +def MonDownNum (q : NumQuant) : Prop := + ∀ m n, q m (n + 1) → q (m + 1) n + +def evenNum : NumQuant := fun _ n => n % 2 == 0 + +theorem atLeastNum_monUp (k : Nat) : + MonUpNum (atLeastNum k) := by + intro m n h + simp [atLeastNum] at * + omega + +theorem noNum_monDown : MonDownNum noNum := by + intro m n h + simp [noNum] at h +``` + +::::exercise (rating := 2) (name := "even-not-mon") +Prove que *an even number of* não é MON↑ nem MON↓. Basta uma posição do +padrão em que a forma falha. + +```lean +theorem evenNum_not_monUp : ¬ MonUpNum evenNum := by + solution! + intro h + have h' := h 0 0 (by decide) + simp [evenNum] at h' + +theorem evenNum_not_monDown : ¬ MonDownNum evenNum := by + solution! + intro h + have h' := h 0 1 (by decide) + simp [evenNum] at h' +``` +:::: + +:::terse +- A monotonicidade tem uso linguístico. Sintagmas nominais com a mesma + monotonicidade se coordenam com *and*, e com monotonicidades opostas, com + *but*: *all men and some women*, *many English but no Dutch*. +- *Itens de polaridade negativa*, como *any* e *lift a finger*, aparecem no + escopo de sintagmas MON↓: *No dwarf liked any of the elves*, mas não + *Every dwarf liked any of the elves*. Os de polaridade positiva, como + *hardly*, fazem o contrário. +- Pelos padrões, dá para responder como negação, conjunção e disjunção + afetam a monotonicidade. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "An example for a quantifier that satisfies +neither MON↑ nor MON↓…" to "…are in the next exercises.", with examples +(7.10)–(7.15), and the sentence after Exercise 7.10, "The answers to these +questions can be tested…". +::: +:::: + +::::exercise (rating := 2) (name := "mon-not") +Prove que a negação troca MON↑ por MON↓, e MON↓ por MON↑. + +```lean +theorem notNum_monUp (q : NumQuant) (h : MonUpNum q) : + MonDownNum (notNum q) := by + solution! + intro m n hq + simp [notNum] at * + by_cases hq' : q (m + 1) n + · have h' := h m n hq' + simp_all + · simpa using hq' + +theorem notNum_monDown (q : NumQuant) (h : MonDownNum q) : + MonUpNum (notNum q) := by + solution! + intro m n hq + simp [notNum] at * + by_cases hq' : q m (n + 1) + · have h' := h m n hq' + simp_all + · simpa using hq' +``` +:::: + +::::exercise (rating := 2) (name := "mon-and") +Prove que a conjunção de dois quantificadores MON↑ é MON↑, e que a de dois +MON↓ é MON↓. + +```lean +theorem andNum_monUp (q₁ q₂ : NumQuant) + (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : + MonUpNum (andNum q₁ q₂) := by + solution! + intro m n h + simp [andNum] at * + exact ⟨h₁ m n h.1, h₂ m n h.2⟩ + +theorem andNum_monDown (q₁ q₂ : NumQuant) + (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : + MonDownNum (andNum q₁ q₂) := by + solution! + intro m n h + simp [andNum] at * + exact ⟨h₁ m n h.1, h₂ m n h.2⟩ +``` +:::: + +::::exercise (rating := 2) (name := "mon-or") +Prove que a disjunção de dois quantificadores MON↑ é MON↑, e que a de dois +MON↓ é MON↓. + +```lean +theorem orNum_monUp (q₁ q₂ : NumQuant) + (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : + MonUpNum (orNum q₁ q₂) := by + solution! + intro m n h + simp [orNum] at * + cases h with + | inl h => exact Or.inl (h₁ m n h) + | inr h => exact Or.inr (h₂ m n h) + +theorem orNum_monDown (q₁ q₂ : NumQuant) + (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : + MonDownNum (orNum q₁ q₂) := by + solution! + intro m n h + simp [orNum] at * + cases h with + | inl h => exact Or.inl (h₁ m n h) + | inr h => exact Or.inr (h₂ m n h) +``` +:::: + +::::exercise (rating := 3) (name := "mon-up-down") +Mostre que, combinando um quantificador MON↑ com um MON↓, nada se pode +garantir: nem a conjunção nem a disjunção são sempre MON↑ ou MON↓. + +Dica: use *at least one* e *at most three*. Antes de provar, desenhe os +padrões da conjunção e da disjunção com `patternTree`. + +```lean +theorem andNum_up_down : + ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → + MonUpNum (andNum q₁ q₂) ∨ + MonDownNum (andNum q₁ q₂) := by + solution! + intro h + have hup := atLeastNum_monUp 1 + have hdown : MonDownNum (atMostNum 3) := by + intro m n h + simp [atMostNum] at * + omega + cases h _ _ hup hdown with + | inl h => + have h' := h 0 3 (by decide) + simp [andNum, atLeastNum, atMostNum] at h' + | inr h => + have h' := h 0 0 (by decide) + simp [andNum, atLeastNum, atMostNum] at h' + +theorem orNum_up_down : + ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → + MonUpNum (orNum q₁ q₂) ∨ + MonDownNum (orNum q₁ q₂) := by + solution! + intro h + have hup := atLeastNum_monUp 3 + have hdown : MonDownNum (atMostNum 1) := by + intro m n h + simp [atMostNum] at * + omega + cases h _ _ hup hdown with + | inl h => + have h' := h 0 1 (by decide) + simp [orNum, atLeastNum, atMostNum] at h' + | inr h => + have h' := h 0 2 (by decide) + simp [orNum, atLeastNum, atMostNum] at h' +``` +:::: + +:::terse +- A monotonicidade também pode ser na restrição. `Q` é *↑MON* se `Q A B` + continua verdadeiro quando `A` cresce, e *↓MON* se continua verdadeiro + quando `A` diminui. *Some* e *not all* são ↑MON; *all* e *no* são ↓MON. +- Ela explica a polaridade dentro da restrição: *All dwarfs who liked any + of the elves were mistrusted*, mas não *Some dwarfs who liked any of the + elves were mistrusted*. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "One can also study monotonicity in the +first argument…" to example (7.17). +::: +:::: + +::::exercise (rating := 2) (name := "left-mon-pattern") +Defina `UpMonNum q` e `DownMonNum q`, as formas do padrão de um quantificador +↑MON e de um ↓MON. Depois, prove que *some* e *not all* são ↑MON, e que +*all* e *no* são ↓MON. + +Dica: acrescentar um elemento a `A` aumenta `m` ou `n` em um, conforme o +elemento esteja ou não em `B`. + +```lean +def UpMonNum (q : NumQuant) : Prop := + solution!(∀ m n, q m n → q (m + 1) n ∧ q m (n + 1)) + +def DownMonNum (q : NumQuant) : Prop := + solution!( + ∀ m n, (q (m + 1) n → q m n) ∧ (q m (n + 1) → q m n)) + +theorem some_upMon : UpMonNum (notNum noNum) := by + solution! + intro m n h + simp_all [notNum, noNum] + +theorem notAll_upMon : UpMonNum (notNum allNum) := by + solution! + intro m n h + simp [notNum, allNum] at * + omega + +theorem all_downMon : DownMonNum allNum := by + solution! + intro m n + simp [allNum] + +theorem no_downMon : DownMonNum noNum := by + solution! + intro m n + simp [noNum] +``` +:::: + # A linguagem da lógica tipada e sua semântica %%% tag := "comp-typed-logic" diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 4ec5f55..b8443a6 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -154,6 +154,18 @@ syntax and model, so it comes after `ModelChecking`. Being written. Quantifiers" keep one cast of examples, the quantifiers of exercise 7.2 and Figure 7.6, announced at the start. So CSwFP's `atleast2butnotall` becomes `atLeast3ButNotAll`, *at least three but not all*. +- In "Relational Properties", CSwFP calls *some* reflexive. With its own + definition, `∀X Q XX`, it is not: `Q ∅ ∅` is false, the top of the tree + pattern. The book keeps the definition and makes the empty set the point, + in exercise `some-not-refl` and in the quiz on irreflexivity. +- Each relational property is defined twice, over sets (`GQ.Refl`, + `GQ.MonUp`, …) and over the tree (`ReflNum`, `MonUpNum`, …). That the two + versions agree is stated, not proved: the proof goes from sets to + cardinalities through EXT, CONS and ISOM. +- Exercises 7.5 and 7.6 become quizzes, because their answers, the tree + forms of MON↑ and MON↓, are the definitions `MonUpNum` and `MonDownNum` + that exercises 7.7–7.10 use. Exercises 7.8 and 7.9 are split by + operation, `mon-and` and `mon-or`, each with both directions. - CSwFP's `Quant` is `ListQuant`, in parallel with `NumQuant`, and takes the universe before the property, `List Nat → (Nat → Bool) → Bool`, so that `List.all` and `List.any` have the type as they are. `toNum` turns a From b53fccbf490b4cfdce40b888f46646ef053923bd Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Fri, 23 Oct 2026 09:32:39 -0300 Subject: [PATCH 10/20] docs(Composition): add model examples to reflexivity and symmetry Evaluate reflexivity and symmetry in the model of ModelChecking with `every` and `a`: an intransitive verb in both positions, an empty restriction (`nobody`) that separates every from a, and the inversion of restriction and scope for a and every. The symmetry cue adds more There-are-Q examples, and a dev note keeps the intransitive-verb examples as material for the translation. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the dev note; all of it was reviewed by a human author. --- CSwL/Composition.lean | 47 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 28585cf..1144827 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -1178,6 +1178,21 @@ theorem some_not_refl : ¬ Refl (some : Det Entity) := by ``` :::: +:::terse +- O mesmo se vê no modelo de {ref "ModelChecking"}[Model checking], com + `every` e `a`. Com um verbo intransitivo nas duas posições, *Todos os que + riram riram* e *Alguém que riu riu* são verdadeiras. +- Com uma restrição vazia, `nobody`, *every* continua verdadeiro e *a* fica + falso: é o caso em que *some* não é reflexivo. +::: + +```lean +def nobody : OnePlacePred := fun _ => false + +#eval (every laugh laugh, a laugh laugh) +#eval (every nobody nobody, a nobody nobody) +``` + :::terse - Na árvore, `Q A A` é a posição `(0, n)`, com $`n = |A|`: nenhum A fica fora de A. Então `Q` é reflexivo quando a borda direita do padrão é toda `+`. @@ -1218,16 +1233,46 @@ patterns…" to "…which relational property of Q does this reflect?" :::terse - `Q` é *simétrico* se `Q A B` e `Q B A` sempre têm o mesmo valor. *Some* é simétrico: "algum A é B" e "algum B é A" dizem a mesma coisa. +- Com um verbo intransitivo no escopo, inverter `A` e `B` leva o verbo para + a restrição: *Alguma menina riu* tem o mesmo valor que *Alguém que riu era + menina*. Já *Toda princesa riu* é verdadeira no modelo, e *Todos os que + riram eram princesas* é falsa: *all* não é simétrico. - Os quantificadores simétricos são exatamente os que cabem na posição `Q` - de *There are Q*: *There are some dwarfs*, mas não *There are all dwarfs*. + de *There are Q*: *There are some dwarfs*, *There are no dragons*, *There + are three wizards*, mas não \**There are all dwarfs* nem \**There are most + dragons*. ::: +```lean +#eval (a girl laugh, a laugh girl) +#eval (every princess laugh, every laugh princess) +``` + ::::full :::dev BeforeNextRelease TODO: translate CSwFP/7.2, from "A relational property with linguistic interest is symmetry…" to the end of the paragraph after Exercise 7.4, "…(sentences of the form There are Q)", without the exercise itself. ::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. Material para quem escrever o `full` desta parte, +não uma tradução do CSwFP. + +A simetria fica mais visível com um verbo intransitivo no escopo, porque a +inversão leva o verbo para a restrição, numa oração relativa. *Alguns anões +comemoraram* equivale a *Alguns dos que comemoraram eram anões*, e *Nenhum +anão comemorou* a *Ninguém que comemorou era anão*: os dois lados dependem +só de $`|A \cap B|`, e a interseção não muda quando os conjuntos trocam de +lugar. Com *all*, a inversão muda o sentido: *Todos os anões comemoraram* +deixa que gigantes também tenham comemorado, *Todos os que comemoraram eram +anões* não deixa. + +Além do elenco, *at most k*, *exactly k* e *an even number of* também são +simétricos, porque só dependem de `n`; *the* e *most* não são. Os exemplos +de *There are Q* marcados com `*` são inaceitáveis, e a razão é semântica, a +falta de simetria, não sintática. +::: :::: ```lean From bf75e6a17c5316e35e1fc93a4a2d99b187c22d84 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Sun, 25 Oct 2026 23:17:23 -0300 Subject: [PATCH 11/20] docs(Composition): clarify reflexivity on the tree pattern Drop the model examples with `nobody`, which the section does not need, and explain step by step why `Q A A` is the right edge of the tree. The irreflexivity quiz answer now shows the patterns of not all and no. An `#eval` of `someNum` is dropped: `someNum` is defined by an exercise, so it is `sorry` in the student variant and cannot be evaluated there. Also small cleanups in two proofs. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues and the code changes; all of it was reviewed by a human author. --- CSwL/Composition.lean | 47 ++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 1144827..8cdb486 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -599,8 +599,7 @@ theorem many_not_ext : ¬ Ext (many : Det Nat) := by simp [many] have h2 := (h {0} {0, 1} {0} {0} le_rfl le_rfl (by simp)).1 h1 - simp [many] at h1 - simp [many] at h2 + simp [many] at h1 h2 ``` :::: @@ -1143,7 +1142,8 @@ tag := "comp-rel-props" `GQ.Det`, como EXT, CONS e ISOM. Na árvore, é uma forma do padrão, uma `Prop` sobre `NumQuant`. - A pergunta que se repete: se `Q` tem a propriedade, como é o seu padrão? -- `Q` é *reflexivo* se `Q A A` vale para todo `A`. + +Começamos avaliando se {lean}`GQ.all` é reflexiva. O quantificador {lean}`GQ.some` não é reflexivo se aceitarmos a restrição vazia. ::: ::::full @@ -1162,7 +1162,7 @@ def Refl {α : Type} (D : Det α) : Prop := ∀ E A, A ⊆ E → D E A A theorem all_refl {α : Type} : Refl (all : Det α) := by - intro E A _ x hx + intro E A ha x hx exact hx ``` @@ -1173,29 +1173,18 @@ Prove que *some* não é reflexivo. theorem some_not_refl : ¬ Refl (some : Det Entity) := by solution! intro h - obtain ⟨x, hx, _⟩ := h Set.univ ∅ (Set.empty_subset _) + obtain ⟨x, hx, h2⟩ := h Set.univ ∅ (Set.empty_subset _) exact hx ``` :::: :::terse -- O mesmo se vê no modelo de {ref "ModelChecking"}[Model checking], com - `every` e `a`. Com um verbo intransitivo nas duas posições, *Todos os que - riram riram* e *Alguém que riu riu* são verdadeiras. -- Com uma restrição vazia, `nobody`, *every* continua verdadeiro e *a* fica - falso: é o caso em que *some* não é reflexivo. -::: - -```lean -def nobody : OnePlacePred := fun _ => false - -#eval (every laugh laugh, a laugh laugh) -#eval (every nobody nobody, a nobody nobody) -``` - -:::terse -- Na árvore, `Q A A` é a posição `(0, n)`, com $`n = |A|`: nenhum A fica fora - de A. Então `Q` é reflexivo quando a borda direita do padrão é toda `+`. +- Em `Q A A`, o escopo é a própria restrição. Nenhum elemento de `A` fica fora + de `A`, então $`m = 0`; todos ficam dentro, então $`n = |A|`. `Q A A` é a + posição `(0, |A|)`. +- Variando o tamanho de `A`, essas posições são `(0, 0)`, `(0, 1)`, + `(0, 2)`, …: a borda direita da árvore. `Q` é reflexivo quando essa borda + é toda `+`. - A borda inclui o topo, `(0, 0)`, o caso em que `A` é vazio. É ali que *some* falha. ::: @@ -1217,9 +1206,17 @@ Se a borda direita do padrão de `Q` é toda `-`, que propriedade `Q` tem? Qual quantificador do nosso elenco tem esse padrão? E *no*, tem? :::quizSolution -`Q A A` é falso para todo `A`: `Q` é *irreflexivo*. *Not all* é irreflexivo, -porque na borda direita `m = 0`. *No* não é: no topo, com `A` vazio, -"nenhum A é A" é verdadeiro. *No* não é reflexivo nem irreflexivo. +`Q A A` é falso para todo `A`: `Q` é *irreflexivo*. Os padrões de *not all* +e de *no* mostram a borda direita de cada um: + +```lean +#eval IO.println <| patternTree 5 (notNum allNum) +#eval IO.println <| patternTree 5 noNum +``` + +*Not all* é irreflexivo: sua borda direita é toda `-`. *No* não é: o topo, +com `A` vazio, é `+`, porque "nenhum A é A" é verdadeiro. E o resto da borda +é `-`, então *no* não é reflexivo nem irreflexivo. ::: :::: From 8f298514c782626f1e9d282131c65e3ea310c08e Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Sun, 25 Oct 2026 23:17:23 -0300 Subject: [PATCH 12/20] refactor(Composition): split the chapter into one file per section Composition.lean becomes the chapter's glue, with the opening and one include per section, as in Logic and Morphology. Section 7.2 stays whole in Composition/Quantification.lean. The sections set no `file :=`, so the HTML is still one page and the generated project still has a single Composition.lean. This commit was prepared with the assistance of an AI tool (Claude Code), which split the file and checked the builds; the structure was decided by a human author. --- CSwFP.yaml | 2 +- CSwL/Composition.lean | 1602 +------------------------- CSwL/Composition/Ambiguity.lean | 10 + CSwL/Composition/Interpretation.lean | 10 + CSwL/Composition/Quantification.lean | 1545 +++++++++++++++++++++++++ CSwL/Composition/Reduction.lean | 10 + CSwL/Composition/Rules.lean | 31 + CSwL/Composition/TypedLogic.lean | 17 + CSwL/Composition/TypedMeanings.lean | 10 + README.md | 1 + 10 files changed, 1649 insertions(+), 1589 deletions(-) create mode 100644 CSwL/Composition/Ambiguity.lean create mode 100644 CSwL/Composition/Interpretation.lean create mode 100644 CSwL/Composition/Quantification.lean create mode 100644 CSwL/Composition/Reduction.lean create mode 100644 CSwL/Composition/Rules.lean create mode 100644 CSwL/Composition/TypedLogic.lean create mode 100644 CSwL/Composition/TypedMeanings.lean diff --git a/CSwFP.yaml b/CSwFP.yaml index 27d4bf3..9d4e64f 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -190,7 +190,7 @@ original: Morphology/Phonemes.lean: [append-suffix-text] Morphology/SwedishPlural.lean: [swedish-plural] InfEngine.lean: [inconsistent-kb, ferio] - Composition.lean: + Composition/Quantification.lean: - at-most-two # from the prose on "At least two A are B" in 7.2 - at-least-n # from the prose on "at least n" and "at most m" in 7.2 - subalternation # from the prose on existential presuppositions in 7.2 diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 8cdb486..7539e5e 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -3,6 +3,13 @@ import Bib import CSwL.ModelChecking import Mathlib.Data.Set.Function import Mathlib.Data.Set.Card +import CSwL.Composition.Rules +import CSwL.Composition.Quantification +import CSwL.Composition.TypedLogic +import CSwL.Composition.Reduction +import CSwL.Composition.TypedMeanings +import CSwL.Composition.Interpretation +import CSwL.Composition.Ambiguity open Verso.Genre Manual open CSwLMeta @@ -14,12 +21,6 @@ htmlSplit := .never file := "Composition" %%% -```lean -namespace Composition - -open ModelChecking -``` - :::dev NOW Plan. The headings follow CSwFP/7.1–7.7 (7.8, further reading, is omitted). Sections are written `terse` first (see `STYLE-CODE.md`). Code comes in the @@ -65,1591 +66,16 @@ lambda-calculus engine of `ModelChecking`. ::: :::: -# As regras do jogo -%%% -tag := "comp-rules" -%%% - -:::terse -- Traduzir sentenças para uma lógica pressupõe entender as fórmulas e as - sentenças. Por isso a tradução não explica o significado das sentenças. -- O procedimento de {ref "english-lf"}[FOL como linguagem de representação] - explica: o significado do todo é construído a partir dos significados das - partes. Os significados das palavras vêm do modelo. -- A semântica computacional tem pouco ou nada a dizer sobre a interpretação dos - átomos semânticos (a interpretação dos átomos no modelo de primeira ordem); tem muito a dizer sobre o processo de compor sistematicamente significados complexos a partir dos significados dos componentes. -- Princípio da Composicionalidade, já visto em {ref "IntroCS"}[O estudo formal - da língua natural]: o significado de uma expressão é uma função dos - significados de seus componentes imediatos e do modo de composição. -- Frege, depois Montague. Em Montague, outro ingrediente-chave: os - quantificadores. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.1. -::: -:::: - -# Quantificação -%%% -tag := "comp-quantification" -%%% - -:::terse -- O objetivo da seção é comparar a visão aristotélica e a visão fregeana dos - quantificadores. A de Frege é muito superior, mas deixa três problemas em - aberto, e o resto do capítulo trata deles. -- A teoria da quantificação de Aristóteles, que vimos em - {ref "InfEngine"}[Um motor de inferência], tem dois defeitos lógicos e uma - falha menor: - 1. ela não trata combinações de quantificadores, pois só admite um - quantificador por sentença; - 2. ela não cobre quantificadores "não padrão", como *most*, *half of* e - *at least five*; - 3. ela supõe a pressuposição existencial. -- Frege remove o primeiro defeito. Os quantificadores ∀ e ∃ ligam variáveis - e se combinam com fórmulas arbitrárias, de modo que uma fórmula pode ter - quantos quantificadores quiser. O segundo defeito continua. -- ∀ e ∃ se definem um pelo outro com a negação: $`\exists x P x` vale se e - somente se $`\neg \forall x \neg P x` vale. -- Os quatro quantificadores do quadrado das oposições se escrevem com ∀ e ∃: - "todo A é B" é $`\forall x (Ax \to Bx)`, "algum A é B" é - $`\exists x (Ax \land Bx)`, e assim por diante. -- Por que "esquecer" a pressuposição existencial: a questão não é o domínio - (em FOL ele é não vazio), mas a extensão de `A`. Se nenhum elemento satisfaz - `A`, então $`\forall x (Ax \to Bx)` é vacuamente verdadeira e - $`\exists x (Ax \land Bx)` é falsa. -- Com `A` vazio, só as diagonais (contraditórias) sobrevivem. Caem as - contrárias ("todo A é B" e "nenhum A é B" ambas verdadeiras), as - subcontrárias e a subalternação. Ex.: *Darapti* não vale em FOL. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from the start to "…in terms of standard -quantifiers and equality." -::: -:::: - -:::terse -- Com a igualdade, a lógica de primeira ordem exprime também quantificadores - numéricos. "Pelo menos dois A são B" é - $`\exists x \exists y (x \neq y \land Ax \land Ay \land Bx \land By)`. -- A fórmula de "pelo menos dois A são B" em Lean é um valor do tipo `LF`, o - mesmo de {ref "ModelChecking"}[Model checking]. Os predicados `a` e `b` são - parâmetros, e a função devolve uma fórmula para cada par de predicados. -- `.neg (.eq tx ty)` é $`x \neq y`. A igualdade já é um construtor de - `Formula` desde {ref "FOL"}[FOL]. -- No modelo do capítulo há três pessoas que riem e só duas meninas que riem. -::: - -```lean -open FOL in -def atLeastTwo (a b : String) : LF := - .exists_ x (.exists_ y (.conjs - [.neg (.eq tx ty), .atom a [tx], .atom a [ty], - .atom b [tx], .atom b [ty]])) - - -def check (f : LF) : Bool := - f.eval entities intFairy ass0 (FOL.liftAssign fintFairy) - -#eval toString <| atLeastTwo "person" "laugh" -#eval check (atLeastTwo "person" "laugh") -``` - -::::exercise (rating := 1) (name := "at-most-two") - -Seguindo o modelo de {name}`atLeastTwo`, defina a fórmula de "no máximo dois -A são B". Dica: se três elementos são A e B, dois deles são iguais. - -```lean -open FOL in -def atMostTwo (a b : String) : LF := - solution!( - .forall_ x (.forall_ y (.forall_ z (.impl - (.conjs [.atom a [tx], .atom a [ty], .atom a [tz], - .atom b [tx], .atom b [ty], .atom b [tz]]) - (.disjs [.eq tx ty, .eq tx tz, .eq ty tz]))))) - -theorem atMostTwo_girl : - check (atMostTwo "girl" "laugh") = true := - solution!(by native_decide) - -theorem atMostTwo_person : - check (atMostTwo "person" "laugh") = false := - solution!(by native_decide) -``` - -:::: - -:::terse -- {name}`atLeastTwo` e `atMostTwo` são funções que *geram* fórmulas. A - função é escrita em Lean, a metalinguagem; o que ela devolve é uma fórmula - de FOL, a linguagem objeto. -- Todas as disjunções e conjunções de quantificadores das formas *pelo menos - n* e *no máximo m* podem ser expressas com os quantificadores padrão e a - igualdade. -- O que a lógica de primeira ordem consegue contar: só números fixos e - finitos, com uma fórmula diferente para cada `n`. -- Não existe uma única fórmula que expresse "pelo menos n" para `n` - arbitrário. Cada fórmula tem um número fixo de quantificadores, e isso - limita até onde ela consegue contar. -- Em Lean, porém, podemos escrever uma única *função* `atLeast n` que, para - cada `n`, gera a fórmula correspondente. As `n` variáveis distintas saem do - índice de `Variable`: `⟨"x", [i]⟩` é a variável `xi`. -::: - -::::exercise (rating := 3) (name := "at-least-n") - -Defina `atLeast n a b`, a fórmula de "pelo menos n A são B", e -`atMost n a b`, a de "no máximo n A são B". Dica: "no máximo n" é a negação -de "pelo menos n + 1". Para `atLeast`, uma função auxiliar recursiva pode -carregar a lista dos termos já quantificados, para exigir que cada nova -variável seja diferente de todos eles. - -```lean -open FOL in -def atLeastFrom (a b : String) (n : Nat) (ts : List Term) : - LF := - solution!( - match n with - | 0 => .top - | n + 1 => - let v : Variable := ⟨"x", [n]⟩ - let t : Term := .var v - .exists_ v (.conjs ([.atom a [t], .atom b [t]] ++ - ts.map (fun s => .neg (.eq s t)) ++ - [atLeastFrom a b n (t :: ts)]))) - -def atLeast (n : Nat) (a b : String) : LF := - solution!(atLeastFrom a b n []) - -def atMost (n : Nat) (a b : String) : LF := - solution!(.neg (atLeast (n + 1) a b)) - -theorem atLeast_person : - check (atLeast 3 "person" "laugh") = true ∧ - check (atLeast 4 "person" "laugh") = false := - solution!(by native_decide) - -theorem atMost_girl : - check (atMost 2 "girl" "laugh") = true ∧ - check (atMost 1 "girl" "laugh") = false := - solution!(by native_decide) -``` -:::: - -:::terse -- *Every prince sang a ballad* ("Todo príncipe cantou uma balada"): na - fórmula, os sintagmas nominais desaparecem. -- *A ballad was sung by every prince* ("Uma balada foi cantada por todo - príncipe"): duas fórmulas, duas leituras. A lógica de primeira ordem - desambigua. -- A visão fregeana deixa três problemas em aberto: - 1. encontrar uma linguagem de representação que preserve os sintagmas - nominais como constituintes; - 2. encontrar um procedimento de tradução da língua natural que não seja - ad hoc; - 3. tratar quantificadores não padrão como *most*, de preferência junto com - os quantificadores padrão. -- O resto desta seção, a partir da visão relacional, responde aos problemas - 1 e 3: *every dwarf* vira uma função, e *most* é uma relação entre - conjuntos como *every*. A lógica tipada e o cálculo lambda, nas próximas - seções, respondem ao problema 2. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "To illustrate the claim that first-order -logic has no difficulty…" to "…in a uniform framework with standard -quantifiers." The two paragraphs on the noun phrases of (7.1) and on -"systematically misleading expressions" are cut to a reminder of -`english-form` (see `DEVIATIONS.md`). -::: -:::: - -## A visão relacional dos quantificadores -%%% -tag := "comp-relational" -%%% - -:::terse -- O objetivo da subseção é apresentar a visão relacional dos quantificadores - e mostrar, em dois exemplos, que com ela os sintagmas nominais continuam - sendo constituintes, inclusive quando há dois quantificadores na mesma - sentença. -- Um quantificador é uma relação binária entre subconjuntos de um domínio - $`E` (Mostowski {citep Bib.mostowski1957}[]; Barwise e Cooper - {citep Bib.barwise1981}[]). -- A relação já apareceu em {ref "english-lf"}[FOL como linguagem de - representação]: os dois argumentos de `lfDET` são a restrição e o escopo. - Lá, porém, o determinante construía uma fórmula. Aqui ele relaciona - diretamente dois conjuntos de entidades. -- *Every princess laughed* ("Toda princesa riu"): o determinante é uma função - de duas propriedades, `every : OnePlacePred → OnePlacePred → Bool`. - `every p q` verifica que toda entidade com `p` tem `q`. -- Os tipos acompanham a composição: `every princess : OnePlacePred → Bool`, - e a sentença `every princess laugh : Bool`. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "The relational view of quantifiers", from the -start to the table after (7.3). Decide whether the table keeps the types -e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. -::: -:::: - -```lean -def every (p q : OnePlacePred) : Bool := - entities.all (fun x => p x → q x) - -#eval (every princess) laugh -``` - -:::terse -- Lembre de {ref "Sets"}[Conjuntos e Relações]: a função característica de - um conjunto responde, para cada elemento, se ele pertence ao conjunto. - `princess : Entity → Bool` é a função característica do conjunto das - princesas. -- `every princess` aplica a mesma ideia um nível acima. Ele tem tipo - `OnePlacePred → Bool`, logo é a função característica de um conjunto de - *propriedades*: as que toda princesa tem, isto é, as `q` com - $`\textit{princess} \subseteq q`. -- O `#eval` a seguir mostra esse conjunto, restrito a três propriedades. O - resultado é `["laugh"]`: das três propriedades, só "rir" é de toda - princesa. -::: - -```lean (name := everyPrincessEval) -#eval [("laugh", laugh), ("cheer", cheer), - ("shudder", shudder)] - |>.filter (fun (_, q) => every princess q) |>.map (·.1) -``` - -:::terse -- *Every dwarf defeated a giant* ("Todo anão derrotou um gigante"): uma - sentença com dois quantificadores. -- `a p q` verifica que alguma entidade tem `p` e `q`: a interseção dos dois - conjuntos não é vazia. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "To see how quantifier combinations…" to the -summary tree, with *Every dwarf defeated a giant* in place of (7.4) (see -`DEVIATIONS.md`). -::: -:::: - -```lean -def a (p q : OnePlacePred) : Bool := - entities.any (fun x => p x ∧ q x) -``` - -:::terse -- Há três nomes para `defeated`, em três níveis: - - `TV.defeated` é a palavra, um construtor da gramática; - - `defeat : Entity → Entity → Bool` é a relação no modelo; - - `defeated`, que definimos agora, é a tradução do verbo. -- Lembre que `OnePlacePred` é uma abreviação (`abbrev`) de `Entity → Bool`, - o tipo das propriedades. O objeto `a giant` tem tipo - `OnePlacePred → Bool`: ele espera uma propriedade. Mas `defeat` tem dois - argumentos e não é uma propriedade. -- O truque é fixar o sujeito `y`. `fun z => defeat y z` é a propriedade "ser - derrotado por `y`", e `X (fun z => defeat y z)` diz que `y` derrotou `X`. - Abstraindo `y`, obtemos uma propriedade do sujeito. -- Por isso `defeated` toma o significado de um sintagma nominal, - `X : OnePlacePred → Bool`, e devolve o de um VP, um `OnePlacePred`. A avaliação da lista as entidades com essa propriedade, as que derrotaram um - gigante: `[B, R]`, que são justamente os dois anões do modelo. -::: - -```lean (name := defeatedEval) -def defeated (X : OnePlacePred → Bool) : OnePlacePred := - fun y => X (fun z => defeat y z) - -#eval entities.filter (defeated (a giant)) -``` - -:::terse -- A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: - a avaliação consulta o modelo diretamente. -- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura - fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. -::: +{include 1 CSwL.Composition.Rules} -```lean -#eval (every dwarf) (defeated (a giant)) -#eval every dwarf (defeated (a giant)) -``` +{include 1 CSwL.Composition.Quantification} +{include 1 CSwL.Composition.TypedLogic} -## Condições sobre as relações quantificadoras -%%% -tag := "comp-conditions" -%%% - -::::terse -O objetivo da subseção é dizer quais relações entre conjuntos são -quantificadores. É uma definição, *quantificador* é o nome de uma relação que satisfaz EXT, CONS e ISOM. Uma relação qualquer entre conjuntos pode depender de coisas que um quantificador ignora, e cada uma das três condições exclui um desses casos: - -:::table +header -* - * Condição - * O que garante - * O que exclui -* - * EXT - * O resultado não depende do tamanho do universo $`E`, só de - $`A \cup B`. - * *Many* no sentido de "relativamente muitos", que depende de quantas - coisas existem no total. -* - * CONS - * Nada fora da restrição $`A` importa. - * *Only*: em *Only dwarfs sing during work*, acrescentar não anões que - cantam torna a sentença falsa. -* - * ISOM - * Importa quantos elementos há, e não quais. - * Determinantes que falam de um indivíduo, como o possessivo *Alice's*: - em *Alice's daggers are sharp*, o que importa é quem é o dono, e não - quantas adagas há. -::: - -- EXT e CONS valem para quase todos os determinantes da língua natural. - ISOM separa, entre eles, os que exprimem quantidade. -- Juntas, as três condições reduzem o valor de `D E A B` a dois números, - $`|A - B|` e $`|A \cap B|`. É isso que permite a árvore de números de - {ref "comp-trees"}[Árvores numéricas]. -- Para enunciar as condições, saímos de `Bool` e passamos a `Prop` sobre - `Set`, como em {ref "Sets"}[Conjuntos]: `D E A B` diz que o determinante - `D` relaciona a *restrição* `A` e o *escopo* `B` no universo `E`. -- O tipo `GQ.Det α` é só uma abreviação para `Set α → Set α → Set α → Prop`. - Nada no tipo diz que `A` e `B` estão dentro de `E`. - Essa exigência aparece como as hipóteses `A ⊆ E` e `B ⊆ E` em cada uma das - três condições. -- Não confundir `DET` com `GQ.Det`. `DET` é a categoria sintática de - {ref "ModelChecking"}[Model checking], com as palavras *a*, *the*, - *every*, …. `GQ.Det` é o tipo dos significados dessas palavras. O tipo é - amplo de propósito: todo quantificador é um `GQ.Det`, mas nem todo - `GQ.Det` é um quantificador. -:::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "Conditions on Quantifier Relations", from the -start to Figure 7.2. -::: -:::: - -```lean -namespace GQ - -abbrev Det (α : Type) := Set α → Set α → Set α → Prop - -def all {α} : Det α := fun _ A B => A ⊆ B -def some {α} : Det α := fun _ A B => ∃ x, x ∈ A ∧ x ∈ B -def no {α} : Det α := fun _ A B => ∀ x, x ∈ A → x ∉ B -def only {α} : Det α := fun _ A B => B ⊆ A -``` - -:::terse -- {lean}`GQ.all` é a contraparte de {lean}`every` em conjuntos: `every p q` é `true` - exatamente quando o conjunto das entidades com `p` está contido no das - entidades com `q`. -- A prova usa {lean}`mem_entities`: toda entidade está na lista `entities`. -::: +{include 1 CSwL.Composition.Reduction} -```lean -theorem every_iff_all (p q : OnePlacePred) : - every p q = true ↔ - all Set.univ {x | p x = true} {x | q x = true} := by - unfold every all - constructor - · intro h x hx - have hx' := List.all_eq_true.mp h x (mem_entities x) - simp_all - · intro h - apply List.all_eq_true.mpr - intro x _ - by_cases hp : p x = true - · have hq : q x = true := h hp - simp [hq] - · simp [hp] -``` +{include 1 CSwL.Composition.TypedMeanings} -::::exercise (rating := 2) (name := "subalternation") - -Em {ref "comp-quantification"}[Quantificação] vimos que, sem a pressuposição -existencial, "todo A é B" não implica "algum A é B". Prove as duas coisas: a -subalternação vale quando `A` tem um elemento, e falha em geral. - -```lean -theorem all_imp_some {α : Type} (E A B : Set α) - (hA : ∃ x, x ∈ A) (h : all E A B) : some E A B := by - solution! - obtain ⟨x, hx⟩ := hA - exact ⟨x, hx, h hx⟩ - -theorem all_not_imp_some : - ¬ ∀ (A B : Set Entity), - all Set.univ A B → some Set.univ A B := by - solution! - intro h - obtain ⟨x, hx, _⟩ := h ∅ ∅ (fun _ hx => hx) - exact hx -``` -:::: - -:::terse -- *EXT*: o resultado não muda quando o universo cresce; só importa $`A \cup B`. -- *CONS*: tudo o que está fora da restrição é irrelevante, `D E A B` equivale a - `D E A (A ∩ B)`. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "Not all two-place relations on sets of -individuals…" to "…A − B and A ∩ B." -::: -:::: - -```lean -def Ext {α : Type} (D : Det α) : Prop := - ∀ E E' A B, A ⊆ E → B ⊆ E → E ⊆ E' → (D E A B ↔ D E' A B) - -def Cons {α : Type} (D : Det α) : Prop := - ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E A (A ∩ B)) -``` - -:::terse -- Para *all* e *some*, as duas condições valem e as provas são curtas. -- As provas de EXT são só `rfl`: as definições começam com `fun _ A B`, isto - é, ignoram o universo `E`, e os dois lados do `↔` são a mesma proposição. -::: - -```lean -theorem all_ext {α : Type} : Ext (all : Det α) := by - intro E E' A B _ _ _ - rfl - -theorem all_cons {α : Type} : Cons (all : Det α) := by - intro E A B _ _ - constructor - · intro h x hx - exact ⟨hx, h hx⟩ - · intro h x hx - exact (h hx).2 - -theorem some_ext {α : Type} : Ext (some : Det α) := by - intro E E' A B _ _ _ - rfl - -theorem some_cons {α : Type} : Cons (some : Det α) := by - intro E A B _ _ - constructor - · intro h - obtain ⟨x, hA, hB⟩ := h - exact ⟨x, hA, hA, hB⟩ - · intro h - obtain ⟨x, hA, _, hB⟩ := h - exact ⟨x, hA, hB⟩ -``` - -::::exercise (rating := 2) (name := "no-cons") -Prove que *no* é conservativo. - -```lean -theorem no_cons {α : Type} : Cons (no : Det α) := by - solution! - intro E A B _ _ - constructor - · intro h x hA hAB - exact h x hA hAB.2 - · intro h x hA hB - exact h x hA ⟨hA, hB⟩ -``` -:::: - -:::terse -- *Many*, no sentido de "relativamente muitos", não satisfaz EXT. Uma versão - simples: "muitos A são B" quando os A que são B são mais da metade do - universo `E`. Com um universo maior, a mesma sentença pode ficar falsa. -- `Set.ncard` é o número de elementos de um conjunto finito, a $`|A|` da - notação matemática. Ela vem de `Mathlib.Data.Set.Card`. -::: - -```lean -def many {α : Type} : Det α := - fun E A B => E.ncard < 2 * (A ∩ B).ncard -``` - -::::exercise (rating := 2) (name := "many-not-ext") -Prove que `many` não satisfaz EXT. Basta um universo `E` em que a relação -vale e um universo maior `E'` em que ela deixa de valer. - -```lean -theorem many_not_ext : ¬ Ext (many : Det Nat) := by - solution! - intro h - have h1 : (many : Det Nat) {0} {0} {0} := by - simp [many] - have h2 := (h {0} {0, 1} {0} {0} le_rfl le_rfl - (by simp)).1 h1 - simp [many] at h1 h2 -``` -:::: - -:::terse -*Only*, como em *Only dwarfs sing during work*, não é conservativo. -::: - -::::exercise (rating := 2) (name := "only-not-cons") -Prove que *only* não é conservativo. Basta escolher uma restrição e um escopo -para os quais as duas leituras da definição de `Cons` dão resultados -diferentes. - -```lean -theorem only_not_cons : ¬ Cons (only : Det Entity) := by - solution! - intro h - have hcons : - (only : Det Entity) Set.univ ∅ (∅ ∩ Set.univ) := by - intro x hx - exact hx.1 - have hS : Entity.S ∈ (∅ : Set Entity) := - (h Set.univ ∅ Set.univ (Set.empty_subset _) - (Set.subset_univ _)).2 hcons (Set.mem_univ Entity.S) - exact hS -``` -:::: - -:::terse -- *ISOM*: só importam as quantidades. Se `f` leva `E` bijetivamente em `E'`, - então `D E A B` implica `D E' (f '' A) (f '' B)`. -- `f '' A` é a imagem de `A` por `f`, o conjunto dos `f x` com `x ∈ A`. - `Set.BijOn f E E'` diz que `f` é uma bijeção de `E` em `E'`. -- Um quantificador é uma relação que satisfaz EXT, CONS e ISOM. O valor de - `D E A B` depende então só de $`|A - B|` e $`|A \cap B|`. -- Os artigos também são quantificadores no sentido técnico desta seção. *a* - tem o mesmo significado que *some*: vale quando $`|A \cap B| \geq 1`. *the*, - na leitura russelliana de {ref "ModelChecking"}[Model checking], vale - quando $`|A \cap B| = 1` e $`|A - B| = 0`. A gramática tradicional, porém, - não vê *the* como expressão de quantidade, e sim como um modo de identificar - um referente. Quantificador, aqui, é uma propriedade semântica; determinante - é uma categoria sintática. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "Next, the relational perspective -suggests…" to "…the logical representation of quantifiers." -::: -:::: - -```lean -def Isom {α : Type} (D : Det α) : Prop := - ∀ (f : α → α) E E' A B, A ⊆ E → B ⊆ E → - Set.BijOn f E E' → D E A B → D E' (f '' A) (f '' B) - -theorem all_isom {α : Type} : Isom (all : Det α) := by - intro f E E' A B _ _ _ h - exact Set.image_mono h - -theorem some_isom {α : Type} : Isom (some : Det α) := by - intro f E E' A B _ _ _ h - obtain ⟨x, hA, hB⟩ := h - exact ⟨f x, ⟨x, hA, rfl⟩, ⟨x, hB, rfl⟩⟩ -``` - -::::exercise (rating := 2) (name := "the-quant") - -Na leitura de {ref "ModelChecking"}[Model checking], *The dwarf laughed* -diz que há exatamente um anão e que ele riu. Como relação entre conjuntos, -`the E A B` diz que `A` tem um único elemento e que ele está em `B`. Mostre -que `the` satisfaz EXT, CONS e ISOM. Assim, o artigo *the* é, no sentido -técnico desta seção, um quantificador. - -```lean -def the {α : Type} : Det α := - fun _ A B => ∃ x, A = {x} ∧ x ∈ B - -theorem the_ext {α : Type} : Ext (the : Det α) := by - solution! - intro E E' A B _ _ _ - rfl - -theorem the_cons {α : Type} : Cons (the : Det α) := by - solution! - intro E A B _ _ - constructor - · intro h - obtain ⟨x, hA, hB⟩ := h - exact ⟨x, hA, by rw [hA]; rfl, hB⟩ - · intro h - obtain ⟨x, hA, _, hB⟩ := h - exact ⟨x, hA, hB⟩ - -theorem the_isom {α : Type} : Isom (the : Det α) := by - solution! - intro f E E' A B _ _ _ h - obtain ⟨x, hA, hB⟩ := h - refine ⟨f x, ?_, ⟨x, hB, rfl⟩⟩ - rw [hA, Set.image_singleton] -``` - -:::: - -::::exercise (rating := 3) (name := "poss-not-isom") - -O possessivo *Alice's*, como em *Alice's daggers are sharp*, ocupa a posição -de um determinante: `poss owns a A B` diz que todo `A` que `a` possui é `B`. -A relação de posse `owns` é um parâmetro. Mostre que `poss` satisfaz EXT e -CONS, mas não ISOM. Assim, as três condições são independentes: EXT e CONS -não bastam para fazer de um determinante um quantificador. - -Dica: para ISOM, basta um exemplo pequeno em `Bool`, em que `false` possui -só `true`, e a bijeção `not`. - -```lean -def poss {α : Type} (owns : α → α → Prop) (a : α) : Det α := - fun _ A B => ∀ x, x ∈ A → owns a x → x ∈ B - -theorem poss_ext {α : Type} (owns : α → α → Prop) (a : α) : - Ext (poss owns a) := by - solution! - intro E E' A B _ _ _ - rfl - -theorem poss_cons {α : Type} (owns : α → α → Prop) (a : α) : - Cons (poss owns a) := by - solution! - intro E A B _ _ - constructor - · intro h x hA ho - exact ⟨hA, h x hA ho⟩ - · intro h x hA ho - exact (h x hA ho).2 - -theorem poss_not_isom : - ¬ Isom (poss (fun _ x => x = true) false) := by - solution! - intro h - have hb : Set.BijOn not Set.univ Set.univ := by - refine ⟨fun _ _ => trivial, ?_, ?_⟩ - · intro x _ y _ hxy - cases x <;> cases y <;> simp_all - · intro y _ - exact ⟨!y, trivial, by simp⟩ - have h1 : poss (fun _ x => x = true) false - Set.univ {false} ∅ := by - intro x hx ho - simp_all - have h2 := h not Set.univ Set.univ {false} ∅ - (Set.subset_univ _) (Set.subset_univ _) hb h1 - obtain ⟨_, hx, _⟩ := h2 true ⟨false, rfl, rfl⟩ rfl - exact hx -``` - -:::: - -```lean -end GQ -``` - -## Árvores numéricas -%%% -tag := "comp-trees" -%%% - -:::terse -- Com EXT, CONS e ISOM, o valor de `Q A B` depende só de dois números: - quantos A não são B ($`m = |A - B|`) e quantos A são B ($`n = |A \cap B|`). - Cada caso possível é um par `(m, n)`. -- Por EXT e CONS, nem o universo nem $`B - A` importam. -- Nesta seção e na seguinte, os exemplos são sempre os mesmos - quantificadores: *all*, *some*, *no* e *not all*; *at least three*, *at - most three* e *exactly three*; *less than half*; e *an even number of*. - Combinando-os, aparece também *at least three but not all*. - -Organizar os pares numa árvore ajuda. Cada linha `row k` reúne os casos em que `A` tem `k` elementos, isto é, os pares com `m + n = k`. Da esquerda para a direita: `m` diminui e `n` aumenta. Na ponta esquerda, nenhum A é B; na direita, todo A é B. -::: - -::::full -Em uma frase como *Todo aluno passou*, o determinante relaciona a restrição `A` -(os alunos) e o escopo `B` (quem passou). EXT, CONS e ISOM juntas garantem que -o valor de `Q A B` depende só de dois números: `m`, quantos A não são B, e -`n`, quantos A são B. Cada condição elimina uma informação. Por CONS, o que -está fora de `A` não importa (quem passou sem ser aluno é irrelevante). Por -EXT, o tamanho do universo não importa. Por ISOM, não importa quem são os -objetos, só quantos são. - -Se só o par `(m, n)` importa, basta listar todos os pares e marcar em quais o -quantificador é verdadeiro. A árvore de números organiza os pares por linha. -A linha `k` reúne os casos com $`|A| = m + n = k`. Da esquerda para a -direita, `n` cresce. Assim, a borda esquerda é "nenhum A é B" e a borda -direita é "todo A é B". Para ler uma posição, tome `(1, 2)` na linha 3: há -três alunos, um não passou e dois passaram. Se o quantificador tem `+` ali, a -frase é verdadeira nessa situação. - -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has -A as a first…" to "…both of these objects have property B.", with Figure 7.5. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Texto gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. -::: -:::: - -```lean -def row (k : Nat) : List (Nat × Nat) := - (List.range (k + 1)).map fun x => (k - x, x) -``` - -:::terse -- A árvore é a lista das suas linhas: `tree k` tem as linhas `0` a `k`. A - árvore não tem fim, mas uma `List` é sempre finita; por isso o limite `k`. -::: - -```lean -def tree (k : Nat) : List (List (Nat × Nat)) := - (List.range (k + 1)).map row - -#eval tree 3 -``` - -:::terse -- Para desenhar a árvore, `labelTree k cell` troca cada par `(m, n)` de - `tree k` pelo texto `cell m n`, e `drawTree w` desenha as linhas de textos, - cada um com largura `w`. -- `numberTree k` é a *árvore de números*: em cada posição, o próprio par. Até - a linha `9`, todo par cabe em três caracteres. -::: - -```lean -def labelTree (k : Nat) (cell : Nat → Nat → String) : - List (List String) := - (tree k).map fun r => r.map fun (m, n) => cell m n - -def drawTree (w : Nat) (rows : List (List String)) : - String := - let last := rows.length - 1 - let lines := rows.mapIdx fun k cells => - let indent := (last - k) * (w + 1) / 2 - String.ofList (List.replicate indent ' ') ++ - String.intercalate " " cells - String.intercalate "\n" lines - -def numberTree (k : Nat) : String := - drawTree 3 (labelTree k fun m n => s!"{m},{n}") - -#eval IO.println <| numberTree 3 -``` - -::::exercise (rating := 1) (name := "tree-of-numbers") -Defina `treeOfNumbers k`, a lista dos pares de `tree k`, percorrida de cima -para baixo e da esquerda para a direita. - -```lean -def treeOfNumbers (k : Nat) : List (Nat × Nat) := - solution!((tree k).flatten) - -theorem treeOfNumbers_three : - treeOfNumbers 3 = - [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), - (3, 0), (2, 1), (1, 2), (0, 3)] := - solution!(by rfl) -``` -:::: - -:::terse -- Um quantificador escolhe alguns pares da árvore: aqueles em que ele é - verdadeiro. Aqui o quantificador é dado direto como uma função de `m` e - `n`. -- Para saber se `q` vale num caso, basta saber se o par foi escolhido. Então - a árvore de pares vira uma árvore de `+` e `-`. A função `patternTree k q` - é o par de `numberTree k`: o mesmo `labelTree`, trocando cada par por `+`, - se `q` vale nele, ou por `-`. Essa árvore é o *padrão* de `q`. -- Três exemplos de padrão: *at least three* ($`n \geq 3`), *less than - half* ($`2n < m + n`) e *an even number of* ($`n` par). -::: - -```lean -def patternTree (k : Nat) (q : Nat → Nat → Bool) : - String := - drawTree 1 (labelTree k fun m n => - if q m n then "+" else "-") -``` - -```lean -#eval IO.println <| patternTree 5 fun _ n => n ≥ 3 -#eval IO.println <| patternTree 5 fun m n => 2 * n < m + n -#eval IO.println <| patternTree 5 fun _ n => n % 2 == 0 -``` - -:::terse -- Um quantificador também pode ser dado como uma função que recebe um - universo (uma lista) e uma propriedade: o tipo `ListQuant`. {lean}`List.all` - e {lean}`List.any` já têm esse tipo, e são *all* e *some*. *No* é - `fun dom p => !dom.any p`: nenhum elemento de `dom` tem `p`. -- Um `ListQuant` é um determinante depois de CONS: o universo é o próprio `A` - e a propriedade é `B`. Pode ser assim porque, por CONS, nada fora de `A` - importa. -::: - -::::full -Alguns padrões. *All* ($`m = 0`) tem `+` só na borda direita, porque nenhum A -fica fora de B. *No* ($`n = 0`) tem `+` só na borda esquerda. *Less than half* -($`n < m`) tem, na linha 2, `+` em `(2, 0)`, `-` em `(1, 1)` e `(0, 2)`. - -O exercício `genTree` liga a árvore ao quantificador dado como uma função de -um universo e uma propriedade. Para cada `(m, n)`, ele monta um -universo concreto `[1, …, m + n]` em que exatamente `n` elementos têm a -propriedade, e pergunta ao quantificador. Qualquer universo -com essas contagens serve (ISOM). - -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "To get used to these representations…" to -the end of Exercise 7.3, without the exercises themselves. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Comentário gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. -::: -:::: - -```lean -abbrev ListQuant := List Nat → (Nat → Bool) → Bool -``` - -::::exercise (rating := 2) (name := "gen-tree") -Defina `genTree q k`, a lista dos pares `(m, n)` de `tree k` para os quais `q` -é verdadeiro num universo de `m + n` objetos dos quais exatamente `n` têm a -propriedade. Por exemplo, `(0, 3)` está na lista de `List.all`, porque se -todos os A são B, os 3 objetos de um A de 3 objetos têm a propriedade B. - -```lean -def genTree (q : ListQuant) (k : Nat) : List (Nat × Nat) := - solution!( - (tree k).flatten.filter fun (m, n) => - q (List.range' 1 (m + n)) (fun x => x ≤ n)) - -theorem genTree_all : - genTree List.all 3 = [(0, 0), (0, 1), (0, 2), (0, 3)] := - solution!(by rfl) - -theorem genTree_any : - genTree List.any 3 = - [(0, 1), (1, 1), (0, 2), (2, 1), (1, 2), (0, 3)] := - solution!(by rfl) - -theorem genTree_no : - genTree (fun dom p => !dom.any p) 3 = - [(0, 0), (1, 0), (2, 0), (3, 0)] := - solution!(by rfl) -``` -:::: - -## Representações lógicas para quantificadores -%%% -tag := "comp-num-repr" -%%% - -:::terse -- O objetivo desta subseção é representar cada quantificador por uma - expressão aritmética em `m` e `n`. Isso é possível porque, com EXT, CONS e - ISOM, o valor de `Q A B` depende só de $`m = |A - B|` e $`n = |A \cap B|`. -- Os padrões de {ref "comp-trees"}[Árvores numéricas] já eram desenhados a - partir de funções de `m` e `n`, como `fun _ n => n ≥ 3`: é o tipo do - argumento de `patternTree`. `NumQuant` dá um nome a esse tipo. Por isso - todo `NumQuant` pode ser desenhado como árvore. -::: - -::::full -Esta subseção tira a conclusão da anterior. Um padrão na árvore é um -subconjunto dos pares de naturais. Por isso, o próprio quantificador pode ser -escrito como uma expressão aritmética em `m` e `n`, sem conjuntos e sem -listas: *all* é $`m = 0`, *no* é $`n = 0`, *at least k* é $`n \geq k` e *at -most k* é $`n \leq k`. Em Lean, essa expressão tem o tipo `NumQuant`, que é -justamente o tipo do argumento de `patternTree`. Por isso todo `NumQuant` pode -ser desenhado. - -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from -"The pairs of cardinals that characterize…" to the definitions of `allNum`, -`noNum`, `atleastNum` and `atmostNum`. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Comentário gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. -::: -:::: - -```lean -abbrev NumQuant := Nat → Nat → Bool - -def allNum : NumQuant := fun m _ => m = 0 -def noNum : NumQuant := fun _ n => n = 0 -def atLeastNum (k : Nat) : NumQuant := fun _ n => n ≥ k -def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k -``` - -:::terse -- Um `ListQuant` também vira um `NumQuant`: na posição `(m, n)`, `toNum q` - aplica `q` a um universo de `m + n` objetos, `[1, …, m + n]`, com uma - propriedade que vale para exatamente `n` deles, "ser no máximo `n`". -- Qualquer universo com essas contagens daria a mesma resposta: é ISOM. -- Assim podemos comparar as duas formas: o padrão de `List.all` é o de - `allNum`, e o de *no* é o de `noNum`. -::: - -```lean -def toNum (q : ListQuant) : NumQuant := - fun m n => q (List.range' 1 (m + n)) (fun x => x ≤ n) - -theorem toNum_all : - patternTree 5 (toNum List.all) = - patternTree 5 allNum := by - rfl - -theorem toNum_no : - patternTree 5 (toNum fun dom p => !dom.any p) = - patternTree 5 noNum := by - rfl -``` - -:::terse -- As operações lógicas sobre quantificadores viram operações sobre essas - expressões. `Not Q` nega a expressão de `Q`. `Q₁ && Q₂` e `Q₁ || Q₂` - combinam as duas expressões. -- Na árvore, a negação troca `+` por `-` em todas as posições. A conjunção - marca com `+` só as posições marcadas nas duas árvores, e a disjunção, as - marcadas em pelo menos uma. -- Um exemplo é *at least three but not all*, que fica `n ≥ 3` e não `m = 0`. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "Logical operations on quantifiers can now be -handled compositionally…" to the definition of `atleast2butnotall`. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Comentário gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. - -O ganho é a composicionalidade. As operações lógicas entre quantificadores -viram operações ponto a ponto nas expressões, e cada uma tem uma leitura na -árvore. *Not Q* troca `+` por `-` em todas as posições. *Q₁ and Q₂* marca -`+` só onde as duas árvores têm `+`. *Q₁ or Q₂* marca `+` onde pelo menos -uma tem. O padrão de *at least three but not all* é o de *at least three* sem a -borda direita. Ninguém precisou pensar em conjuntos: o significado da -expressão composta saiu do significado das partes. - -A subseção seguinte usa essas árvores para perguntas como "se `Q` é -reflexivo, como é o seu padrão?". As árvores transformam propriedades -lógicas dos quantificadores em propriedades geométricas fáceis de ver. -::: -:::: - -```lean -def notNum (q : NumQuant) : NumQuant := - fun m n => !q m n - -def andNum (q₁ q₂ : NumQuant) : NumQuant := - fun m n => q₁ m n && q₂ m n - -def orNum (q₁ q₂ : NumQuant) : NumQuant := - fun m n => q₁ m n || q₂ m n - -def atLeast3ButNotAll : NumQuant := - andNum (atLeastNum 3) (notNum allNum) - -#eval IO.println <| patternTree 5 atLeast3ButNotAll -``` - -::::exercise (rating := 3) (name := "tree-patterns") - -Defina `someNum`, `notAllNum` e `exactlyNum k`, as expressões de *some*, -*not all* e *exactly k*. Use `patternTree` para ver os padrões de *all*, *some*, -*no* e *not all*, e os de *at least three*, *at most three* e *exactly -three*. Depois, prove as relações entre eles: *some* é a negação de *no*, -*not all* é a negação de *all*, *exactly k* é a conjunção de *at least k* e -*at most k*, e *at most k* é a negação de *at least k + 1*. - -Dica: depois de `funext m n`, `rw [Bool.eq_iff_iff]` transforma a igualdade -entre dois `Bool` numa equivalência entre proposições. Em seguida, `simp` -com as definições simplifica a meta, e `omega` resolve o que sobrar de -aritmética. - -```lean -def someNum : NumQuant := - solution!(fun _ n => n > 0) - -def notAllNum : NumQuant := - solution!(fun m _ => m > 0) - -def exactlyNum (k : Nat) : NumQuant := - solution!(fun _ n => n = k) - -theorem someNum_eq : someNum = notNum noNum := by - solution! - funext m n - rw [Bool.eq_iff_iff] - simp [someNum, notNum, noNum] - omega - -theorem notAllNum_eq : notAllNum = notNum allNum := by - solution! - funext m n - rw [Bool.eq_iff_iff] - simp [notAllNum, notNum, allNum] - omega - -theorem exactlyNum_eq (k : Nat) : - exactlyNum k = andNum (atLeastNum k) (atMostNum k) := by - solution! - funext m n - rw [Bool.eq_iff_iff] - simp [exactlyNum, andNum, atLeastNum, atMostNum] - omega - -theorem atMostNum_eq (k : Nat) : - atMostNum k = notNum (atLeastNum (k + 1)) := by - solution! - funext m n - rw [Bool.eq_iff_iff] - simp [atMostNum, notNum, atLeastNum] -``` -:::: - -## Propriedades relacionais -%%% -tag := "comp-rel-props" -%%% - -:::terse -- Quantificadores são relações entre conjuntos, então podemos estudar as - propriedades dessas relações: reflexividade, simetria e monotonicidade. -- Cada propriedade tem dois lados. Nos conjuntos, é uma `Prop` sobre - `GQ.Det`, como EXT, CONS e ISOM. Na árvore, é uma forma do padrão, uma - `Prop` sobre `NumQuant`. -- A pergunta que se repete: se `Q` tem a propriedade, como é o seu padrão? - -Começamos avaliando se {lean}`GQ.all` é reflexiva. O quantificador {lean}`GQ.some` não é reflexivo se aceitarmos a restrição vazia. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "Relational Properties", from "As quantifiers are -relations…" to "…the quantifiers no and not all are not." CSwFP calls *some* -reflexive; with its own definition it is not, because of the empty set (see -`DEVIATIONS.md`). -::: -:::: - -```lean -namespace GQ - -def Refl {α : Type} (D : Det α) : Prop := - ∀ E A, A ⊆ E → D E A A - -theorem all_refl {α : Type} : Refl (all : Det α) := by - intro E A ha x hx - exact hx -``` - -::::exercise (rating := 1) (name := "some-not-refl") -Prove que *some* não é reflexivo. - -```lean -theorem some_not_refl : ¬ Refl (some : Det Entity) := by - solution! - intro h - obtain ⟨x, hx, h2⟩ := h Set.univ ∅ (Set.empty_subset _) - exact hx -``` -:::: - -:::terse -- Em `Q A A`, o escopo é a própria restrição. Nenhum elemento de `A` fica fora - de `A`, então $`m = 0`; todos ficam dentro, então $`n = |A|`. `Q A A` é a - posição `(0, |A|)`. -- Variando o tamanho de `A`, essas posições são `(0, 0)`, `(0, 1)`, - `(0, 2)`, …: a borda direita da árvore. `Q` é reflexivo quando essa borda - é toda `+`. -- A borda inclui o topo, `(0, 0)`, o caso em que `A` é vazio. É ali que - *some* falha. -::: - -```lean -def ReflNum (q : NumQuant) : Prop := - ∀ n, q 0 n - -theorem allNum_refl : ReflNum allNum := by - intro n - rfl - -#eval IO.println <| patternTree 5 allNum -#eval IO.println <| patternTree 5 (notNum noNum) -``` - -::::quiz -Se a borda direita do padrão de `Q` é toda `-`, que propriedade `Q` tem? -Qual quantificador do nosso elenco tem esse padrão? E *no*, tem? - -:::quizSolution -`Q A A` é falso para todo `A`: `Q` é *irreflexivo*. Os padrões de *not all* -e de *no* mostram a borda direita de cada um: - -```lean -#eval IO.println <| patternTree 5 (notNum allNum) -#eval IO.println <| patternTree 5 noNum -``` - -*Not all* é irreflexivo: sua borda direita é toda `-`. *No* não é: o topo, -com `A` vazio, é `+`, porque "nenhum A é A" é verdadeiro. E o resto da borda -é `-`, então *no* não é reflexivo nem irreflexivo. -::: -:::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "One can now study questions about tree -patterns…" to "…which relational property of Q does this reflect?" -::: -:::: - -:::terse -- `Q` é *simétrico* se `Q A B` e `Q B A` sempre têm o mesmo valor. *Some* - é simétrico: "algum A é B" e "algum B é A" dizem a mesma coisa. -- Com um verbo intransitivo no escopo, inverter `A` e `B` leva o verbo para - a restrição: *Alguma menina riu* tem o mesmo valor que *Alguém que riu era - menina*. Já *Toda princesa riu* é verdadeira no modelo, e *Todos os que - riram eram princesas* é falsa: *all* não é simétrico. -- Os quantificadores simétricos são exatamente os que cabem na posição `Q` - de *There are Q*: *There are some dwarfs*, *There are no dragons*, *There - are three wizards*, mas não \**There are all dwarfs* nem \**There are most - dragons*. -::: - -```lean -#eval (a girl laugh, a laugh girl) -#eval (every princess laugh, every laugh princess) -``` - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "A relational property with linguistic -interest is symmetry…" to the end of the paragraph after Exercise 7.4, -"…(sentences of the form There are Q)", without the exercise itself. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Comentário gerado por IA. Material para quem escrever o `full` desta parte, -não uma tradução do CSwFP. - -A simetria fica mais visível com um verbo intransitivo no escopo, porque a -inversão leva o verbo para a restrição, numa oração relativa. *Alguns anões -comemoraram* equivale a *Alguns dos que comemoraram eram anões*, e *Nenhum -anão comemorou* a *Ninguém que comemorou era anão*: os dois lados dependem -só de $`|A \cap B|`, e a interseção não muda quando os conjuntos trocam de -lugar. Com *all*, a inversão muda o sentido: *Todos os anões comemoraram* -deixa que gigantes também tenham comemorado, *Todos os que comemoraram eram -anões* não deixa. - -Além do elenco, *at most k*, *exactly k* e *an even number of* também são -simétricos, porque só dependem de `n`; *the* e *most* não são. Os exemplos -de *There are Q* marcados com `*` são inaceitáveis, e a razão é semântica, a -falta de simetria, não sintática. -::: -:::: - -```lean -def Symm {α : Type} (D : Det α) : Prop := - ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E B A) - -theorem some_symm {α : Type} : Symm (some : Det α) := by - intro E A B _ _ - constructor - · intro h - obtain ⟨x, hA, hB⟩ := h - exact ⟨x, hB, hA⟩ - · intro h - obtain ⟨x, hB, hA⟩ := h - exact ⟨x, hA, hB⟩ -``` - -::::exercise (rating := 2) (name := "symm-pattern") -Defina `SymmNum q`, a forma do padrão de um quantificador simétrico. Depois, -prove que *no* e *at least three* têm essa forma, e que *all* não tem. - -Dica: em `Q A B`, `m` conta os A que não são B; em `Q B A`, conta os B que -não são A. O que muda entre os dois é só `m`. - -```lean -def SymmNum (q : NumQuant) : Prop := - solution!(∀ m m' n, q m n = q m' n) - -theorem noNum_symm : SymmNum noNum := by - solution! - intro m m' n - rfl - -theorem atLeastNum_symm : SymmNum (atLeastNum 3) := by - solution! - intro m m' n - rfl - -theorem allNum_not_symm : ¬ SymmNum allNum := by - solution! - intro h - have h' := h 0 1 0 - simp [allNum] at h' -``` -:::: - -:::terse -- `Q` é *MON↑* (monótono para cima no escopo) se `Q A B` continua - verdadeiro quando `B` cresce. *All*, *some* e *at least three* são MON↑. -- `Q` é *MON↓* se `Q A B` continua verdadeiro quando `B` diminui. *No* e - *not all* são MON↓. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "Another example of a relational property…" -to "…Examples are not all and no.", without Exercises 7.5 and 7.6, which -became the quizzes below. CSwFP's example *at least five* is *at least -three* here, as in the rest of the cast. -::: -:::: - -```lean -def MonUp {α : Type} (D : Det α) : Prop := - ∀ E A B B', A ⊆ E → B ⊆ B' → B' ⊆ E → - D E A B → D E A B' - -def MonDown {α : Type} (D : Det α) : Prop := - ∀ E A B B', A ⊆ E → B' ⊆ B → B ⊆ E → - D E A B → D E A B' - -theorem all_monUp {α : Type} : MonUp (all : Det α) := by - intro E A B B' _ hB _ h x hx - exact hB (h hx) -``` - -::::exercise (rating := 1) (name := "no-mon-down") -Prove que *no* é MON↓. - -```lean -theorem no_monDown {α : Type} : MonDown (no : Det α) := by - solution! - intro E A B B' _ hB _ h x hA hB' - exact h x hA (hB hB') -``` -:::: - -```lean -end GQ -``` - -::::quiz -Compare os padrões de *all* e de *at least three*, que são MON↑. Que forma -tem o padrão de um quantificador MON↑? E o de um MON↓? - -:::quizSolution -Acrescentar a `B` um elemento de `A` tira esse elemento de $`A - B` e o põe -em $`A \cap B`: a posição passa de `(m + 1, n)` para `(m, n + 1)`, uma casa à -direita na mesma linha. Então, num padrão MON↑, à direita de um `+` na mesma -linha só há `+`. Num padrão MON↓, o mesmo vale à esquerda. -::: -:::: - -:::terse -- As duas formas, escritas sobre `NumQuant`: `MonUpNum` e `MonDownNum`. -- *An even number of* não é nem MON↑ nem MON↓: no padrão, `+` e `-` - alternam em cada linha. -::: - -```lean -def MonUpNum (q : NumQuant) : Prop := - ∀ m n, q (m + 1) n → q m (n + 1) - -def MonDownNum (q : NumQuant) : Prop := - ∀ m n, q m (n + 1) → q (m + 1) n - -def evenNum : NumQuant := fun _ n => n % 2 == 0 - -theorem atLeastNum_monUp (k : Nat) : - MonUpNum (atLeastNum k) := by - intro m n h - simp [atLeastNum] at * - omega - -theorem noNum_monDown : MonDownNum noNum := by - intro m n h - simp [noNum] at h -``` - -::::exercise (rating := 2) (name := "even-not-mon") -Prove que *an even number of* não é MON↑ nem MON↓. Basta uma posição do -padrão em que a forma falha. - -```lean -theorem evenNum_not_monUp : ¬ MonUpNum evenNum := by - solution! - intro h - have h' := h 0 0 (by decide) - simp [evenNum] at h' - -theorem evenNum_not_monDown : ¬ MonDownNum evenNum := by - solution! - intro h - have h' := h 0 1 (by decide) - simp [evenNum] at h' -``` -:::: - -:::terse -- A monotonicidade tem uso linguístico. Sintagmas nominais com a mesma - monotonicidade se coordenam com *and*, e com monotonicidades opostas, com - *but*: *all men and some women*, *many English but no Dutch*. -- *Itens de polaridade negativa*, como *any* e *lift a finger*, aparecem no - escopo de sintagmas MON↓: *No dwarf liked any of the elves*, mas não - *Every dwarf liked any of the elves*. Os de polaridade positiva, como - *hardly*, fazem o contrário. -- Pelos padrões, dá para responder como negação, conjunção e disjunção - afetam a monotonicidade. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "An example for a quantifier that satisfies -neither MON↑ nor MON↓…" to "…are in the next exercises.", with examples -(7.10)–(7.15), and the sentence after Exercise 7.10, "The answers to these -questions can be tested…". -::: -:::: - -::::exercise (rating := 2) (name := "mon-not") -Prove que a negação troca MON↑ por MON↓, e MON↓ por MON↑. - -```lean -theorem notNum_monUp (q : NumQuant) (h : MonUpNum q) : - MonDownNum (notNum q) := by - solution! - intro m n hq - simp [notNum] at * - by_cases hq' : q (m + 1) n - · have h' := h m n hq' - simp_all - · simpa using hq' - -theorem notNum_monDown (q : NumQuant) (h : MonDownNum q) : - MonUpNum (notNum q) := by - solution! - intro m n hq - simp [notNum] at * - by_cases hq' : q m (n + 1) - · have h' := h m n hq' - simp_all - · simpa using hq' -``` -:::: - -::::exercise (rating := 2) (name := "mon-and") -Prove que a conjunção de dois quantificadores MON↑ é MON↑, e que a de dois -MON↓ é MON↓. - -```lean -theorem andNum_monUp (q₁ q₂ : NumQuant) - (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : - MonUpNum (andNum q₁ q₂) := by - solution! - intro m n h - simp [andNum] at * - exact ⟨h₁ m n h.1, h₂ m n h.2⟩ - -theorem andNum_monDown (q₁ q₂ : NumQuant) - (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : - MonDownNum (andNum q₁ q₂) := by - solution! - intro m n h - simp [andNum] at * - exact ⟨h₁ m n h.1, h₂ m n h.2⟩ -``` -:::: - -::::exercise (rating := 2) (name := "mon-or") -Prove que a disjunção de dois quantificadores MON↑ é MON↑, e que a de dois -MON↓ é MON↓. - -```lean -theorem orNum_monUp (q₁ q₂ : NumQuant) - (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : - MonUpNum (orNum q₁ q₂) := by - solution! - intro m n h - simp [orNum] at * - cases h with - | inl h => exact Or.inl (h₁ m n h) - | inr h => exact Or.inr (h₂ m n h) - -theorem orNum_monDown (q₁ q₂ : NumQuant) - (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : - MonDownNum (orNum q₁ q₂) := by - solution! - intro m n h - simp [orNum] at * - cases h with - | inl h => exact Or.inl (h₁ m n h) - | inr h => exact Or.inr (h₂ m n h) -``` -:::: - -::::exercise (rating := 3) (name := "mon-up-down") -Mostre que, combinando um quantificador MON↑ com um MON↓, nada se pode -garantir: nem a conjunção nem a disjunção são sempre MON↑ ou MON↓. - -Dica: use *at least one* e *at most three*. Antes de provar, desenhe os -padrões da conjunção e da disjunção com `patternTree`. - -```lean -theorem andNum_up_down : - ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → - MonUpNum (andNum q₁ q₂) ∨ - MonDownNum (andNum q₁ q₂) := by - solution! - intro h - have hup := atLeastNum_monUp 1 - have hdown : MonDownNum (atMostNum 3) := by - intro m n h - simp [atMostNum] at * - omega - cases h _ _ hup hdown with - | inl h => - have h' := h 0 3 (by decide) - simp [andNum, atLeastNum, atMostNum] at h' - | inr h => - have h' := h 0 0 (by decide) - simp [andNum, atLeastNum, atMostNum] at h' - -theorem orNum_up_down : - ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → - MonUpNum (orNum q₁ q₂) ∨ - MonDownNum (orNum q₁ q₂) := by - solution! - intro h - have hup := atLeastNum_monUp 3 - have hdown : MonDownNum (atMostNum 1) := by - intro m n h - simp [atMostNum] at * - omega - cases h _ _ hup hdown with - | inl h => - have h' := h 0 1 (by decide) - simp [orNum, atLeastNum, atMostNum] at h' - | inr h => - have h' := h 0 2 (by decide) - simp [orNum, atLeastNum, atMostNum] at h' -``` -:::: - -:::terse -- A monotonicidade também pode ser na restrição. `Q` é *↑MON* se `Q A B` - continua verdadeiro quando `A` cresce, e *↓MON* se continua verdadeiro - quando `A` diminui. *Some* e *not all* são ↑MON; *all* e *no* são ↓MON. -- Ela explica a polaridade dentro da restrição: *All dwarfs who liked any - of the elves were mistrusted*, mas não *Some dwarfs who liked any of the - elves were mistrusted*. -::: - -::::full -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "One can also study monotonicity in the -first argument…" to example (7.17). -::: -:::: - -::::exercise (rating := 2) (name := "left-mon-pattern") -Defina `UpMonNum q` e `DownMonNum q`, as formas do padrão de um quantificador -↑MON e de um ↓MON. Depois, prove que *some* e *not all* são ↑MON, e que -*all* e *no* são ↓MON. - -Dica: acrescentar um elemento a `A` aumenta `m` ou `n` em um, conforme o -elemento esteja ou não em `B`. - -```lean -def UpMonNum (q : NumQuant) : Prop := - solution!(∀ m n, q m n → q (m + 1) n ∧ q m (n + 1)) - -def DownMonNum (q : NumQuant) : Prop := - solution!( - ∀ m n, (q (m + 1) n → q m n) ∧ (q m (n + 1) → q m n)) - -theorem some_upMon : UpMonNum (notNum noNum) := by - solution! - intro m n h - simp_all [notNum, noNum] - -theorem notAll_upMon : UpMonNum (notNum allNum) := by - solution! - intro m n h - simp [notNum, allNum] at * - omega - -theorem all_downMon : DownMonNum allNum := by - solution! - intro m n - simp [allNum] - -theorem no_downMon : DownMonNum noNum := by - solution! - intro m n - simp [noNum] -``` -:::: - -# A linguagem da lógica tipada e sua semântica -%%% -tag := "comp-typed-logic" -%%% - -:::terse -- A linguagem de tipos da lógica tipada: $`e` para entidades, $`t` para - valores de verdade, e $`\tau_1 \to \tau_2` para funções. -- No nosso modelo, $`e` é `Entity` e $`t` é `Bool`; os tipos de - {ref "comp-relational"}[A visão relacional dos quantificadores] são esses. -::: - -# Redução de expressões da lógica tipada -%%% -tag := "comp-reduction" -%%% - -# Significados tipados para a língua natural -%%% -tag := "comp-typed-meanings" -%%% - -# Implementando a interpretação semântica -%%% -tag := "comp-interpretation" -%%% - -# Tratando a ambiguidade -%%% -tag := "comp-ambiguity" -%%% +{include 1 CSwL.Composition.Interpretation} -```lean -end Composition -``` +{include 1 CSwL.Composition.Ambiguity} diff --git a/CSwL/Composition/Ambiguity.lean b/CSwL/Composition/Ambiguity.lean new file mode 100644 index 0000000..f7fc0b4 --- /dev/null +++ b/CSwL/Composition/Ambiguity.lean @@ -0,0 +1,10 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "Tratando a ambiguidade" => +%%% +tag := "comp-ambiguity" +%%% diff --git a/CSwL/Composition/Interpretation.lean b/CSwL/Composition/Interpretation.lean new file mode 100644 index 0000000..05ae912 --- /dev/null +++ b/CSwL/Composition/Interpretation.lean @@ -0,0 +1,10 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "Implementando a interpretação semântica" => +%%% +tag := "comp-interpretation" +%%% diff --git a/CSwL/Composition/Quantification.lean b/CSwL/Composition/Quantification.lean new file mode 100644 index 0000000..b44bdaa --- /dev/null +++ b/CSwL/Composition/Quantification.lean @@ -0,0 +1,1545 @@ +import CSwLMeta +import Bib +import CSwL.ModelChecking +import Mathlib.Data.Set.Function +import Mathlib.Data.Set.Card + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "Quantificação" => +%%% +tag := "comp-quantification" +%%% + +```lean +namespace Composition + +open ModelChecking +``` + +:::terse +- O objetivo da seção é comparar a visão aristotélica e a visão fregeana dos + quantificadores. A de Frege é muito superior, mas deixa três problemas em + aberto, e o resto do capítulo trata deles. +- A teoria da quantificação de Aristóteles, que vimos em + {ref "InfEngine"}[Um motor de inferência], tem dois defeitos lógicos e uma + falha menor: + 1. ela não trata combinações de quantificadores, pois só admite um + quantificador por sentença; + 2. ela não cobre quantificadores "não padrão", como *most*, *half of* e + *at least five*; + 3. ela supõe a pressuposição existencial. +- Frege remove o primeiro defeito. Os quantificadores ∀ e ∃ ligam variáveis + e se combinam com fórmulas arbitrárias, de modo que uma fórmula pode ter + quantos quantificadores quiser. O segundo defeito continua. +- ∀ e ∃ se definem um pelo outro com a negação: $`\exists x P x` vale se e + somente se $`\neg \forall x \neg P x` vale. +- Os quatro quantificadores do quadrado das oposições se escrevem com ∀ e ∃: + "todo A é B" é $`\forall x (Ax \to Bx)`, "algum A é B" é + $`\exists x (Ax \land Bx)`, e assim por diante. +- Por que "esquecer" a pressuposição existencial: a questão não é o domínio + (em FOL ele é não vazio), mas a extensão de `A`. Se nenhum elemento satisfaz + `A`, então $`\forall x (Ax \to Bx)` é vacuamente verdadeira e + $`\exists x (Ax \land Bx)` é falsa. +- Com `A` vazio, só as diagonais (contraditórias) sobrevivem. Caem as + contrárias ("todo A é B" e "nenhum A é B" ambas verdadeiras), as + subcontrárias e a subalternação. Ex.: *Darapti* não vale em FOL. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from the start to "…in terms of standard +quantifiers and equality." +::: +:::: + +:::terse +- Com a igualdade, a lógica de primeira ordem exprime também quantificadores + numéricos. "Pelo menos dois A são B" é + $`\exists x \exists y (x \neq y \land Ax \land Ay \land Bx \land By)`. +- A fórmula de "pelo menos dois A são B" em Lean é um valor do tipo `LF`, o + mesmo de {ref "ModelChecking"}[Model checking]. Os predicados `a` e `b` são + parâmetros, e a função devolve uma fórmula para cada par de predicados. +- `.neg (.eq tx ty)` é $`x \neq y`. A igualdade já é um construtor de + `Formula` desde {ref "FOL"}[FOL]. +- No modelo do capítulo há três pessoas que riem e só duas meninas que riem. +::: + +```lean +open FOL in +def atLeastTwo (a b : String) : LF := + .exists_ x (.exists_ y (.conjs + [.neg (.eq tx ty), .atom a [tx], .atom a [ty], + .atom b [tx], .atom b [ty]])) + + +def check (f : LF) : Bool := + f.eval entities intFairy ass0 (FOL.liftAssign fintFairy) + +#eval toString <| atLeastTwo "person" "laugh" +#eval check (atLeastTwo "person" "laugh") +``` + +::::exercise (rating := 1) (name := "at-most-two") + +Seguindo o modelo de {name}`atLeastTwo`, defina a fórmula de "no máximo dois +A são B". Dica: se três elementos são A e B, dois deles são iguais. + +```lean +open FOL in +def atMostTwo (a b : String) : LF := + solution!( + .forall_ x (.forall_ y (.forall_ z (.impl + (.conjs [.atom a [tx], .atom a [ty], .atom a [tz], + .atom b [tx], .atom b [ty], .atom b [tz]]) + (.disjs [.eq tx ty, .eq tx tz, .eq ty tz]))))) + +theorem atMostTwo_girl : + check (atMostTwo "girl" "laugh") = true := + solution!(by native_decide) + +theorem atMostTwo_person : + check (atMostTwo "person" "laugh") = false := + solution!(by native_decide) +``` + +:::: + +:::terse +- {name}`atLeastTwo` e `atMostTwo` são funções que *geram* fórmulas. A + função é escrita em Lean, a metalinguagem; o que ela devolve é uma fórmula + de FOL, a linguagem objeto. +- Todas as disjunções e conjunções de quantificadores das formas *pelo menos + n* e *no máximo m* podem ser expressas com os quantificadores padrão e a + igualdade. +- O que a lógica de primeira ordem consegue contar: só números fixos e + finitos, com uma fórmula diferente para cada `n`. +- Não existe uma única fórmula que expresse "pelo menos n" para `n` + arbitrário. Cada fórmula tem um número fixo de quantificadores, e isso + limita até onde ela consegue contar. +- Em Lean, porém, podemos escrever uma única *função* `atLeast n` que, para + cada `n`, gera a fórmula correspondente. As `n` variáveis distintas saem do + índice de `Variable`: `⟨"x", [i]⟩` é a variável `xi`. +::: + +::::exercise (rating := 3) (name := "at-least-n") + +Defina `atLeast n a b`, a fórmula de "pelo menos n A são B", e +`atMost n a b`, a de "no máximo n A são B". Dica: "no máximo n" é a negação +de "pelo menos n + 1". Para `atLeast`, uma função auxiliar recursiva pode +carregar a lista dos termos já quantificados, para exigir que cada nova +variável seja diferente de todos eles. + +```lean +open FOL in +def atLeastFrom (a b : String) (n : Nat) (ts : List Term) : + LF := + solution!( + match n with + | 0 => .top + | n + 1 => + let v : Variable := ⟨"x", [n]⟩ + let t : Term := .var v + .exists_ v (.conjs ([.atom a [t], .atom b [t]] ++ + ts.map (fun s => .neg (.eq s t)) ++ + [atLeastFrom a b n (t :: ts)]))) + +def atLeast (n : Nat) (a b : String) : LF := + solution!(atLeastFrom a b n []) + +def atMost (n : Nat) (a b : String) : LF := + solution!(.neg (atLeast (n + 1) a b)) + +theorem atLeast_person : + check (atLeast 3 "person" "laugh") = true ∧ + check (atLeast 4 "person" "laugh") = false := + solution!(by native_decide) + +theorem atMost_girl : + check (atMost 2 "girl" "laugh") = true ∧ + check (atMost 1 "girl" "laugh") = false := + solution!(by native_decide) +``` +:::: + +:::terse +- *Every prince sang a ballad* ("Todo príncipe cantou uma balada"): na + fórmula, os sintagmas nominais desaparecem. +- *A ballad was sung by every prince* ("Uma balada foi cantada por todo + príncipe"): duas fórmulas, duas leituras. A lógica de primeira ordem + desambigua. +- A visão fregeana deixa três problemas em aberto: + 1. encontrar uma linguagem de representação que preserve os sintagmas + nominais como constituintes; + 2. encontrar um procedimento de tradução da língua natural que não seja + ad hoc; + 3. tratar quantificadores não padrão como *most*, de preferência junto com + os quantificadores padrão. +- O resto desta seção, a partir da visão relacional, responde aos problemas + 1 e 3: *every dwarf* vira uma função, e *most* é uma relação entre + conjuntos como *every*. A lógica tipada e o cálculo lambda, nas próximas + seções, respondem ao problema 2. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To illustrate the claim that first-order +logic has no difficulty…" to "…in a uniform framework with standard +quantifiers." The two paragraphs on the noun phrases of (7.1) and on +"systematically misleading expressions" are cut to a reminder of +`english-form` (see `DEVIATIONS.md`). +::: +:::: + +# A visão relacional dos quantificadores +%%% +tag := "comp-relational" +%%% + +:::terse +- O objetivo da subseção é apresentar a visão relacional dos quantificadores + e mostrar, em dois exemplos, que com ela os sintagmas nominais continuam + sendo constituintes, inclusive quando há dois quantificadores na mesma + sentença. +- Um quantificador é uma relação binária entre subconjuntos de um domínio + $`E` (Mostowski {citep Bib.mostowski1957}[]; Barwise e Cooper + {citep Bib.barwise1981}[]). +- A relação já apareceu em {ref "english-lf"}[FOL como linguagem de + representação]: os dois argumentos de `lfDET` são a restrição e o escopo. + Lá, porém, o determinante construía uma fórmula. Aqui ele relaciona + diretamente dois conjuntos de entidades. +- *Every princess laughed* ("Toda princesa riu"): o determinante é uma função + de duas propriedades, `every : OnePlacePred → OnePlacePred → Bool`. + `every p q` verifica que toda entidade com `p` tem `q`. +- Os tipos acompanham a composição: `every princess : OnePlacePred → Bool`, + e a sentença `every princess laugh : Bool`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "The relational view of quantifiers", from the +start to the table after (7.3). Decide whether the table keeps the types +e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. +::: +:::: + +```lean +def every (p q : OnePlacePred) : Bool := + entities.all (fun x => p x → q x) + +#eval (every princess) laugh +``` + +:::terse +- Lembre de {ref "Sets"}[Conjuntos e Relações]: a função característica de + um conjunto responde, para cada elemento, se ele pertence ao conjunto. + `princess : Entity → Bool` é a função característica do conjunto das + princesas. +- `every princess` aplica a mesma ideia um nível acima. Ele tem tipo + `OnePlacePred → Bool`, logo é a função característica de um conjunto de + *propriedades*: as que toda princesa tem, isto é, as `q` com + $`\textit{princess} \subseteq q`. +- O `#eval` a seguir mostra esse conjunto, restrito a três propriedades. O + resultado é `["laugh"]`: das três propriedades, só "rir" é de toda + princesa. +::: + +```lean (name := everyPrincessEval) +#eval [("laugh", laugh), ("cheer", cheer), + ("shudder", shudder)] + |>.filter (fun (_, q) => every princess q) |>.map (·.1) +``` + +:::terse +- *Every dwarf defeated a giant* ("Todo anão derrotou um gigante"): uma + sentença com dois quantificadores. +- `a p q` verifica que alguma entidade tem `p` e `q`: a interseção dos dois + conjuntos não é vazia. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To see how quantifier combinations…" to the +summary tree, with *Every dwarf defeated a giant* in place of (7.4) (see +`DEVIATIONS.md`). +::: +:::: + +```lean +def a (p q : OnePlacePred) : Bool := + entities.any (fun x => p x ∧ q x) +``` + +:::terse +- Há três nomes para `defeated`, em três níveis: + - `TV.defeated` é a palavra, um construtor da gramática; + - `defeat : Entity → Entity → Bool` é a relação no modelo; + - `defeated`, que definimos agora, é a tradução do verbo. +- Lembre que `OnePlacePred` é uma abreviação (`abbrev`) de `Entity → Bool`, + o tipo das propriedades. O objeto `a giant` tem tipo + `OnePlacePred → Bool`: ele espera uma propriedade. Mas `defeat` tem dois + argumentos e não é uma propriedade. +- O truque é fixar o sujeito `y`. `fun z => defeat y z` é a propriedade "ser + derrotado por `y`", e `X (fun z => defeat y z)` diz que `y` derrotou `X`. + Abstraindo `y`, obtemos uma propriedade do sujeito. +- Por isso `defeated` toma o significado de um sintagma nominal, + `X : OnePlacePred → Bool`, e devolve o de um VP, um `OnePlacePred`. A avaliação da lista as entidades com essa propriedade, as que derrotaram um + gigante: `[B, R]`, que são justamente os dois anões do modelo. +::: + +```lean (name := defeatedEval) +def defeated (X : OnePlacePred → Bool) : OnePlacePred := + fun y => X (fun z => defeat y z) + +#eval entities.filter (defeated (a giant)) +``` + +:::terse +- A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: + a avaliação consulta o modelo diretamente. +- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura + fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. +::: + +```lean +#eval (every dwarf) (defeated (a giant)) +#eval every dwarf (defeated (a giant)) +``` + + +# Condições sobre as relações quantificadoras +%%% +tag := "comp-conditions" +%%% + +::::terse +O objetivo da subseção é dizer quais relações entre conjuntos são +quantificadores. É uma definição, *quantificador* é o nome de uma relação que satisfaz EXT, CONS e ISOM. Uma relação qualquer entre conjuntos pode depender de coisas que um quantificador ignora, e cada uma das três condições exclui um desses casos: + +:::table +header +* + * Condição + * O que garante + * O que exclui +* + * EXT + * O resultado não depende do tamanho do universo $`E`, só de + $`A \cup B`. + * *Many* no sentido de "relativamente muitos", que depende de quantas + coisas existem no total. +* + * CONS + * Nada fora da restrição $`A` importa. + * *Only*: em *Only dwarfs sing during work*, acrescentar não anões que + cantam torna a sentença falsa. +* + * ISOM + * Importa quantos elementos há, e não quais. + * Determinantes que falam de um indivíduo, como o possessivo *Alice's*: + em *Alice's daggers are sharp*, o que importa é quem é o dono, e não + quantas adagas há. +::: + +- EXT e CONS valem para quase todos os determinantes da língua natural. + ISOM separa, entre eles, os que exprimem quantidade. +- Juntas, as três condições reduzem o valor de `D E A B` a dois números, + $`|A - B|` e $`|A \cap B|`. É isso que permite a árvore de números de + {ref "comp-trees"}[Árvores numéricas]. +- Para enunciar as condições, saímos de `Bool` e passamos a `Prop` sobre + `Set`, como em {ref "Sets"}[Conjuntos]: `D E A B` diz que o determinante + `D` relaciona a *restrição* `A` e o *escopo* `B` no universo `E`. +- O tipo `GQ.Det α` é só uma abreviação para `Set α → Set α → Set α → Prop`. + Nada no tipo diz que `A` e `B` estão dentro de `E`. + Essa exigência aparece como as hipóteses `A ⊆ E` e `B ⊆ E` em cada uma das + três condições. +- Não confundir `DET` com `GQ.Det`. `DET` é a categoria sintática de + {ref "ModelChecking"}[Model checking], com as palavras *a*, *the*, + *every*, …. `GQ.Det` é o tipo dos significados dessas palavras. O tipo é + amplo de propósito: todo quantificador é um `GQ.Det`, mas nem todo + `GQ.Det` é um quantificador. +:::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Conditions on Quantifier Relations", from the +start to Figure 7.2. +::: +:::: + +```lean +namespace GQ + +abbrev Det (α : Type) := Set α → Set α → Set α → Prop + +def all {α} : Det α := fun _ A B => A ⊆ B +def some {α} : Det α := fun _ A B => ∃ x, x ∈ A ∧ x ∈ B +def no {α} : Det α := fun _ A B => ∀ x, x ∈ A → x ∉ B +def only {α} : Det α := fun _ A B => B ⊆ A +``` + +:::terse +- {lean}`GQ.all` é a contraparte de {lean}`every` em conjuntos: `every p q` é `true` + exatamente quando o conjunto das entidades com `p` está contido no das + entidades com `q`. +- A prova usa {lean}`mem_entities`: toda entidade está na lista `entities`. +::: + +```lean +theorem every_iff_all (p q : OnePlacePred) : + every p q = true ↔ + all Set.univ {x | p x = true} {x | q x = true} := by + unfold every all + constructor + · intro h x hx + have hx' := List.all_eq_true.mp h x (mem_entities x) + simp_all + · intro h + apply List.all_eq_true.mpr + intro x _ + by_cases hp : p x = true + · have hq : q x = true := h hp + simp [hq] + · simp [hp] +``` + +::::exercise (rating := 2) (name := "subalternation") + +Em {ref "comp-quantification"}[Quantificação] vimos que, sem a pressuposição +existencial, "todo A é B" não implica "algum A é B". Prove as duas coisas: a +subalternação vale quando `A` tem um elemento, e falha em geral. + +```lean +theorem all_imp_some {α : Type} (E A B : Set α) + (hA : ∃ x, x ∈ A) (h : all E A B) : some E A B := by + solution! + obtain ⟨x, hx⟩ := hA + exact ⟨x, hx, h hx⟩ + +theorem all_not_imp_some : + ¬ ∀ (A B : Set Entity), + all Set.univ A B → some Set.univ A B := by + solution! + intro h + obtain ⟨x, hx, _⟩ := h ∅ ∅ (fun _ hx => hx) + exact hx +``` +:::: + +:::terse +- *EXT*: o resultado não muda quando o universo cresce; só importa $`A \cup B`. +- *CONS*: tudo o que está fora da restrição é irrelevante, `D E A B` equivale a + `D E A (A ∩ B)`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Not all two-place relations on sets of +individuals…" to "…A − B and A ∩ B." +::: +:::: + +```lean +def Ext {α : Type} (D : Det α) : Prop := + ∀ E E' A B, A ⊆ E → B ⊆ E → E ⊆ E' → (D E A B ↔ D E' A B) + +def Cons {α : Type} (D : Det α) : Prop := + ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E A (A ∩ B)) +``` + +:::terse +- Para *all* e *some*, as duas condições valem e as provas são curtas. +- As provas de EXT são só `rfl`: as definições começam com `fun _ A B`, isto + é, ignoram o universo `E`, e os dois lados do `↔` são a mesma proposição. +::: + +```lean +theorem all_ext {α : Type} : Ext (all : Det α) := by + intro E E' A B _ _ _ + rfl + +theorem all_cons {α : Type} : Cons (all : Det α) := by + intro E A B _ _ + constructor + · intro h x hx + exact ⟨hx, h hx⟩ + · intro h x hx + exact (h hx).2 + +theorem some_ext {α : Type} : Ext (some : Det α) := by + intro E E' A B _ _ _ + rfl + +theorem some_cons {α : Type} : Cons (some : Det α) := by + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hA, hA, hB⟩ + · intro h + obtain ⟨x, hA, _, hB⟩ := h + exact ⟨x, hA, hB⟩ +``` + +::::exercise (rating := 2) (name := "no-cons") +Prove que *no* é conservativo. + +```lean +theorem no_cons {α : Type} : Cons (no : Det α) := by + solution! + intro E A B _ _ + constructor + · intro h x hA hAB + exact h x hA hAB.2 + · intro h x hA hB + exact h x hA ⟨hA, hB⟩ +``` +:::: + +:::terse +- *Many*, no sentido de "relativamente muitos", não satisfaz EXT. Uma versão + simples: "muitos A são B" quando os A que são B são mais da metade do + universo `E`. Com um universo maior, a mesma sentença pode ficar falsa. +- `Set.ncard` é o número de elementos de um conjunto finito, a $`|A|` da + notação matemática. Ela vem de `Mathlib.Data.Set.Card`. +::: + +```lean +def many {α : Type} : Det α := + fun E A B => E.ncard < 2 * (A ∩ B).ncard +``` + +::::exercise (rating := 2) (name := "many-not-ext") +Prove que `many` não satisfaz EXT. Basta um universo `E` em que a relação +vale e um universo maior `E'` em que ela deixa de valer. + +```lean +theorem many_not_ext : ¬ Ext (many : Det Nat) := by + solution! + intro h + have h1 : (many : Det Nat) {0} {0} {0} := by + simp [many] + have h2 := (h {0} {0, 1} {0} {0} le_rfl le_rfl + (by simp)).1 h1 + simp [many] at h1 h2 +``` +:::: + +:::terse +*Only*, como em *Only dwarfs sing during work*, não é conservativo. +::: + +::::exercise (rating := 2) (name := "only-not-cons") +Prove que *only* não é conservativo. Basta escolher uma restrição e um escopo +para os quais as duas leituras da definição de `Cons` dão resultados +diferentes. + +```lean +theorem only_not_cons : ¬ Cons (only : Det Entity) := by + solution! + intro h + have hcons : + (only : Det Entity) Set.univ ∅ (∅ ∩ Set.univ) := by + intro x hx + exact hx.1 + have hS : Entity.S ∈ (∅ : Set Entity) := + (h Set.univ ∅ Set.univ (Set.empty_subset _) + (Set.subset_univ _)).2 hcons (Set.mem_univ Entity.S) + exact hS +``` +:::: + +:::terse +- *ISOM*: só importam as quantidades. Se `f` leva `E` bijetivamente em `E'`, + então `D E A B` implica `D E' (f '' A) (f '' B)`. +- `f '' A` é a imagem de `A` por `f`, o conjunto dos `f x` com `x ∈ A`. + `Set.BijOn f E E'` diz que `f` é uma bijeção de `E` em `E'`. +- Um quantificador é uma relação que satisfaz EXT, CONS e ISOM. O valor de + `D E A B` depende então só de $`|A - B|` e $`|A \cap B|`. +- Os artigos também são quantificadores no sentido técnico desta seção. *a* + tem o mesmo significado que *some*: vale quando $`|A \cap B| \geq 1`. *the*, + na leitura russelliana de {ref "ModelChecking"}[Model checking], vale + quando $`|A \cap B| = 1` e $`|A - B| = 0`. A gramática tradicional, porém, + não vê *the* como expressão de quantidade, e sim como um modo de identificar + um referente. Quantificador, aqui, é uma propriedade semântica; determinante + é uma categoria sintática. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Next, the relational perspective +suggests…" to "…the logical representation of quantifiers." +::: +:::: + +```lean +def Isom {α : Type} (D : Det α) : Prop := + ∀ (f : α → α) E E' A B, A ⊆ E → B ⊆ E → + Set.BijOn f E E' → D E A B → D E' (f '' A) (f '' B) + +theorem all_isom {α : Type} : Isom (all : Det α) := by + intro f E E' A B _ _ _ h + exact Set.image_mono h + +theorem some_isom {α : Type} : Isom (some : Det α) := by + intro f E E' A B _ _ _ h + obtain ⟨x, hA, hB⟩ := h + exact ⟨f x, ⟨x, hA, rfl⟩, ⟨x, hB, rfl⟩⟩ +``` + +::::exercise (rating := 2) (name := "the-quant") + +Na leitura de {ref "ModelChecking"}[Model checking], *The dwarf laughed* +diz que há exatamente um anão e que ele riu. Como relação entre conjuntos, +`the E A B` diz que `A` tem um único elemento e que ele está em `B`. Mostre +que `the` satisfaz EXT, CONS e ISOM. Assim, o artigo *the* é, no sentido +técnico desta seção, um quantificador. + +```lean +def the {α : Type} : Det α := + fun _ A B => ∃ x, A = {x} ∧ x ∈ B + +theorem the_ext {α : Type} : Ext (the : Det α) := by + solution! + intro E E' A B _ _ _ + rfl + +theorem the_cons {α : Type} : Cons (the : Det α) := by + solution! + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hA, by rw [hA]; rfl, hB⟩ + · intro h + obtain ⟨x, hA, _, hB⟩ := h + exact ⟨x, hA, hB⟩ + +theorem the_isom {α : Type} : Isom (the : Det α) := by + solution! + intro f E E' A B _ _ _ h + obtain ⟨x, hA, hB⟩ := h + refine ⟨f x, ?_, ⟨x, hB, rfl⟩⟩ + rw [hA, Set.image_singleton] +``` + +:::: + +::::exercise (rating := 3) (name := "poss-not-isom") + +O possessivo *Alice's*, como em *Alice's daggers are sharp*, ocupa a posição +de um determinante: `poss owns a A B` diz que todo `A` que `a` possui é `B`. +A relação de posse `owns` é um parâmetro. Mostre que `poss` satisfaz EXT e +CONS, mas não ISOM. Assim, as três condições são independentes: EXT e CONS +não bastam para fazer de um determinante um quantificador. + +Dica: para ISOM, basta um exemplo pequeno em `Bool`, em que `false` possui +só `true`, e a bijeção `not`. + +```lean +def poss {α : Type} (owns : α → α → Prop) (a : α) : Det α := + fun _ A B => ∀ x, x ∈ A → owns a x → x ∈ B + +theorem poss_ext {α : Type} (owns : α → α → Prop) (a : α) : + Ext (poss owns a) := by + solution! + intro E E' A B _ _ _ + rfl + +theorem poss_cons {α : Type} (owns : α → α → Prop) (a : α) : + Cons (poss owns a) := by + solution! + intro E A B _ _ + constructor + · intro h x hA ho + exact ⟨hA, h x hA ho⟩ + · intro h x hA ho + exact (h x hA ho).2 + +theorem poss_not_isom : + ¬ Isom (poss (fun _ x => x = true) false) := by + solution! + intro h + have hb : Set.BijOn not Set.univ Set.univ := by + refine ⟨fun _ _ => trivial, ?_, ?_⟩ + · intro x _ y _ hxy + cases x <;> cases y <;> simp_all + · intro y _ + exact ⟨!y, trivial, by simp⟩ + have h1 : poss (fun _ x => x = true) false + Set.univ {false} ∅ := by + intro x hx ho + simp_all + have h2 := h not Set.univ Set.univ {false} ∅ + (Set.subset_univ _) (Set.subset_univ _) hb h1 + obtain ⟨_, hx, _⟩ := h2 true ⟨false, rfl, rfl⟩ rfl + exact hx +``` + +:::: + +```lean +end GQ +``` + +# Árvores numéricas +%%% +tag := "comp-trees" +%%% + +:::terse +- Com EXT, CONS e ISOM, o valor de `Q A B` depende só de dois números: + quantos A não são B ($`m = |A - B|`) e quantos A são B ($`n = |A \cap B|`). + Cada caso possível é um par `(m, n)`. +- Por EXT e CONS, nem o universo nem $`B - A` importam. +- Nesta seção e na seguinte, os exemplos são sempre os mesmos + quantificadores: *all*, *some*, *no* e *not all*; *at least three*, *at + most three* e *exactly three*; *less than half*; e *an even number of*. + Combinando-os, aparece também *at least three but not all*. + +Organizar os pares numa árvore ajuda. Cada linha `row k` reúne os casos em que `A` tem `k` elementos, isto é, os pares com `m + n = k`. Da esquerda para a direita: `m` diminui e `n` aumenta. Na ponta esquerda, nenhum A é B; na direita, todo A é B. +::: + +::::full +Em uma frase como *Todo aluno passou*, o determinante relaciona a restrição `A` +(os alunos) e o escopo `B` (quem passou). EXT, CONS e ISOM juntas garantem que +o valor de `Q A B` depende só de dois números: `m`, quantos A não são B, e +`n`, quantos A são B. Cada condição elimina uma informação. Por CONS, o que +está fora de `A` não importa (quem passou sem ser aluno é irrelevante). Por +EXT, o tamanho do universo não importa. Por ISOM, não importa quem são os +objetos, só quantos são. + +Se só o par `(m, n)` importa, basta listar todos os pares e marcar em quais o +quantificador é verdadeiro. A árvore de números organiza os pares por linha. +A linha `k` reúne os casos com $`|A| = m + n = k`. Da esquerda para a +direita, `n` cresce. Assim, a borda esquerda é "nenhum A é B" e a borda +direita é "todo A é B". Para ler uma posição, tome `(1, 2)` na linha 3: há +três alunos, um não passou e dois passaram. Se o quantificador tem `+` ali, a +frase é verdadeira nessa situação. + +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has +A as a first…" to "…both of these objects have property B.", with Figure 7.5. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Texto gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: +:::: + +```lean +def row (k : Nat) : List (Nat × Nat) := + (List.range (k + 1)).map fun x => (k - x, x) +``` + +:::terse +- A árvore é a lista das suas linhas: `tree k` tem as linhas `0` a `k`. A + árvore não tem fim, mas uma `List` é sempre finita; por isso o limite `k`. +::: + +```lean +def tree (k : Nat) : List (List (Nat × Nat)) := + (List.range (k + 1)).map row + +#eval tree 3 +``` + +:::terse +- Para desenhar a árvore, `labelTree k cell` troca cada par `(m, n)` de + `tree k` pelo texto `cell m n`, e `drawTree w` desenha as linhas de textos, + cada um com largura `w`. +- `numberTree k` é a *árvore de números*: em cada posição, o próprio par. Até + a linha `9`, todo par cabe em três caracteres. +::: + +```lean +def labelTree (k : Nat) (cell : Nat → Nat → String) : + List (List String) := + (tree k).map fun r => r.map fun (m, n) => cell m n + +def drawTree (w : Nat) (rows : List (List String)) : + String := + let last := rows.length - 1 + let lines := rows.mapIdx fun k cells => + let indent := (last - k) * (w + 1) / 2 + String.ofList (List.replicate indent ' ') ++ + String.intercalate " " cells + String.intercalate "\n" lines + +def numberTree (k : Nat) : String := + drawTree 3 (labelTree k fun m n => s!"{m},{n}") + +#eval IO.println <| numberTree 3 +``` + +::::exercise (rating := 1) (name := "tree-of-numbers") +Defina `treeOfNumbers k`, a lista dos pares de `tree k`, percorrida de cima +para baixo e da esquerda para a direita. + +```lean +def treeOfNumbers (k : Nat) : List (Nat × Nat) := + solution!((tree k).flatten) + +theorem treeOfNumbers_three : + treeOfNumbers 3 = + [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), + (3, 0), (2, 1), (1, 2), (0, 3)] := + solution!(by rfl) +``` +:::: + +:::terse +- Um quantificador escolhe alguns pares da árvore: aqueles em que ele é + verdadeiro. Aqui o quantificador é dado direto como uma função de `m` e + `n`. +- Para saber se `q` vale num caso, basta saber se o par foi escolhido. Então + a árvore de pares vira uma árvore de `+` e `-`. A função `patternTree k q` + é o par de `numberTree k`: o mesmo `labelTree`, trocando cada par por `+`, + se `q` vale nele, ou por `-`. Essa árvore é o *padrão* de `q`. +- Três exemplos de padrão: *at least three* ($`n \geq 3`), *less than + half* ($`2n < m + n`) e *an even number of* ($`n` par). +::: + +```lean +def patternTree (k : Nat) (q : Nat → Nat → Bool) : + String := + drawTree 1 (labelTree k fun m n => + if q m n then "+" else "-") +``` + +```lean +#eval IO.println <| patternTree 5 fun _ n => n ≥ 3 +#eval IO.println <| patternTree 5 fun m n => 2 * n < m + n +#eval IO.println <| patternTree 5 fun _ n => n % 2 == 0 +``` + +:::terse +- Um quantificador também pode ser dado como uma função que recebe um + universo (uma lista) e uma propriedade: o tipo `ListQuant`. {lean}`List.all` + e {lean}`List.any` já têm esse tipo, e são *all* e *some*. *No* é + `fun dom p => !dom.any p`: nenhum elemento de `dom` tem `p`. +- Um `ListQuant` é um determinante depois de CONS: o universo é o próprio `A` + e a propriedade é `B`. Pode ser assim porque, por CONS, nada fora de `A` + importa. +::: + +::::full +Alguns padrões. *All* ($`m = 0`) tem `+` só na borda direita, porque nenhum A +fica fora de B. *No* ($`n = 0`) tem `+` só na borda esquerda. *Less than half* +($`n < m`) tem, na linha 2, `+` em `(2, 0)`, `-` em `(1, 1)` e `(0, 2)`. + +O exercício `genTree` liga a árvore ao quantificador dado como uma função de +um universo e uma propriedade. Para cada `(m, n)`, ele monta um +universo concreto `[1, …, m + n]` em que exatamente `n` elementos têm a +propriedade, e pergunta ao quantificador. Qualquer universo +com essas contagens serve (ISOM). + +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To get used to these representations…" to +the end of Exercise 7.3, without the exercises themselves. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: +:::: + +```lean +abbrev ListQuant := List Nat → (Nat → Bool) → Bool +``` + +::::exercise (rating := 2) (name := "gen-tree") +Defina `genTree q k`, a lista dos pares `(m, n)` de `tree k` para os quais `q` +é verdadeiro num universo de `m + n` objetos dos quais exatamente `n` têm a +propriedade. Por exemplo, `(0, 3)` está na lista de `List.all`, porque se +todos os A são B, os 3 objetos de um A de 3 objetos têm a propriedade B. + +```lean +def genTree (q : ListQuant) (k : Nat) : List (Nat × Nat) := + solution!( + (tree k).flatten.filter fun (m, n) => + q (List.range' 1 (m + n)) (fun x => x ≤ n)) + +theorem genTree_all : + genTree List.all 3 = [(0, 0), (0, 1), (0, 2), (0, 3)] := + solution!(by rfl) + +theorem genTree_any : + genTree List.any 3 = + [(0, 1), (1, 1), (0, 2), (2, 1), (1, 2), (0, 3)] := + solution!(by rfl) + +theorem genTree_no : + genTree (fun dom p => !dom.any p) 3 = + [(0, 0), (1, 0), (2, 0), (3, 0)] := + solution!(by rfl) +``` +:::: + +# Representações lógicas para quantificadores +%%% +tag := "comp-num-repr" +%%% + +:::terse +- O objetivo desta subseção é representar cada quantificador por uma + expressão aritmética em `m` e `n`. Isso é possível porque, com EXT, CONS e + ISOM, o valor de `Q A B` depende só de $`m = |A - B|` e $`n = |A \cap B|`. +- Os padrões de {ref "comp-trees"}[Árvores numéricas] já eram desenhados a + partir de funções de `m` e `n`, como `fun _ n => n ≥ 3`: é o tipo do + argumento de `patternTree`. `NumQuant` dá um nome a esse tipo. Por isso + todo `NumQuant` pode ser desenhado como árvore. +::: + +::::full +Esta subseção tira a conclusão da anterior. Um padrão na árvore é um +subconjunto dos pares de naturais. Por isso, o próprio quantificador pode ser +escrito como uma expressão aritmética em `m` e `n`, sem conjuntos e sem +listas: *all* é $`m = 0`, *no* é $`n = 0`, *at least k* é $`n \geq k` e *at +most k* é $`n \leq k`. Em Lean, essa expressão tem o tipo `NumQuant`, que é +justamente o tipo do argumento de `patternTree`. Por isso todo `NumQuant` pode +ser desenhado. + +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from +"The pairs of cardinals that characterize…" to the definitions of `allNum`, +`noNum`, `atleastNum` and `atmostNum`. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. +::: +:::: + +```lean +abbrev NumQuant := Nat → Nat → Bool + +def allNum : NumQuant := fun m _ => m = 0 +def noNum : NumQuant := fun _ n => n = 0 +def atLeastNum (k : Nat) : NumQuant := fun _ n => n ≥ k +def atMostNum (k : Nat) : NumQuant := fun _ n => n ≤ k +``` + +:::terse +- Um `ListQuant` também vira um `NumQuant`: na posição `(m, n)`, `toNum q` + aplica `q` a um universo de `m + n` objetos, `[1, …, m + n]`, com uma + propriedade que vale para exatamente `n` deles, "ser no máximo `n`". +- Qualquer universo com essas contagens daria a mesma resposta: é ISOM. +- Assim podemos comparar as duas formas: o padrão de `List.all` é o de + `allNum`, e o de *no* é o de `noNum`. +::: + +```lean +def toNum (q : ListQuant) : NumQuant := + fun m n => q (List.range' 1 (m + n)) (fun x => x ≤ n) + +theorem toNum_all : + patternTree 5 (toNum List.all) = + patternTree 5 allNum := by + rfl + +theorem toNum_no : + patternTree 5 (toNum fun dom p => !dom.any p) = + patternTree 5 noNum := by + rfl +``` + +:::terse +- As operações lógicas sobre quantificadores viram operações sobre essas + expressões. `Not Q` nega a expressão de `Q`. `Q₁ && Q₂` e `Q₁ || Q₂` + combinam as duas expressões. +- Na árvore, a negação troca `+` por `-` em todas as posições. A conjunção + marca com `+` só as posições marcadas nas duas árvores, e a disjunção, as + marcadas em pelo menos uma. +- Um exemplo é *at least three but not all*, que fica `n ≥ 3` e não `m = 0`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Logical operations on quantifiers can now be +handled compositionally…" to the definition of `atleast2butnotall`. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. + +O ganho é a composicionalidade. As operações lógicas entre quantificadores +viram operações ponto a ponto nas expressões, e cada uma tem uma leitura na +árvore. *Not Q* troca `+` por `-` em todas as posições. *Q₁ and Q₂* marca +`+` só onde as duas árvores têm `+`. *Q₁ or Q₂* marca `+` onde pelo menos +uma tem. O padrão de *at least three but not all* é o de *at least three* sem a +borda direita. Ninguém precisou pensar em conjuntos: o significado da +expressão composta saiu do significado das partes. + +A subseção seguinte usa essas árvores para perguntas como "se `Q` é +reflexivo, como é o seu padrão?". As árvores transformam propriedades +lógicas dos quantificadores em propriedades geométricas fáceis de ver. +::: +:::: + +```lean +def notNum (q : NumQuant) : NumQuant := + fun m n => !q m n + +def andNum (q₁ q₂ : NumQuant) : NumQuant := + fun m n => q₁ m n && q₂ m n + +def orNum (q₁ q₂ : NumQuant) : NumQuant := + fun m n => q₁ m n || q₂ m n + +def atLeast3ButNotAll : NumQuant := + andNum (atLeastNum 3) (notNum allNum) + +#eval IO.println <| patternTree 5 atLeast3ButNotAll +``` + +::::exercise (rating := 3) (name := "tree-patterns") + +Defina `someNum`, `notAllNum` e `exactlyNum k`, as expressões de *some*, +*not all* e *exactly k*. Use `patternTree` para ver os padrões de *all*, *some*, +*no* e *not all*, e os de *at least three*, *at most three* e *exactly +three*. Depois, prove as relações entre eles: *some* é a negação de *no*, +*not all* é a negação de *all*, *exactly k* é a conjunção de *at least k* e +*at most k*, e *at most k* é a negação de *at least k + 1*. + +Dica: depois de `funext m n`, `rw [Bool.eq_iff_iff]` transforma a igualdade +entre dois `Bool` numa equivalência entre proposições. Em seguida, `simp` +com as definições simplifica a meta, e `omega` resolve o que sobrar de +aritmética. + +```lean +def someNum : NumQuant := + solution!(fun _ n => n > 0) + +def notAllNum : NumQuant := + solution!(fun m _ => m > 0) + +def exactlyNum (k : Nat) : NumQuant := + solution!(fun _ n => n = k) + +theorem someNum_eq : someNum = notNum noNum := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [someNum, notNum, noNum] + omega + +theorem notAllNum_eq : notAllNum = notNum allNum := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [notAllNum, notNum, allNum] + omega + +theorem exactlyNum_eq (k : Nat) : + exactlyNum k = andNum (atLeastNum k) (atMostNum k) := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [exactlyNum, andNum, atLeastNum, atMostNum] + omega + +theorem atMostNum_eq (k : Nat) : + atMostNum k = notNum (atLeastNum (k + 1)) := by + solution! + funext m n + rw [Bool.eq_iff_iff] + simp [atMostNum, notNum, atLeastNum] +``` +:::: + +# Propriedades relacionais +%%% +tag := "comp-rel-props" +%%% + +:::terse +- Quantificadores são relações entre conjuntos, então podemos estudar as + propriedades dessas relações: reflexividade, simetria e monotonicidade. +- Cada propriedade tem dois lados. Nos conjuntos, é uma `Prop` sobre + `GQ.Det`, como EXT, CONS e ISOM. Na árvore, é uma forma do padrão, uma + `Prop` sobre `NumQuant`. +- A pergunta que se repete: se `Q` tem a propriedade, como é o seu padrão? + +Começamos avaliando se {lean}`GQ.all` é reflexiva. O quantificador {lean}`GQ.some` não é reflexivo se aceitarmos a restrição vazia. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Relational Properties", from "As quantifiers are +relations…" to "…the quantifiers no and not all are not." CSwFP calls *some* +reflexive; with its own definition it is not, because of the empty set (see +`DEVIATIONS.md`). +::: +:::: + +```lean +namespace GQ + +def Refl {α : Type} (D : Det α) : Prop := + ∀ E A, A ⊆ E → D E A A + +theorem all_refl {α : Type} : Refl (all : Det α) := by + intro E A ha x hx + exact hx +``` + +::::exercise (rating := 1) (name := "some-not-refl") +Prove que *some* não é reflexivo. + +```lean +theorem some_not_refl : ¬ Refl (some : Det Entity) := by + solution! + intro h + obtain ⟨x, hx, h2⟩ := h Set.univ ∅ (Set.empty_subset _) + exact hx +``` +:::: + +:::terse +- Em `Q A A`, o escopo é a própria restrição. Nenhum elemento de `A` fica fora + de `A`, então $`m = 0`; todos ficam dentro, então $`n = |A|`. `Q A A` é a + posição `(0, |A|)`. +- Variando o tamanho de `A`, essas posições são `(0, 0)`, `(0, 1)`, + `(0, 2)`, …: a borda direita da árvore. `Q` é reflexivo quando essa borda + é toda `+`. +- A borda inclui o topo, `(0, 0)`, o caso em que `A` é vazio. É ali que + *some* falha. +::: + +```lean +def ReflNum (q : NumQuant) : Prop := + ∀ n, q 0 n + +theorem allNum_refl : ReflNum allNum := by + intro n + rfl + +#eval IO.println <| patternTree 5 allNum +#eval IO.println <| patternTree 5 (notNum noNum) +``` + +::::quiz +Se a borda direita do padrão de `Q` é toda `-`, que propriedade `Q` tem? +Qual quantificador do nosso elenco tem esse padrão? E *no*, tem? + +:::quizSolution +`Q A A` é falso para todo `A`: `Q` é *irreflexivo*. Os padrões de *not all* +e de *no* mostram a borda direita de cada um: + +```lean +#eval IO.println <| patternTree 5 (notNum allNum) +#eval IO.println <| patternTree 5 noNum +``` + +*Not all* é irreflexivo: sua borda direita é toda `-`. *No* não é: o topo, +com `A` vazio, é `+`, porque "nenhum A é A" é verdadeiro. E o resto da borda +é `-`, então *no* não é reflexivo nem irreflexivo. +::: +:::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "One can now study questions about tree +patterns…" to "…which relational property of Q does this reflect?" +::: +:::: + +:::terse +- `Q` é *simétrico* se `Q A B` e `Q B A` sempre têm o mesmo valor. *Some* + é simétrico: "algum A é B" e "algum B é A" dizem a mesma coisa. +- Com um verbo intransitivo no escopo, inverter `A` e `B` leva o verbo para + a restrição: *Alguma menina riu* tem o mesmo valor que *Alguém que riu era + menina*. Já *Toda princesa riu* é verdadeira no modelo, e *Todos os que + riram eram princesas* é falsa: *all* não é simétrico. +- Os quantificadores simétricos são exatamente os que cabem na posição `Q` + de *There are Q*: *There are some dwarfs*, *There are no dragons*, *There + are three wizards*, mas não \**There are all dwarfs* nem \**There are most + dragons*. +::: + +```lean +#eval (a girl laugh, a laugh girl) +#eval (every princess laugh, every laugh princess) +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "A relational property with linguistic +interest is symmetry…" to the end of the paragraph after Exercise 7.4, +"…(sentences of the form There are Q)", without the exercise itself. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. Material para quem escrever o `full` desta parte, +não uma tradução do CSwFP. + +A simetria fica mais visível com um verbo intransitivo no escopo, porque a +inversão leva o verbo para a restrição, numa oração relativa. *Alguns anões +comemoraram* equivale a *Alguns dos que comemoraram eram anões*, e *Nenhum +anão comemorou* a *Ninguém que comemorou era anão*: os dois lados dependem +só de $`|A \cap B|`, e a interseção não muda quando os conjuntos trocam de +lugar. Com *all*, a inversão muda o sentido: *Todos os anões comemoraram* +deixa que gigantes também tenham comemorado, *Todos os que comemoraram eram +anões* não deixa. + +Além do elenco, *at most k*, *exactly k* e *an even number of* também são +simétricos, porque só dependem de `n`; *the* e *most* não são. Os exemplos +de *There are Q* marcados com `*` são inaceitáveis, e a razão é semântica, a +falta de simetria, não sintática. +::: +:::: + +```lean +def Symm {α : Type} (D : Det α) : Prop := + ∀ E A B, A ⊆ E → B ⊆ E → (D E A B ↔ D E B A) + +theorem some_symm {α : Type} : Symm (some : Det α) := by + intro E A B _ _ + constructor + · intro h + obtain ⟨x, hA, hB⟩ := h + exact ⟨x, hB, hA⟩ + · intro h + obtain ⟨x, hB, hA⟩ := h + exact ⟨x, hA, hB⟩ +``` + +::::exercise (rating := 2) (name := "symm-pattern") +Defina `SymmNum q`, a forma do padrão de um quantificador simétrico. Depois, +prove que *no* e *at least three* têm essa forma, e que *all* não tem. + +Dica: em `Q A B`, `m` conta os A que não são B; em `Q B A`, conta os B que +não são A. O que muda entre os dois é só `m`. + +```lean +def SymmNum (q : NumQuant) : Prop := + solution!(∀ m m' n, q m n = q m' n) + +theorem noNum_symm : SymmNum noNum := by + solution! + intro m m' n + rfl + +theorem atLeastNum_symm : SymmNum (atLeastNum 3) := by + solution! + intro m m' n + rfl + +theorem allNum_not_symm : ¬ SymmNum allNum := by + solution! + intro h + have h' := h 0 1 0 + simp [allNum] at h' +``` +:::: + +:::terse +- `Q` é *MON↑* (monótono para cima no escopo) se `Q A B` continua + verdadeiro quando `B` cresce. *All*, *some* e *at least three* são MON↑. +- `Q` é *MON↓* se `Q A B` continua verdadeiro quando `B` diminui. *No* e + *not all* são MON↓. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Another example of a relational property…" +to "…Examples are not all and no.", without Exercises 7.5 and 7.6, which +became the quizzes below. CSwFP's example *at least five* is *at least +three* here, as in the rest of the cast. +::: +:::: + +```lean +def MonUp {α : Type} (D : Det α) : Prop := + ∀ E A B B', A ⊆ E → B ⊆ B' → B' ⊆ E → + D E A B → D E A B' + +def MonDown {α : Type} (D : Det α) : Prop := + ∀ E A B B', A ⊆ E → B' ⊆ B → B ⊆ E → + D E A B → D E A B' + +theorem all_monUp {α : Type} : MonUp (all : Det α) := by + intro E A B B' _ hB _ h x hx + exact hB (h hx) +``` + +::::exercise (rating := 1) (name := "no-mon-down") +Prove que *no* é MON↓. + +```lean +theorem no_monDown {α : Type} : MonDown (no : Det α) := by + solution! + intro E A B B' _ hB _ h x hA hB' + exact h x hA (hB hB') +``` +:::: + +```lean +end GQ +``` + +::::quiz +Compare os padrões de *all* e de *at least three*, que são MON↑. Que forma +tem o padrão de um quantificador MON↑? E o de um MON↓? + +:::quizSolution +Acrescentar a `B` um elemento de `A` tira esse elemento de $`A - B` e o põe +em $`A \cap B`: a posição passa de `(m + 1, n)` para `(m, n + 1)`, uma casa à +direita na mesma linha. Então, num padrão MON↑, à direita de um `+` na mesma +linha só há `+`. Num padrão MON↓, o mesmo vale à esquerda. +::: +:::: + +:::terse +- As duas formas, escritas sobre `NumQuant`: `MonUpNum` e `MonDownNum`. +- *An even number of* não é nem MON↑ nem MON↓: no padrão, `+` e `-` + alternam em cada linha. +::: + +```lean +def MonUpNum (q : NumQuant) : Prop := + ∀ m n, q (m + 1) n → q m (n + 1) + +def MonDownNum (q : NumQuant) : Prop := + ∀ m n, q m (n + 1) → q (m + 1) n + +def evenNum : NumQuant := fun _ n => n % 2 == 0 + +theorem atLeastNum_monUp (k : Nat) : + MonUpNum (atLeastNum k) := by + intro m n h + simp [atLeastNum] at * + omega + +theorem noNum_monDown : MonDownNum noNum := by + intro m n h + simp [noNum] at h +``` + +::::exercise (rating := 2) (name := "even-not-mon") +Prove que *an even number of* não é MON↑ nem MON↓. Basta uma posição do +padrão em que a forma falha. + +```lean +theorem evenNum_not_monUp : ¬ MonUpNum evenNum := by + solution! + intro h + have h' := h 0 0 (by decide) + simp [evenNum] at h' + +theorem evenNum_not_monDown : ¬ MonDownNum evenNum := by + solution! + intro h + have h' := h 0 1 (by decide) + simp [evenNum] at h' +``` +:::: + +:::terse +- A monotonicidade tem uso linguístico. Sintagmas nominais com a mesma + monotonicidade se coordenam com *and*, e com monotonicidades opostas, com + *but*: *all men and some women*, *many English but no Dutch*. +- *Itens de polaridade negativa*, como *any* e *lift a finger*, aparecem no + escopo de sintagmas MON↓: *No dwarf liked any of the elves*, mas não + *Every dwarf liked any of the elves*. Os de polaridade positiva, como + *hardly*, fazem o contrário. +- Pelos padrões, dá para responder como negação, conjunção e disjunção + afetam a monotonicidade. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "An example for a quantifier that satisfies +neither MON↑ nor MON↓…" to "…are in the next exercises.", with examples +(7.10)–(7.15), and the sentence after Exercise 7.10, "The answers to these +questions can be tested…". +::: +:::: + +::::exercise (rating := 2) (name := "mon-not") +Prove que a negação troca MON↑ por MON↓, e MON↓ por MON↑. + +```lean +theorem notNum_monUp (q : NumQuant) (h : MonUpNum q) : + MonDownNum (notNum q) := by + solution! + intro m n hq + simp [notNum] at * + by_cases hq' : q (m + 1) n + · have h' := h m n hq' + simp_all + · simpa using hq' + +theorem notNum_monDown (q : NumQuant) (h : MonDownNum q) : + MonUpNum (notNum q) := by + solution! + intro m n hq + simp [notNum] at * + by_cases hq' : q m (n + 1) + · have h' := h m n hq' + simp_all + · simpa using hq' +``` +:::: + +::::exercise (rating := 2) (name := "mon-and") +Prove que a conjunção de dois quantificadores MON↑ é MON↑, e que a de dois +MON↓ é MON↓. + +```lean +theorem andNum_monUp (q₁ q₂ : NumQuant) + (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : + MonUpNum (andNum q₁ q₂) := by + solution! + intro m n h + simp [andNum] at * + exact ⟨h₁ m n h.1, h₂ m n h.2⟩ + +theorem andNum_monDown (q₁ q₂ : NumQuant) + (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : + MonDownNum (andNum q₁ q₂) := by + solution! + intro m n h + simp [andNum] at * + exact ⟨h₁ m n h.1, h₂ m n h.2⟩ +``` +:::: + +::::exercise (rating := 2) (name := "mon-or") +Prove que a disjunção de dois quantificadores MON↑ é MON↑, e que a de dois +MON↓ é MON↓. + +```lean +theorem orNum_monUp (q₁ q₂ : NumQuant) + (h₁ : MonUpNum q₁) (h₂ : MonUpNum q₂) : + MonUpNum (orNum q₁ q₂) := by + solution! + intro m n h + simp [orNum] at * + cases h with + | inl h => exact Or.inl (h₁ m n h) + | inr h => exact Or.inr (h₂ m n h) + +theorem orNum_monDown (q₁ q₂ : NumQuant) + (h₁ : MonDownNum q₁) (h₂ : MonDownNum q₂) : + MonDownNum (orNum q₁ q₂) := by + solution! + intro m n h + simp [orNum] at * + cases h with + | inl h => exact Or.inl (h₁ m n h) + | inr h => exact Or.inr (h₂ m n h) +``` +:::: + +::::exercise (rating := 3) (name := "mon-up-down") +Mostre que, combinando um quantificador MON↑ com um MON↓, nada se pode +garantir: nem a conjunção nem a disjunção são sempre MON↑ ou MON↓. + +Dica: use *at least one* e *at most three*. Antes de provar, desenhe os +padrões da conjunção e da disjunção com `patternTree`. + +```lean +theorem andNum_up_down : + ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → + MonUpNum (andNum q₁ q₂) ∨ + MonDownNum (andNum q₁ q₂) := by + solution! + intro h + have hup := atLeastNum_monUp 1 + have hdown : MonDownNum (atMostNum 3) := by + intro m n h + simp [atMostNum] at * + omega + cases h _ _ hup hdown with + | inl h => + have h' := h 0 3 (by decide) + simp [andNum, atLeastNum, atMostNum] at h' + | inr h => + have h' := h 0 0 (by decide) + simp [andNum, atLeastNum, atMostNum] at h' + +theorem orNum_up_down : + ¬ ∀ q₁ q₂, MonUpNum q₁ → MonDownNum q₂ → + MonUpNum (orNum q₁ q₂) ∨ + MonDownNum (orNum q₁ q₂) := by + solution! + intro h + have hup := atLeastNum_monUp 3 + have hdown : MonDownNum (atMostNum 1) := by + intro m n h + simp [atMostNum] at * + omega + cases h _ _ hup hdown with + | inl h => + have h' := h 0 1 (by decide) + simp [orNum, atLeastNum, atMostNum] at h' + | inr h => + have h' := h 0 2 (by decide) + simp [orNum, atLeastNum, atMostNum] at h' +``` +:::: + +:::terse +- A monotonicidade também pode ser na restrição. `Q` é *↑MON* se `Q A B` + continua verdadeiro quando `A` cresce, e *↓MON* se continua verdadeiro + quando `A` diminui. *Some* e *not all* são ↑MON; *all* e *no* são ↓MON. +- Ela explica a polaridade dentro da restrição: *All dwarfs who liked any + of the elves were mistrusted*, mas não *Some dwarfs who liked any of the + elves were mistrusted*. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "One can also study monotonicity in the +first argument…" to example (7.17). +::: +:::: + +::::exercise (rating := 2) (name := "left-mon-pattern") +Defina `UpMonNum q` e `DownMonNum q`, as formas do padrão de um quantificador +↑MON e de um ↓MON. Depois, prove que *some* e *not all* são ↑MON, e que +*all* e *no* são ↓MON. + +Dica: acrescentar um elemento a `A` aumenta `m` ou `n` em um, conforme o +elemento esteja ou não em `B`. + +```lean +def UpMonNum (q : NumQuant) : Prop := + solution!(∀ m n, q m n → q (m + 1) n ∧ q m (n + 1)) + +def DownMonNum (q : NumQuant) : Prop := + solution!( + ∀ m n, (q (m + 1) n → q m n) ∧ (q m (n + 1) → q m n)) + +theorem some_upMon : UpMonNum (notNum noNum) := by + solution! + intro m n h + simp_all [notNum, noNum] + +theorem notAll_upMon : UpMonNum (notNum allNum) := by + solution! + intro m n h + simp [notNum, allNum] at * + omega + +theorem all_downMon : DownMonNum allNum := by + solution! + intro m n + simp [allNum] + +theorem no_downMon : DownMonNum noNum := by + solution! + intro m n + simp [noNum] +``` +:::: + +```lean +end Composition +``` diff --git a/CSwL/Composition/Reduction.lean b/CSwL/Composition/Reduction.lean new file mode 100644 index 0000000..beea314 --- /dev/null +++ b/CSwL/Composition/Reduction.lean @@ -0,0 +1,10 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "Redução de expressões da lógica tipada" => +%%% +tag := "comp-reduction" +%%% diff --git a/CSwL/Composition/Rules.lean b/CSwL/Composition/Rules.lean new file mode 100644 index 0000000..6d451a0 --- /dev/null +++ b/CSwL/Composition/Rules.lean @@ -0,0 +1,31 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "As regras do jogo" => +%%% +tag := "comp-rules" +%%% + +:::terse +- Traduzir sentenças para uma lógica pressupõe entender as fórmulas e as + sentenças. Por isso a tradução não explica o significado das sentenças. +- O procedimento de {ref "english-lf"}[FOL como linguagem de representação] + explica: o significado do todo é construído a partir dos significados das + partes. Os significados das palavras vêm do modelo. +- A semântica computacional tem pouco ou nada a dizer sobre a interpretação dos + átomos semânticos (a interpretação dos átomos no modelo de primeira ordem); tem muito a dizer sobre o processo de compor sistematicamente significados complexos a partir dos significados dos componentes. +- Princípio da Composicionalidade, já visto em {ref "IntroCS"}[O estudo formal + da língua natural]: o significado de uma expressão é uma função dos + significados de seus componentes imediatos e do modo de composição. +- Frege, depois Montague. Em Montague, outro ingrediente-chave: os + quantificadores. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.1. +::: +:::: diff --git a/CSwL/Composition/TypedLogic.lean b/CSwL/Composition/TypedLogic.lean new file mode 100644 index 0000000..b1059cb --- /dev/null +++ b/CSwL/Composition/TypedLogic.lean @@ -0,0 +1,17 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "A linguagem da lógica tipada e sua semântica" => +%%% +tag := "comp-typed-logic" +%%% + +:::terse +- A linguagem de tipos da lógica tipada: $`e` para entidades, $`t` para + valores de verdade, e $`\tau_1 \to \tau_2` para funções. +- No nosso modelo, $`e` é `Entity` e $`t` é `Bool`; os tipos de + {ref "comp-relational"}[A visão relacional dos quantificadores] são esses. +::: diff --git a/CSwL/Composition/TypedMeanings.lean b/CSwL/Composition/TypedMeanings.lean new file mode 100644 index 0000000..9edc07b --- /dev/null +++ b/CSwL/Composition/TypedMeanings.lean @@ -0,0 +1,10 @@ +import CSwLMeta +import Bib + +open Verso.Genre Manual +open CSwLMeta + +#doc (Manual) "Significados tipados para a língua natural" => +%%% +tag := "comp-typed-meanings" +%%% diff --git a/README.md b/README.md index 3c0835a..7084e83 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ adapts — see [DEVIATIONS.md](DEVIATIONS.md) for why. - [~] An inference engine — [source](CSwL/InfEngine.lean) - [~] Model checking with first-order logic — [source](CSwL/ModelChecking.lean) - [~] The composition of meaning — [source](CSwL/Composition.lean) + (sections in [`CSwL/Composition/`](CSwL/Composition)) - [ ] Extension and intension - [ ] Parsing - [ ] Relations and scope From 3e7fcc65aeda0cc3053c8d6e04361938a294a35a Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Sun, 25 Oct 2026 23:27:08 -0300 Subject: [PATCH 13/20] feat(Composition): add quantifier languages over Mathlib's Language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A quantifier becomes a language of words over Bool: `wordOf` reads the restriction against the scope, `langOf q` is a Mathlib `Language Bool`, and `langOf_perm` shows it is closed under permutation. Negation is complement; exercises `lang-and-or` and `all-kstar` show conjunction as intersection, disjunction as union, and all as `{[true]}∗`. Automata and definability stay in the cues; exercises 7.11 and 7.12 are omitted. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the proofs; all of it was reviewed by a human author. --- CSwFP.yaml | 6 +- CSwL/Composition.lean | 1 + CSwL/Composition/Quantification.lean | 160 +++++++++++++++++++++++++++ DEVIATIONS.md | 7 ++ STYLE-CODE.md | 2 +- 5 files changed, 173 insertions(+), 3 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 9d4e64f..443a754 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -140,8 +140,8 @@ exercises: 7.8 (p. 162): mon-and 7.9 (p. 162): mon-or 7.10 (p. 162): mon-up-down - 7.11 (p. 163): TODO - 7.12 (p. 164): TODO + 7.11 (p. 163): omitted, automata are not implemented + 7.12 (p. 164): omitted, automata are not implemented 7.13 (p. 165): TODO 7.14 (p. 165): TODO 7.15 (p. 166): TODO @@ -203,6 +203,8 @@ original: - no-mon-down # from the prose on MON↓ in 7.2 - even-not-mon # from the prose on "an even number of" in 7.2, neither MON↑ nor MON↓ - left-mon-pattern # from the prose on ↑MON and ↓MON in 7.2, "left to the reader" + - lang-and-or # from the prose on quantifier automata in 7.2 + - all-kstar # from the prose in 7.2, "all corresponds to the regular language 1∗" depends: bangu-proof: bangu-form diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 7539e5e..68ae1cb 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -3,6 +3,7 @@ import Bib import CSwL.ModelChecking import Mathlib.Data.Set.Function import Mathlib.Data.Set.Card +import Mathlib.Computability.Language import CSwL.Composition.Rules import CSwL.Composition.Quantification import CSwL.Composition.TypedLogic diff --git a/CSwL/Composition/Quantification.lean b/CSwL/Composition/Quantification.lean index b44bdaa..06f1609 100644 --- a/CSwL/Composition/Quantification.lean +++ b/CSwL/Composition/Quantification.lean @@ -3,6 +3,7 @@ import Bib import CSwL.ModelChecking import Mathlib.Data.Set.Function import Mathlib.Data.Set.Card +import Mathlib.Computability.Language open Verso.Genre Manual open CSwLMeta @@ -1540,6 +1541,165 @@ theorem no_downMon : DownMonNum noNum := by ``` :::: +# Quantificadores, autômatos e definibilidade +%%% +tag := "comp-automata" +%%% + +:::terse +- Percorrendo os elementos de `A` e anotando `1` para cada um que está em + `B` e `0` para cada um que não está, obtemos uma *palavra* sobre o + alfabeto $`\{0, 1\}`. Aqui, `true` faz o papel de `1` e `false` o de `0`. +- O número de zeros é $`|A - B|` e o de uns é $`|A \cap B|`: a palavra + leva à posição `(m, n)` da árvore. +- Um quantificador `q` determina a linguagem `langOf q`: as palavras cujas + contagens caem num `+` do padrão de `q`. +- `Language Bool`, do Mathlib, é o tipo das linguagens sobre `Bool`: um + conjunto de palavras, com as operações das linguagens formais. +::: + +```lean +abbrev Word := List Bool + +def wordOf (A : List Entity) (B : OnePlacePred) : Word := + A.map B + +def accepts (q : NumQuant) (w : Word) : Bool := + q (w.count false) (w.count true) + +def langOf (q : NumQuant) : Language Bool := + {w | accepts q w} + +theorem mem_langOf (q : NumQuant) (w : Word) : + w ∈ langOf q ↔ accepts q w := + Iff.rfl + +#eval wordOf (entities.filter girl) laugh +#eval (accepts allNum (wordOf (entities.filter girl) laugh), + accepts (notNum noNum) + (wordOf (entities.filter girl) laugh)) +``` + +:::terse +- *All girls laughed* é falsa e *Some girl laughed* é verdadeira: a palavra + tem dois zeros e dois uns. +- A ordem dos elementos de `A` não importa: só contam os zeros e os uns. + Duas palavras que são permutações uma da outra (`List.Perm`) têm as + mesmas contagens, e `List.Perm.count_eq` diz exatamente isso. +- Então `langOf q` é fechada por permutação. É ISOM, visto nas palavras. +::: + +```lean +theorem langOf_perm (q : NumQuant) {v w : Word} + (h : v.Perm w) (hv : v ∈ langOf q) : + w ∈ langOf q := by + rw [mem_langOf, accepts] at * + rw [← h.count_eq, ← h.count_eq] + exact hv +``` + +:::terse +- As operações sobre `NumQuant` são operações sobre linguagens. A negação + `notNum` dá o complemento, `ᶜ`: as palavras que `q` não aceita. +::: + +```lean +theorem langOf_notNum (q : NumQuant) : + langOf (notNum q) = (langOf q)ᶜ := by + ext w + show accepts (notNum q) w ↔ ¬ accepts q w + simp [accepts, notNum] +``` + +::::exercise (rating := 2) (name := "lang-and-or") +Prove que a conjunção `andNum` dá a interseção das linguagens, `⊓`, e que +a disjunção `orNum` dá a união, `+`. + +```lean +theorem langOf_andNum (q₁ q₂ : NumQuant) : + langOf (andNum q₁ q₂) = langOf q₁ ⊓ langOf q₂ := by + solution! + ext w + rw [Language.mem_inf, mem_langOf, mem_langOf, + mem_langOf] + simp [accepts, andNum] + +theorem langOf_orNum (q₁ q₂ : NumQuant) : + langOf (orNum q₁ q₂) = langOf q₁ + langOf q₂ := by + solution! + ext w + rw [Language.mem_add, mem_langOf, mem_langOf, + mem_langOf] + simp [accepts, orNum] +``` +:::: + +:::terse +- *All* aceita as palavras sem nenhum `0`: as feitas só de `1`. É a + linguagem `1∗`, o fecho de Kleene `∗` da linguagem que tem só a palavra + `[true]`. +::: + +::::exercise (rating := 3) (name := "all-kstar") +Prove que a linguagem de *all* é `{[true]}∗`. + +```lean +open Computability in +theorem langOf_allNum : + langOf allNum = ({[true]} : Language Bool)∗ := by + solution! + ext w + rw [mem_langOf, Language.mem_kstar] + simp only [accepts, allNum, List.count_eq_zero, + decide_eq_true_eq] + constructor + · intro h + refine ⟨w.map fun _ => [true], ?_, ?_⟩ + · induction w with + | nil => rfl + | cons b w ih => + simp only [List.mem_cons, not_or] at h + obtain ⟨hb, hw⟩ := h + cases b + · exact absurd rfl hb + · rw [List.map_cons, List.flatten_cons, ← ih hw] + rfl + · intro y hy + simp only [List.mem_map] at hy + obtain ⟨_, _, rfl⟩ := hy + rfl + · intro h + obtain ⟨L, rfl, hL⟩ := h + simp only [List.mem_flatten, not_exists, not_and] + intro y hy + rw [hL y hy] + simp +``` +:::: + +:::terse +- Um autômato finito que aceita exatamente as palavras de `langOf q` + computa `q`. +- Os quantificadores definíveis em primeira ordem (com $`\forall`, + $`\exists`, igualdade e os predicados da restrição e do escopo) são + exatamente os computados por um autômato finito acíclico e invariante + por permutação (van Benthem). +- *An even number of* pede um autômato com ciclo. *Most* não tem autômato + finito nenhum: é preciso memória para comparar $`|A - B|` e + $`|A \cap B|`. Nenhum dos dois é definível em primeira ordem. +- Por isso *most* ficou fora da tradução para a lógica de primeira ordem + em {ref "ModelChecking"}[Model checking]. Na interpretação direta, ele é + uma função como as outras. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "Quantifiers correspond to automata that +accept strings over a binary alphabet…" to "…the numbers of elements in +A − B and A ∩ B)." +::: +:::: + ```lean end Composition ``` diff --git a/DEVIATIONS.md b/DEVIATIONS.md index b8443a6..7937295 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -172,6 +172,13 @@ syntax and model, so it comes after `ModelChecking`. Being written. `ListQuant` into a `NumQuant` at the start of "Logical Representations for Quantifiers", which CSwFP leaves implicit, so that the patterns of `List.all` and `allNum` can be compared. +- Of "Quantifiers, Automata, and Definability" only the words are + implemented: `wordOf`, `langOf q` as a Mathlib `Language Bool`, the + theorem that it is closed under permutation, and the operations + `notNum`, `andNum` and `orNum` as complement, intersection and union + (with *all* as `{[true]}∗`, CSwFP's `1∗`). Automata, van Benthem's characterization and the + definability of *most* are in the cues only, and exercises 7.11 and 7.12 + are left out. The chapter moves on to typed logic. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". diff --git a/STYLE-CODE.md b/STYLE-CODE.md index 049eb50..bc2fd20 100644 --- a/STYLE-CODE.md +++ b/STYLE-CODE.md @@ -83,7 +83,7 @@ this way is usually a mistake; see "Known gaps." | `Morphology` | `open` of constructor namespaces (`open Attr Value`) | `match e₁, e₂ with` (first use outside a solution), `mapM` over `Option` **(solution only)** | *(none new)* | | `InfEngine` | `let rec` | `do`-notation | — | | `ModelChecking` | `mutual` over `inductive` types (`Logic/FOL` only uses it over `def`) | guillemet identifiers (`«with»`), pattern-matching `fun \| … => …` (first use outside a solution) | *(none new)* | -| `Composition` | — | image `f '' A`, `Set.BijOn`, `Set.ncard` | *(none new)* | +| `Composition` | — | image `f '' A`, `Set.BijOn`, `Set.ncard`, `List.count`, `List.Perm`, Mathlib's `Language` with `ᶜ`, `⊓`, `+` and `∗` | *(none new)* | `ModelChecking` is where `abbrev` and `ToString` instances become the dominant idiom, but both arrive earlier; what is genuinely new there is the mutually From e748521d0583493276bd043e6857fe585e6ccb98 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Sun, 25 Oct 2026 23:34:25 -0300 Subject: [PATCH 14/20] docs(Composition): record the quantifier automata as deferred The automata of 7.2 were recorded as omitted, but they are deferred: CSwFP.yaml and DEVIATIONS.md now point to issue 41, which lists what is left. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the issue and the corrections; all of it was reviewed by a human author. --- CSwFP.yaml | 4 ++-- DEVIATIONS.md | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 443a754..e8adf19 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -140,8 +140,8 @@ exercises: 7.8 (p. 162): mon-and 7.9 (p. 162): mon-or 7.10 (p. 162): mon-up-down - 7.11 (p. 163): omitted, automata are not implemented - 7.12 (p. 164): omitted, automata are not implemented + 7.11 (p. 163): deferred with the automata (issue 41) + 7.12 (p. 164): deferred with the automata (issue 41) 7.13 (p. 165): TODO 7.14 (p. 165): TODO 7.15 (p. 166): TODO diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 7937295..97a88ab 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -176,9 +176,10 @@ syntax and model, so it comes after `ModelChecking`. Being written. implemented: `wordOf`, `langOf q` as a Mathlib `Language Bool`, the theorem that it is closed under permutation, and the operations `notNum`, `andNum` and `orNum` as complement, intersection and union - (with *all* as `{[true]}∗`, CSwFP's `1∗`). Automata, van Benthem's characterization and the - definability of *most* are in the cues only, and exercises 7.11 and 7.12 - are left out. The chapter moves on to typed logic. + (with *all* as `{[true]}∗`, CSwFP's `1∗`). The automata are deferred, + not dropped (issue 41): until then, they, van Benthem's + characterization and the definability of *most* are in the cues only, + and exercises 7.11 and 7.12 wait for them. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". From 8af8380db39f09b6855a20742bc36e63ed1d296a Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Sun, 25 Oct 2026 23:59:59 -0300 Subject: [PATCH 15/20] refactor(Composition): drop CSwFP 7.3 and 7.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lean is the typed logic: its types, lambda terms and evaluation are what IntroL presents with the lambda calculus, and Lean reduces and substitutes for the reader. No later section handles terms as data, and CSLib's lambda calculi do not fit (the named one is untyped, the typed one is locally nameless). The opening of 7.5 will say that e is Entity and t is Bool. Exercises 7.13–7.22 go with the sections. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the changes and the recorded reasons; the decision was made by a human author. --- CSwFP.yaml | 32 ++++++++++++++++------------ CSwL/Composition.lean | 17 ++++++--------- CSwL/Composition/Quantification.lean | 3 ++- CSwL/Composition/Reduction.lean | 10 --------- CSwL/Composition/TypedLogic.lean | 17 --------------- DEVIATIONS.md | 7 ++++++ 6 files changed, 33 insertions(+), 53 deletions(-) delete mode 100644 CSwL/Composition/Reduction.lean delete mode 100644 CSwL/Composition/TypedLogic.lean diff --git a/CSwFP.yaml b/CSwFP.yaml index e8adf19..86af3fe 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -142,16 +142,16 @@ exercises: 7.10 (p. 162): mon-up-down 7.11 (p. 163): deferred with the automata (issue 41) 7.12 (p. 164): deferred with the automata (issue 41) - 7.13 (p. 165): TODO - 7.14 (p. 165): TODO - 7.15 (p. 166): TODO - 7.16 (p. 166): TODO - 7.17 (p. 166): TODO - 7.18 (p. 166): TODO - 7.19 (p. 168): TODO - 7.20 (p. 170): TODO - 7.21 (p. 170): TODO - 7.22 (p. 172): TODO + 7.13 (p. 165): dropped with 7.3 + 7.14 (p. 165): dropped with 7.3 + 7.15 (p. 166): dropped with 7.3 + 7.16 (p. 166): dropped with 7.3 + 7.17 (p. 166): dropped with 7.3 + 7.18 (p. 166): dropped with 7.3 + 7.19 (p. 168): dropped with 7.3 + 7.20 (p. 170): dropped with 7.4 + 7.21 (p. 170): dropped with 7.4 + 7.22 (p. 172): dropped with 7.4 7.23 (p. 173): TODO 7.24 (p. 175): TODO 7.25 (p. 179): TODO @@ -319,11 +319,15 @@ sections: why: TODO, its Aristotle-to-Frege opening retells what InfEngine already presents with the syllogisms. 7.3 The Language of Typed Logic and Its Semantics: - to: Composition - why: TODO, it overlaps the lambda calculus that IntroL takes from 2.4. + to: dropped + why: Lean is the typed logic. Its types, lambda terms, application and + evaluation are what IntroL presents with the lambda calculus of 2.4, + and the semantics of 7.3 is Lean's own evaluation. 7.4 Reducing Expressions of Typed Logic: - to: Composition - why: TODO, it overlaps the lambda calculus that IntroL takes from 2.4. + to: dropped + why: Lean reduces and substitutes for the reader, and no later section + handles terms as data. CSLib's lambda calculi do not fit, since the named + one is untyped, and the typed one is locally nameless. 7.5 Typed Meanings for Natural Language: Composition 7.6 Implementing Semantic Interpretation: Composition 7.7 Handling Ambiguity: diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 68ae1cb..975e29a 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -6,8 +6,6 @@ import Mathlib.Data.Set.Card import Mathlib.Computability.Language import CSwL.Composition.Rules import CSwL.Composition.Quantification -import CSwL.Composition.TypedLogic -import CSwL.Composition.Reduction import CSwL.Composition.TypedMeanings import CSwL.Composition.Interpretation import CSwL.Composition.Ambiguity @@ -23,7 +21,8 @@ file := "Composition" %%% :::dev NOW -Plan. The headings follow CSwFP/7.1–7.7 (7.8, further reading, is omitted). +Plan. The headings follow CSwFP/7.1–7.7, without 7.3 and 7.4 (7.8, further +reading, is omitted). Sections are written `terse` first (see `STYLE-CODE.md`). Code comes in the section that presents each idea, not only in 7.6: @@ -31,11 +30,11 @@ section that presents each idea, not only in 7.6: predicates; EXT, CONS and ISOM as `Prop`s over `Set`; the tree of numbers and the numeric quantifiers; ex. 7.7–7.10 as monotonicity theorems; ex. 7.11 with Mathlib's `DFA` (optional). -- 7.3: Lean's types are the typed logic (`Entity` for e, `Bool` for t); no +- 7.3 and 7.4 are dropped (see `CSwFP.yaml`): Lean's types are the typed + logic (`Entity` for e, `Bool` for t), and Lean does the reductions. No deep embedding, since CSwFP/8 needs intensional types. -- 7.4: `#reduce` shows the β-reductions; free variables and substitution - from CSLib's `Named.Untyped`; confluence and normal forms only cited. -- 7.5: the semantic rules as Lean functions. +- 7.5: the semantic rules as Lean functions. Its opening says in a few + lines that e is `Entity` and t is `Bool`. - 7.6: `intSent` and friends over `ModelChecking`'s `Sent`, with `intDET` built from the 7.2 definitions; a theorem that the direct interpretation agrees with `checkSentence`, if it turns out feasible. @@ -71,10 +70,6 @@ lambda-calculus engine of `ModelChecking`. {include 1 CSwL.Composition.Quantification} -{include 1 CSwL.Composition.TypedLogic} - -{include 1 CSwL.Composition.Reduction} - {include 1 CSwL.Composition.TypedMeanings} {include 1 CSwL.Composition.Interpretation} diff --git a/CSwL/Composition/Quantification.lean b/CSwL/Composition/Quantification.lean index 06f1609..b20aa3a 100644 --- a/CSwL/Composition/Quantification.lean +++ b/CSwL/Composition/Quantification.lean @@ -221,7 +221,8 @@ tag := "comp-relational" :::dev BeforeNextRelease TODO: translate CSwFP/7.2, "The relational view of quantifiers", from the start to the table after (7.3). Decide whether the table keeps the types -e and t or shows the Lean types; e and t are presented in `comp-typed-logic`. +e and t or shows the Lean types; CSwFP/7.3, which presents e and t, is +dropped, so they need a word here or in `comp-typed-meanings`. ::: :::: diff --git a/CSwL/Composition/Reduction.lean b/CSwL/Composition/Reduction.lean deleted file mode 100644 index beea314..0000000 --- a/CSwL/Composition/Reduction.lean +++ /dev/null @@ -1,10 +0,0 @@ -import CSwLMeta -import Bib - -open Verso.Genre Manual -open CSwLMeta - -#doc (Manual) "Redução de expressões da lógica tipada" => -%%% -tag := "comp-reduction" -%%% diff --git a/CSwL/Composition/TypedLogic.lean b/CSwL/Composition/TypedLogic.lean deleted file mode 100644 index b1059cb..0000000 --- a/CSwL/Composition/TypedLogic.lean +++ /dev/null @@ -1,17 +0,0 @@ -import CSwLMeta -import Bib - -open Verso.Genre Manual -open CSwLMeta - -#doc (Manual) "A linguagem da lógica tipada e sua semântica" => -%%% -tag := "comp-typed-logic" -%%% - -:::terse -- A linguagem de tipos da lógica tipada: $`e` para entidades, $`t` para - valores de verdade, e $`\tau_1 \to \tau_2` para funções. -- No nosso modelo, $`e` é `Entity` e $`t` é `Bool`; os tipos de - {ref "comp-relational"}[A visão relacional dos quantificadores] são esses. -::: diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 97a88ab..81ad53a 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -180,6 +180,13 @@ syntax and model, so it comes after `ModelChecking`. Being written. not dropped (issue 41): until then, they, van Benthem's characterization and the definability of *most* are in the cues only, and exercises 7.11 and 7.12 wait for them. +- 7.3 and 7.4, the language of typed logic and the reduction of its + expressions, are dropped, with their exercises 7.13–7.22. Lean is the + typed logic: its types, lambda terms and evaluation are what `IntroL` + presents with the lambda calculus of 2.4, and Lean reduces and substitutes + for the reader. No later section handles terms as data. CSLib's lambda + calculi were considered for 7.4 and do not fit: the named one is untyped, + and the typed one is locally nameless, without constants. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". From 1f8a1652c6b671df32e52a7f29df9e02eac2ca50 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 26 Oct 2026 00:07:39 -0300 Subject: [PATCH 16/20] feat(Composition): add typed meanings for the fragment Each grammar rule gets its semantic rule as a Lean function in namespace `Rule`, named after the constructor it interprets: `sent`, `npName`, `npDet`, `rcnSubj`, `rcnObj`, `vpTrans` and `vpDitrans`, with the determiners `no` and `the`. The opening says that e is Entity and t is Bool. The reduction of Alice admired Dorothy is a theorem proved by `rfl` for any relation, and exercise `snow-white-helped` (7.24) asks for the same. Both 7.5 and 7.6 take the subject first, as the model does. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the proofs; all of it was reviewed by a human author. --- CSwFP.yaml | 4 +- CSwL/Composition/TypedMeanings.lean | 201 ++++++++++++++++++++++++++++ DEVIATIONS.md | 10 ++ 3 files changed, 213 insertions(+), 2 deletions(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 86af3fe..728e501 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -152,8 +152,8 @@ exercises: 7.20 (p. 170): dropped with 7.4 7.21 (p. 170): dropped with 7.4 7.22 (p. 172): dropped with 7.4 - 7.23 (p. 173): TODO - 7.24 (p. 175): TODO + 7.23 (p. 173): dropped with 7.4 + 7.24 (p. 175): snow-white-helped 7.25 (p. 179): TODO 7.26 (p. 180): TODO 7.27 (p. 181): TODO diff --git a/CSwL/Composition/TypedMeanings.lean b/CSwL/Composition/TypedMeanings.lean index 9edc07b..2dda9f3 100644 --- a/CSwL/Composition/TypedMeanings.lean +++ b/CSwL/Composition/TypedMeanings.lean @@ -1,5 +1,6 @@ import CSwLMeta import Bib +import CSwL.Composition.Quantification open Verso.Genre Manual open CSwLMeta @@ -8,3 +9,203 @@ open CSwLMeta %%% tag := "comp-typed-meanings" %%% + +```lean +namespace Composition + +open ModelChecking +``` + +:::terse +- Cada regra da gramática de {ref "ModelChecking"}[Model checking] ganha + uma regra semântica: como o significado do todo se constrói a partir dos + significados das partes. Escrevemos ⟦X⟧ para o significado de X. +- Os significados vivem na *lógica tipada*. Há dois tipos básicos, `e` + para entidades e `t` para valores de verdade, e os tipos de função + $`\tau_1 \to \tau_2`. +- Em Lean, `e` é `Entity` e $`t` é `Bool`, e os termos da lógica tipada + são funções do Lean, como em {ref "lambda"}[Lean e o Cálculo Lambda]. +- O tipo de cada categoria: + - S: `Bool`; + - CN, RCN e VP: `Entity → Bool`, isto é, `OnePlacePred`; + - TV: `Entity → Entity → Bool`, isto é, `TwoPlacePred`; + - NP: `OnePlacePred → Bool`; + - DET: `OnePlacePred → OnePlacePred → Bool`. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.5, from the start to the rules for determiners. +Its types e and t are presented in CSwFP/7.3, which is dropped (see +`DEVIATIONS.md`): the translation says in a few words what they are. +::: +:::: + +:::terse +- A sentença é a aplicação do significado do NP ao do VP: + ⟦S⟧ = ⟦NP⟧ ⟦VP⟧. O sujeito é a função; o VP é o argumento. +- Um nome próprio não denota uma entidade, e sim um quantificador: o + conjunto das propriedades da entidade. ⟦Alice⟧ = λP ↦ P a. +- ⟦DET CN⟧ = ⟦DET⟧ ⟦CN⟧. A mesma regra vale para DET RCN. +::: + +```lean +namespace Rule + +def sent (np : OnePlacePred → Bool) + (vp : OnePlacePred) : Bool := + np vp + +def npName (x : Entity) : OnePlacePred → Bool := + fun P => P x + +def npDet (det : OnePlacePred → OnePlacePred → Bool) + (cn : OnePlacePred) : OnePlacePred → Bool := + det cn + +end Rule +``` + +:::terse +- Os determinantes são relações entre duas propriedades, como em + {ref "comp-relational"}[A visão relacional dos quantificadores]. *Some* e + *a* têm o mesmo significado, `a`; *every* é `every`. +- *No*: nenhuma entidade com `p` tem `q`. +- *The*, à maneira de Russell: há exatamente uma entidade com `p`, e ela + tem `q`. +::: + +```lean +def no (p q : OnePlacePred) : Bool := + entities.all (fun x => p x → ¬ q x) + +def the (p q : OnePlacePred) : Bool := + entities.any (fun x => + entities.all (fun y => p y ↔ x = y) ∧ q x) + +#eval (the princess laugh, no dwarf laugh) +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.5, the rules for determiners and common nouns. +::: +:::: + +:::terse +- Substantivos comuns e verbos intransitivos são as propriedades do + modelo: ⟦girl⟧ = λx ↦ Girl x, que é `girl`. +- Uma oração relativa é a interseção de duas propriedades. + *girl that laughed*: ser menina e ter rido. +- *girl that some boy loved*: ser menina e ser amada por algum menino. O + NP *some boy* recebe a propriedade "amar `x`", `fun y => tv y x`. +::: + +```lean +namespace Rule + +def rcnSubj (cn vp : OnePlacePred) : OnePlacePred := + fun x => cn x && vp x + +def rcnObj (cn : OnePlacePred) (np : OnePlacePred → Bool) + (tv : TwoPlacePred) : OnePlacePred := + fun x => cn x && np (fun y => tv y x) + +end Rule +``` + +:::terse +- VP → TV NP é o truque de `defeated`: fixar o sujeito `x` e entregar ao + NP a propriedade "ser o objeto de `x`". `defeated` é `vpTrans defeat`. +- Com um verbo bitransitivo, o mesmo truque duas vezes, um para cada + objeto. +- O verbo recebe primeiro o sujeito, depois os objetos, como as relações + do modelo. +::: + +```lean +namespace Rule + +def vpTrans (tv : TwoPlacePred) + (np : OnePlacePred → Bool) : OnePlacePred := + fun x => np (fun y => tv x y) + +def vpDitrans (dv : ThreePlacePred) + (np₁ np₂ : OnePlacePred → Bool) : OnePlacePred := + fun x => np₁ (fun y => np₂ (fun z => dv x y z)) + +theorem defeated_eq : defeated = vpTrans defeat := + rfl + +end Rule +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.5, the rules for relative clauses, verb phrases +and transitive verbs. CSwFP's rule for VP → TV NP applies the verb to the +object first, `λx ↦ ⟦NP⟧ (λy ↦ ((⟦TV⟧ y) x))`, and its 7.6 implementation +to the subject first; here both follow the model (see `DEVIATIONS.md`). +::: +:::: + +:::terse +- *Alice admired Dorothy*: compomos as regras na forma da árvore + `[S [NP Alice] [VP [TV admired] [NP Dorothy]]]`. +- O `#eval` consulta o modelo. O teorema diz mais: para *qualquer* + relação `r` no lugar de *admire*, o significado composto é `r alice + dorothy`. É a forma normal do significado. +- `rfl` basta, porque o Lean faz as β-reduções sozinho: aplica cada + `fun` ao seu argumento até sobrar `r alice dorothy`. +::: + +```lean +namespace Rule + +#eval sent (npName alice) + (vpTrans admire (npName dorothy)) + +theorem alice_admired_dorothy (r : TwoPlacePred) : + sent (npName alice) (vpTrans r (npName dorothy)) = + r alice dorothy := + rfl + +end Rule +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.5, from "As an example, consider the sentence +Alice admired Dorothy…" to the end of the section. The chain of +β-reductions is shown by `alice_admired_dorothy`, proved by `rfl`. +::: +:::: + +::::exercise (rating := 2) (name := "snow-white-helped") +Componha, com as regras, o significado de *Snow White helped some dwarf*, +com uma relação `r` qualquer no lugar de *help*. Depois, escreva a sua +forma normal, sem as regras, e prove que as duas são iguais. + +```lean +namespace Rule + +def snowWhiteHelped (r : TwoPlacePred) : Bool := + solution!( + sent (npName snowWhite) (vpTrans r (npDet a dwarf))) + +def snowWhiteHelpedNF (r : TwoPlacePred) : Bool := + solution!( + entities.any (fun x => dwarf x ∧ r snowWhite x)) + +theorem snowWhiteHelped_nf (r : TwoPlacePred) : + snowWhiteHelped r = snowWhiteHelpedNF r := by + solution! + rfl + +end Rule +``` +:::: + +```lean +end Composition +``` diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 81ad53a..b1da86e 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -187,6 +187,16 @@ syntax and model, so it comes after `ModelChecking`. Being written. for the reader. No later section handles terms as data. CSLib's lambda calculi were considered for 7.4 and do not fit: the named one is untyped, and the typed one is locally nameless, without constants. +- CSwFP changes the argument order of transitive verbs between 7.5 and + 7.6: the rule for VP → TV NP in 7.5 applies the verb to the object first, + `λx ↦ ⟦NP⟧ (λy ↦ ((⟦TV⟧ y) x))`, and the code of 7.6 to the subject + first, `intTV tv subj obj`, without comment. Both sections here follow + 7.6 and the model, whose relations take the subject first. +- The semantic rules of 7.5 are Lean functions in namespace `Rule`, named + after the grammar constructors they interpret (`Rule.vpTrans` for + `VP.vpTrans`). The chain of β-reductions for *Alice admired Dorothy* is + the theorem `alice_admired_dorothy`, proved by `rfl` for any relation in + place of *admire*, and exercise 7.24 asks for the same. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". From 3d5bda21da7f88dc8ae231cf23fd96d26888b5c8 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 26 Oct 2026 00:24:32 -0300 Subject: [PATCH 17/20] feat(Composition): add the semantic interpretation of the fragment intSent, intNP, intVP and intRCN interpret ModelChecking's syntax trees by recursion, one line per constructor, applying the rules of `Rule` to the lexicon (intCN, intADJ, intTV, intDV, intDET). An #eval checks that the direct interpretation agrees with the translation into a formula on the 32 sentences of `help-defeat`. Most, and at least / at most in exercise `at-least-at-most` (7.25), are meanings used through the rules, with no change to the grammar (issue 42). This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cues, the Lean code and the proofs; all of it was reviewed by a human author. --- CSwFP.yaml | 2 +- CSwL/Composition/Interpretation.lean | 195 +++++++++++++++++++++++++++ DEVIATIONS.md | 8 ++ 3 files changed, 204 insertions(+), 1 deletion(-) diff --git a/CSwFP.yaml b/CSwFP.yaml index 728e501..4baa37d 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -154,7 +154,7 @@ exercises: 7.22 (p. 172): dropped with 7.4 7.23 (p. 173): dropped with 7.4 7.24 (p. 175): snow-white-helped - 7.25 (p. 179): TODO + 7.25 (p. 179): at-least-at-most 7.26 (p. 180): TODO 7.27 (p. 181): TODO 7.28 (p. 182): TODO diff --git a/CSwL/Composition/Interpretation.lean b/CSwL/Composition/Interpretation.lean index 05ae912..9f87796 100644 --- a/CSwL/Composition/Interpretation.lean +++ b/CSwL/Composition/Interpretation.lean @@ -1,5 +1,6 @@ import CSwLMeta import Bib +import CSwL.Composition.TypedMeanings open Verso.Genre Manual open CSwLMeta @@ -8,3 +9,197 @@ open CSwLMeta %%% tag := "comp-interpretation" %%% + +```lean +namespace Composition + +open ModelChecking +``` + +:::terse +- Em {ref "comp-typed-meanings"}[Significados tipados para a língua + natural], quem escolhia a regra para cada nó da árvore éramos nós. + Agora uma função de interpretação faz isso: ela recebe a árvore + sintática, um valor de `Sent`, e devolve o seu valor de verdade. +- Há uma função para cada categoria, com o tipo da categoria. Elas + começam pelo *léxico*: cada palavra ganha o seu significado no modelo. +- *Some* e *a* têm a mesma interpretação. Os adjetivos e *caught* não + são interpretados no modelo, como em {ref "ModelChecking"}[Model + checking]: são falsos para todos. +::: + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.6, from the start to the interpretation of +determiners, without the Haskell `intDET` for *most*, which comes below. +::: +:::: + +```lean +def intCN : CN → OnePlacePred + | .girl => girl + | .boy => boy + | .princess => princess + | .dwarf => dwarf + | .giant => giant + | .wizard => wizard + | .sword => sword + | .dagger => dagger + +def intADJ : ADJ → OnePlacePred + | _ => fun _ => false + +def intTV : TV → TwoPlacePred + | .loved => love + | .admired => admire + | .helped => help + | .defeated => defeat + | .caught => fun _ _ => false + +def intDV : DV → ThreePlacePred + | .gave => give + +def intDET : DET → OnePlacePred → OnePlacePred → Bool + | .a => a + | .some => a + | .every => every + | .no => no + | .the => the +``` + +:::terse +- As quatro categorias que se referem umas às outras são interpretadas + num bloco `mutual`, como os seus tipos foram declarados. +- Cada caso é uma linha: a regra semântica de `Rule` com o mesmo nome do + construtor, aplicada às interpretações dos filhos. A recursão segue a + árvore. +- *Everyone* e *someone* são *every* e *a* restritos a `person`. +- *happy wizard*: a interseção do adjetivo com o substantivo, como uma + oração relativa. +::: + +```lean +mutual + def intSent : Sent → Bool + | .sent np vp => Rule.sent (intNP np) (intVP vp) + + def intNP : NP → OnePlacePred → Bool + | .snowWhite => Rule.npName snowWhite + | .alice => Rule.npName alice + | .dorothy => Rule.npName dorothy + | .goldilocks => Rule.npName goldilocks + | .littleMook => Rule.npName littleMook + | .atreyu => Rule.npName atreyu + | .everyone => every person + | .someone => a person + | .npDet det cn => + Rule.npDet (intDET det) (intCN cn) + | .npDetRel det rcn => + Rule.npDet (intDET det) (intRCN rcn) + + def intVP : VP → OnePlacePred + | .laughed => laugh + | .cheered => cheer + | .shuddered => shudder + | .vpTrans tv np => Rule.vpTrans (intTV tv) (intNP np) + | .vpDitrans dv np₁ np₂ => + Rule.vpDitrans (intDV dv) (intNP np₁) (intNP np₂) + + def intRCN : RCN → OnePlacePred + | .rcnSubj cn _ vp => Rule.rcnSubj (intCN cn) (intVP vp) + | .rcnObj cn _ np tv => + Rule.rcnObj (intCN cn) (intNP np) (intTV tv) + | .rcnAdj adj cn => Rule.rcnSubj (intADJ adj) (intCN cn) +end +``` + +:::terse +- `sent1` é a árvore de *The dwarf that Snow White helped admired every + princess*, de {ref "ModelChecking"}[Model checking]. +- Lá, a sentença era traduzida para uma fórmula, e a fórmula avaliada no + modelo. Aqui não há fórmula: a interpretação consulta o modelo + diretamente. +- Os dois caminhos dão o mesmo valor. O segundo `#eval` confere isso nas + trinta e duas sentenças de `sentences`. +::: + +```lean +#eval (toString sent1, intSent sent1) + +open FOL in +#eval sentences.all fun s => + intSent s == + (lfSent s).eval entities intFairy ass0 + (liftAssign fintFairy) +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.6, the interpretation of verb phrases, verbs, +noun phrases and relative clauses, and the examples of queries. +::: +:::: + +:::terse +- *Most* não tem tradução na lógica de primeira ordem, e por isso ficou + fora de `DET` em {ref "ModelChecking"}[Model checking]. Na interpretação + direta ele é uma função como as outras: compara quantos `p` têm `q` + com quantos não têm. +- Sem mexer na gramática, ele entra pelas regras semânticas: *Most girls + laughed* é `Rule.sent (Rule.npDet most girl) laugh`. +::: + +```lean +def most (p q : OnePlacePred) : Bool := + (entities.filter fun x => p x && !q x).length < + (entities.filter fun x => p x && q x).length + +#eval Rule.sent (Rule.npDet most girl) laugh +#eval Rule.sent (Rule.npDet most person) + (Rule.vpTrans admire (Rule.npName goldilocks)) +``` + +::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.6, the interpretation of *most*. CSwFP adds +`Most` to `DET`; here *most* is a meaning only, with no change to the +grammar (see issue 42). +::: +:::: + +::::exercise (rating := 2) (name := "at-least-at-most") +Defina `atLeastDet n` e `atMostDet n`, as interpretações de *at least n* e +*at most n*. Depois, prove as sentenças abaixo. + +```lean +def atLeastDet (n : Nat) (p q : OnePlacePred) : Bool := + solution!( + n ≤ (entities.filter fun x => p x && q x).length) + +def atMostDet (n : Nat) (p q : OnePlacePred) : Bool := + solution!( + (entities.filter fun x => p x && q x).length ≤ n) + +theorem atLeastTwoGirlsLaughed : + Rule.sent (Rule.npDet (atLeastDet 2) girl) laugh + = true := by + solution! + decide + +theorem atMostOneDwarfLaughed : + Rule.sent (Rule.npDet (atMostDet 1) dwarf) laugh + = true := by + solution! + decide + +theorem notAtLeastThreeGirlsLaughed : + Rule.sent (Rule.npDet (atLeastDet 3) girl) laugh + = false := by + solution! + decide +``` +:::: + +```lean +end Composition +``` diff --git a/DEVIATIONS.md b/DEVIATIONS.md index b1da86e..23650ab 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -197,6 +197,14 @@ syntax and model, so it comes after `ModelChecking`. Being written. `VP.vpTrans`). The chain of β-reductions for *Alice admired Dorothy* is the theorem `alice_admired_dorothy`, proved by `rfl` for any relation in place of *admire*, and exercise 7.24 asks for the same. +- In 7.6, `intSent`, `intNP`, `intVP` and `intRCN` apply the semantic + rules of 7.5, one line per constructor. *Most* and the *at least* / + *at most* of exercise 7.25 are meanings only, used through `Rule`: + CSwFP adds them to `DET`, which here would mean wrapping `NP`, `VP`, + `RCN` and `Sent` too (issue 42). The adjectives and *caught* are false + of everything, as in `ModelChecking`'s model. An `#eval` checks that + the direct interpretation agrees with the translation into a formula + on the sentences of exercise `help-defeat`. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". From 62caf61683e16cc767ea61c9442dc80f04b25c19 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Mon, 26 Oct 2026 00:32:20 -0300 Subject: [PATCH 18/20] docs(Composition): show Alice admired Dorothy as a tree in 7.6 The example of 7.5 is interpreted again from its syntax tree, and an `rfl` shows that `intSent` builds the same composition that 7.5 wrote by hand. This commit was prepared with the assistance of an AI tool (Claude Code), which drafted the terse cue and the code; all of it was reviewed by a human author. --- CSwL/Composition/Interpretation.lean | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CSwL/Composition/Interpretation.lean b/CSwL/Composition/Interpretation.lean index 9f87796..0394777 100644 --- a/CSwL/Composition/Interpretation.lean +++ b/CSwL/Composition/Interpretation.lean @@ -113,6 +113,24 @@ mutual end ``` +:::terse +- *Alice admired Dorothy* de novo, agora como árvore: um valor de `Sent`, + com as palavras `.alice`, `.admired` e `.dorothy`. +- O `rfl` mostra que `intSent` monta a mesma composição que fizemos à mão + em {ref "comp-typed-meanings"}[Significados tipados para a língua + natural]. +::: + +```lean +#eval intSent (.sent .alice (.vpTrans .admired .dorothy)) + +example : + intSent (.sent .alice (.vpTrans .admired .dorothy)) = + Rule.sent (Rule.npName alice) + (Rule.vpTrans admire (Rule.npName dorothy)) := + rfl +``` + :::terse - `sent1` é a árvore de *The dwarf that Snow White helped admired every princess*, de {ref "ModelChecking"}[Model checking]. From 221eeb95ca0d5746247b14ba06606795f5b3e11c Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Thu, 29 Oct 2026 20:32:35 -0300 Subject: [PATCH 19/20] refactor(Composition): defer CSwFP 7.7 Remove the empty section on handling ambiguity and record it, with exercises 7.26-7.28, as deferred (issue 43). The 7.2 cue no longer points to it. check-cswfp.py accepts `deferred` as a section target. Claude Code (Opus 5.5) drafted these changes and this message under the author's direction; the author reviewed them. --- CSwFP.yaml | 12 ++++++------ CSwL/Composition.lean | 9 +++------ CSwL/Composition/Ambiguity.lean | 10 ---------- CSwL/Composition/Quantification.lean | 4 ++-- DEVIATIONS.md | 4 ++++ scripts/check-cswfp.py | 2 +- 6 files changed, 16 insertions(+), 25 deletions(-) delete mode 100644 CSwL/Composition/Ambiguity.lean diff --git a/CSwFP.yaml b/CSwFP.yaml index 4baa37d..eff5aee 100644 --- a/CSwFP.yaml +++ b/CSwFP.yaml @@ -155,9 +155,9 @@ exercises: 7.23 (p. 173): dropped with 7.4 7.24 (p. 175): snow-white-helped 7.25 (p. 179): at-least-at-most - 7.26 (p. 180): TODO - 7.27 (p. 181): TODO - 7.28 (p. 182): TODO + 7.26 (p. 180): deferred with 7.7 (issue 43) + 7.27 (p. 181): deferred with 7.7 (issue 43) + 7.28 (p. 182): deferred with 7.7 (issue 43) original: IntroL.lean: [sum-of-squares, sum-to, sum-list, count-zeros] @@ -331,9 +331,9 @@ sections: 7.5 Typed Meanings for Natural Language: Composition 7.6 Implementing Semantic Interpretation: Composition 7.7 Handling Ambiguity: - to: Composition - why: TODO, its exercises build on the prepositional phrases that - ModelChecking adds to the fragment. + to: deferred + why: its benefit is unclear for now, and the implementation within + reach looked of little use (issue 43). 7.8 Further Reading: omitted CSwFP/8 Extension and Intension: not yet taken up CSwFP/9 Parsing: not yet taken up diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 975e29a..607cefa 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -8,7 +8,6 @@ import CSwL.Composition.Rules import CSwL.Composition.Quantification import CSwL.Composition.TypedMeanings import CSwL.Composition.Interpretation -import CSwL.Composition.Ambiguity open Verso.Genre Manual open CSwLMeta @@ -21,8 +20,8 @@ file := "Composition" %%% :::dev NOW -Plan. The headings follow CSwFP/7.1–7.7, without 7.3 and 7.4 (7.8, further -reading, is omitted). +Plan. The headings follow CSwFP/7.1–7.6, without 7.3 and 7.4 (7.7 is +deferred, issue 43; 7.8, further reading, is omitted). Sections are written `terse` first (see `STYLE-CODE.md`). Code comes in the section that presents each idea, not only in 7.6: @@ -38,7 +37,7 @@ section that presents each idea, not only in 7.6: - 7.6: `intSent` and friends over `ModelChecking`'s `Sent`, with `intDET` built from the 7.2 definitions; a theorem that the direct interpretation agrees with `checkSentence`, if it turns out feasible. -- 7.7: ex. 7.26–7.27 over `ModelChecking`'s `SentPP`; ex. 7.28. +- 7.7: deferred (issue 43). The chapter's key point for the cues: direct interpretation admits quantifiers, such as *most*, that first-order logic cannot express. @@ -73,5 +72,3 @@ lambda-calculus engine of `ModelChecking`. {include 1 CSwL.Composition.TypedMeanings} {include 1 CSwL.Composition.Interpretation} - -{include 1 CSwL.Composition.Ambiguity} diff --git a/CSwL/Composition/Ambiguity.lean b/CSwL/Composition/Ambiguity.lean deleted file mode 100644 index f7fc0b4..0000000 --- a/CSwL/Composition/Ambiguity.lean +++ /dev/null @@ -1,10 +0,0 @@ -import CSwLMeta -import Bib - -open Verso.Genre Manual -open CSwLMeta - -#doc (Manual) "Tratando a ambiguidade" => -%%% -tag := "comp-ambiguity" -%%% diff --git a/CSwL/Composition/Quantification.lean b/CSwL/Composition/Quantification.lean index b20aa3a..c0ec5a2 100644 --- a/CSwL/Composition/Quantification.lean +++ b/CSwL/Composition/Quantification.lean @@ -300,8 +300,8 @@ def defeated (X : OnePlacePred → Bool) : OnePlacePred := :::terse - A sentença inteira é só aplicação de funções. Nenhuma fórmula é construída: a avaliação consulta o modelo diretamente. -- Nessa composição o objeto fica sempre no escopo do sujeito. A outra leitura - fica para {ref "comp-ambiguity"}[Tratando a ambiguidade]. +- Nessa composição o objeto fica sempre no escopo do sujeito. A outra + leitura, com o objeto de escopo amplo, não é tratada aqui. ::: ```lean diff --git a/DEVIATIONS.md b/DEVIATIONS.md index 23650ab..5863599 100644 --- a/DEVIATIONS.md +++ b/DEVIATIONS.md @@ -205,6 +205,10 @@ syntax and model, so it comes after `ModelChecking`. Being written. of everything, as in `ModelChecking`'s model. An `#eval` checks that the direct interpretation agrees with the translation into a formula on the sentences of exercise `help-defeat`. +- 7.7, handling ambiguity, is deferred with its exercises 7.26–7.28 + (issue 43): its benefit is unclear for now, and the implementation + within reach looked of little use. The scope reading of *Every dwarf + defeated a giant* with the object in wide scope is not presented. - 7.2 calls the second argument of a determiner its *body*, where CSwFP/6 called it its *scope*. Both translate as "escopo". diff --git a/scripts/check-cswfp.py b/scripts/check-cswfp.py index 237c535..61352ba 100755 --- a/scripts/check-cswfp.py +++ b/scripts/check-cswfp.py @@ -93,7 +93,7 @@ def is_exercise_name(value): for section, value in sections.items(): target = value["to"] if isinstance(value, dict) else value chapter = re.match(r"[^,\s]+", target)[0] - if chapter not in {"omitted", "absorbed", "dropped"} | chapters: + if chapter not in {"omitted", "absorbed", "dropped", "deferred"} | chapters: problems.append(f"no such chapter: {chapter} ({section})") # Prose that cites the source. From 239c056a887d14620b5208283133e3f5b567a340 Mon Sep 17 00:00:00 2001 From: Alexandre Rademaker Date: Wed, 4 Nov 2026 00:38:55 -0300 Subject: [PATCH 20/20] fix(Composition): address review of the composition chapter The glue chapter no longer keeps itself on one page: each section has its own file, page and generated module. The AI-written draft explanations in Quantification move inside the dev notes that disclose them, so the student build no longer publishes them. Two exercise hints are corrected: the disjunction case of mon-up-down needs at least three and at most one, and in left-mon-pattern an element inside B increases n, not m. The cue on van Benthem's theorem allows self-loops. In ModelChecking, lf2 and lf3 are live Lean again. AI usage: Claude Code (Claude Opus 5.5) made these changes from a Copilot review, at the author's request; the author reviewed them. --- CSwL/Composition.lean | 1 - CSwL/Composition/Interpretation.lean | 1 + CSwL/Composition/Quantification.lean | 65 +++++++++++++++------------- CSwL/Composition/Rules.lean | 1 + CSwL/Composition/TypedMeanings.lean | 1 + CSwL/ModelChecking.lean | 3 +- 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CSwL/Composition.lean b/CSwL/Composition.lean index 607cefa..9878c48 100644 --- a/CSwL/Composition.lean +++ b/CSwL/Composition.lean @@ -15,7 +15,6 @@ open CSwLMeta #doc (Manual) "A composição do significado na língua natural" => %%% tag := "Composition" -htmlSplit := .never file := "Composition" %%% diff --git a/CSwL/Composition/Interpretation.lean b/CSwL/Composition/Interpretation.lean index 0394777..d39a6bd 100644 --- a/CSwL/Composition/Interpretation.lean +++ b/CSwL/Composition/Interpretation.lean @@ -8,6 +8,7 @@ open CSwLMeta #doc (Manual) "Implementando a interpretação semântica" => %%% tag := "comp-interpretation" +file := "Interpretation" %%% ```lean diff --git a/CSwL/Composition/Quantification.lean b/CSwL/Composition/Quantification.lean index c0ec5a2..f7c0230 100644 --- a/CSwL/Composition/Quantification.lean +++ b/CSwL/Composition/Quantification.lean @@ -11,6 +11,7 @@ open CSwLMeta #doc (Manual) "Quantificação" => %%% tag := "comp-quantification" +file := "Quantification" %%% ```lean @@ -703,6 +704,15 @@ Organizar os pares numa árvore ajuda. Cada linha `row k` reúne os casos em que ::: ::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has +A as a first…" to "…both of these objects have property B.", with Figure 7.5. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Texto gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. + Em uma frase como *Todo aluno passou*, o determinante relaciona a restrição `A` (os alunos) e o escopo `B` (quem passou). EXT, CONS e ISOM juntas garantem que o valor de `Q A B` depende só de dois números: `m`, quantos A não são B, e @@ -718,15 +728,6 @@ direita, `n` cresce. Assim, a borda esquerda é "nenhum A é B" e a borda direita é "todo A é B". Para ler uma posição, tome `(1, 2)` na linha 3: há três alunos, um não passou e dois passaram. Se o quantificador tem `+` ali, a frase é verdadeira nessa situação. - -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, "Numerical Trees", from "Suppose a quantifier Q has -A as a first…" to "…both of these objects have property B.", with Figure 7.5. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Texto gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. ::: :::: @@ -827,6 +828,15 @@ def patternTree (k : Nat) (q : Nat → Nat → Bool) : ::: ::::full +:::dev BeforeNextRelease +TODO: translate CSwFP/7.2, from "To get used to these representations…" to +the end of Exercise 7.3, without the exercises themselves. +::: + +:::dev "Claude Opus 5.5" (year := 2026) +Comentário gerado por IA. É um rascunho de explicação, não uma tradução do +CSwFP. + Alguns padrões. *All* ($`m = 0`) tem `+` só na borda direita, porque nenhum A fica fora de B. *No* ($`n = 0`) tem `+` só na borda esquerda. *Less than half* ($`n < m`) tem, na linha 2, `+` em `(2, 0)`, `-` em `(1, 1)` e `(0, 2)`. @@ -836,15 +846,6 @@ um universo e uma propriedade. Para cada `(m, n)`, ele monta um universo concreto `[1, …, m + n]` em que exatamente `n` elementos têm a propriedade, e pergunta ao quantificador. Qualquer universo com essas contagens serve (ISOM). - -:::dev BeforeNextRelease -TODO: translate CSwFP/7.2, from "To get used to these representations…" to -the end of Exercise 7.3, without the exercises themselves. -::: - -:::dev "Claude Opus 5.5" (year := 2026) -Comentário gerado por IA. É um rascunho de explicação, não uma tradução do -CSwFP. ::: :::: @@ -896,14 +897,6 @@ tag := "comp-num-repr" ::: ::::full -Esta subseção tira a conclusão da anterior. Um padrão na árvore é um -subconjunto dos pares de naturais. Por isso, o próprio quantificador pode ser -escrito como uma expressão aritmética em `m` e `n`, sem conjuntos e sem -listas: *all* é $`m = 0`, *no* é $`n = 0`, *at least k* é $`n \geq k` e *at -most k* é $`n \leq k`. Em Lean, essa expressão tem o tipo `NumQuant`, que é -justamente o tipo do argumento de `patternTree`. Por isso todo `NumQuant` pode -ser desenhado. - :::dev BeforeNextRelease TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from "The pairs of cardinals that characterize…" to the definitions of `allNum`, @@ -913,6 +906,14 @@ TODO: translate CSwFP/7.2, "Logical Representations for Quantifiers", from :::dev "Claude Opus 5.5" (year := 2026) Comentário gerado por IA. É um rascunho de explicação, não uma tradução do CSwFP. + +Esta subseção tira a conclusão da anterior. Um padrão na árvore é um +subconjunto dos pares de naturais. Por isso, o próprio quantificador pode ser +escrito como uma expressão aritmética em `m` e `n`, sem conjuntos e sem +listas: *all* é $`m = 0`, *no* é $`n = 0`, *at least k* é $`n \geq k` e *at +most k* é $`n \leq k`. Em Lean, essa expressão tem o tipo `NumQuant`, que é +justamente o tipo do argumento de `patternTree`. Por isso todo `NumQuant` pode +ser desenhado. ::: :::: @@ -1443,7 +1444,8 @@ theorem orNum_monDown (q₁ q₂ : NumQuant) Mostre que, combinando um quantificador MON↑ com um MON↓, nada se pode garantir: nem a conjunção nem a disjunção são sempre MON↑ ou MON↓. -Dica: use *at least one* e *at most three*. Antes de provar, desenhe os +Dica: para a conjunção, use *at least one* e *at most three*; para a +disjunção, *at least three* e *at most one*. Antes de provar, desenhe os padrões da conjunção e da disjunção com `patternTree`. ```lean @@ -1508,8 +1510,8 @@ Defina `UpMonNum q` e `DownMonNum q`, as formas do padrão de um quantificador ↑MON e de um ↓MON. Depois, prove que *some* e *not all* são ↑MON, e que *all* e *no* são ↓MON. -Dica: acrescentar um elemento a `A` aumenta `m` ou `n` em um, conforme o -elemento esteja ou não em `B`. +Dica: acrescentar um elemento a `A` aumenta em um `n`, se o elemento está +em `B`, ou `m`, se não está. ```lean def UpMonNum (q : NumQuant) : Prop := @@ -1683,8 +1685,9 @@ theorem langOf_allNum : computa `q`. - Os quantificadores definíveis em primeira ordem (com $`\forall`, $`\exists`, igualdade e os predicados da restrição e do escopo) são - exatamente os computados por um autômato finito acíclico e invariante - por permutação (van Benthem). + exatamente os computados por um autômato finito invariante por + permutação e sem ciclos, exceto laços que levam um estado a ele mesmo + (van Benthem). - *An even number of* pede um autômato com ciclo. *Most* não tem autômato finito nenhum: é preciso memória para comparar $`|A - B|` e $`|A \cap B|`. Nenhum dos dois é definível em primeira ordem. diff --git a/CSwL/Composition/Rules.lean b/CSwL/Composition/Rules.lean index 6d451a0..6e29fa3 100644 --- a/CSwL/Composition/Rules.lean +++ b/CSwL/Composition/Rules.lean @@ -7,6 +7,7 @@ open CSwLMeta #doc (Manual) "As regras do jogo" => %%% tag := "comp-rules" +file := "Rules" %%% :::terse diff --git a/CSwL/Composition/TypedMeanings.lean b/CSwL/Composition/TypedMeanings.lean index 2dda9f3..034719b 100644 --- a/CSwL/Composition/TypedMeanings.lean +++ b/CSwL/Composition/TypedMeanings.lean @@ -8,6 +8,7 @@ open CSwLMeta #doc (Manual) "Significados tipados para a língua natural" => %%% tag := "comp-typed-meanings" +file := "TypedMeanings" %%% ```lean diff --git a/CSwL/ModelChecking.lean b/CSwL/ModelChecking.lean index d0822f7..d08c4d3 100644 --- a/CSwL/ModelChecking.lean +++ b/CSwL/ModelChecking.lean @@ -694,7 +694,7 @@ example : lfSent s1 = l0 := by Outros dois exemplos de fórmulas. -``` +```lean def lf2 : LF := lfSent (.sent (.npDetRel .the (.rcnObj .wizard .that .dorothy .admired)) @@ -705,7 +705,6 @@ def lf3 : LF := (.rcnSubj .princess .that (.vpTrans .helped .alice))) .shuddered) - ```