Repository navigation
Expand file tree
/
Copy pathDescriptiveComplexity.lean
More file actions
3198 lines (3128 loc) · 216 KB
/
Copy pathDescriptiveComplexity.lean
File metadata and controls
3198 lines (3128 loc) · 216 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/-
Copyright (c) 2026 Pierre Senellart. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Pierre Senellart
-/
import DescriptiveComplexity.Syntax
import DescriptiveComplexity.Vocabulary
import DescriptiveComplexity.Interpretation
import DescriptiveComplexity.Ordered
import DescriptiveComplexity.Composition
import DescriptiveComplexity.OrderedComposition
import DescriptiveComplexity.OrderedReorder
import DescriptiveComplexity.Complexity
import DescriptiveComplexity.Encoding
import DescriptiveComplexity.Encoding.BinarySubsetSum
import DescriptiveComplexity.Encoding.UnaryBlowup
import DescriptiveComplexity.Decoding
import DescriptiveComplexity.SecondOrder
import DescriptiveComplexity.Block
import DescriptiveComplexity.SecondOrderLift
import DescriptiveComplexity.SecondOrderPull
import DescriptiveComplexity.SecondOrderOrdered
import DescriptiveComplexity.SecondOrderParam
import DescriptiveComplexity.SecondOrderMerge
import DescriptiveComplexity.SecondOrderHorn
import DescriptiveComplexity.SecondOrderHornPull
import DescriptiveComplexity.ClauseDischarge
import DescriptiveComplexity.SecondOrderKrom
import DescriptiveComplexity.SecondOrderKromPull
import DescriptiveComplexity.SecondOrderNew
import DescriptiveComplexity.Relativize
import DescriptiveComplexity.SecondOrderNewBdd
import DescriptiveComplexity.SecondOrderNewBddPull
import DescriptiveComplexity.ParamFormula
import DescriptiveComplexity.SubstFormula
import DescriptiveComplexity.SecondOrderNewCount
import DescriptiveComplexity.SecondOrderNewMeans
import DescriptiveComplexity.SecondOrderNewMeansB
import DescriptiveComplexity.SecondOrderNewExp
import DescriptiveComplexity.SecondOrderNewRead
import DescriptiveComplexity.SecondOrderNewPoint
import DescriptiveComplexity.SecondOrderNewExpPull
import DescriptiveComplexity.SecondOrderNewExpBuild
import DescriptiveComplexity.SecondOrderNewExpConv
import DescriptiveComplexity.SecondOrderNewPull
import DescriptiveComplexity.SecondOrderNewOrdered
import DescriptiveComplexity.RecursivelyEnumerable
import DescriptiveComplexity.LogSpace
import DescriptiveComplexity.TwoCnf
import DescriptiveComplexity.TransitiveClosure
import DescriptiveComplexity.TransitiveClosureKrom
import DescriptiveComplexity.KromImplication
import DescriptiveComplexity.KromTransitiveClosure
import DescriptiveComplexity.InductiveCounting
import DescriptiveComplexity.TransitiveClosureCompl
import DescriptiveComplexity.ImmermanSzelepcsenyi
import DescriptiveComplexity.TransitiveClosureReach
import DescriptiveComplexity.TransitiveClosureDet
import DescriptiveComplexity.TransitiveClosurePull
import DescriptiveComplexity.DetLogSpace
import DescriptiveComplexity.HeadAutomaton
import DescriptiveComplexity.HeadProgram
import DescriptiveComplexity.HeadEval
import DescriptiveComplexity.HeadCapture
import DescriptiveComplexity.WalkBudget
import DescriptiveComplexity.HeadLex
import DescriptiveComplexity.HeadCaptureDet
import DescriptiveComplexity.HeadArith
import DescriptiveComplexity.HeadEvalArith
import DescriptiveComplexity.HeadBit
import DescriptiveComplexity.HeadEvalBit
import DescriptiveComplexity.Iterate
import DescriptiveComplexity.FixedPoint
import DescriptiveComplexity.OrderWalk
import DescriptiveComplexity.FixedPointHorn
import DescriptiveComplexity.FixedPointStep
import DescriptiveComplexity.SecondOrderBlockHom
import DescriptiveComplexity.FixedPointInflationary
import DescriptiveComplexity.FixedPointInflationaryLFP
import DescriptiveComplexity.FixedPointPartial
import DescriptiveComplexity.Hierarchy
import DescriptiveComplexity.Counting
import DescriptiveComplexity.Counting.SharpP
import DescriptiveComplexity.Counting.Relativized
import DescriptiveComplexity.Counting.Class
import DescriptiveComplexity.Counting.Sized
import DescriptiveComplexity.Counting.SizedPairs
import DescriptiveComplexity.Counting.Post
import DescriptiveComplexity.Counting.Encoding
import DescriptiveComplexity.Counting.PossibleWorlds
import DescriptiveComplexity.Counting.Probability
import DescriptiveComplexity.Counting.FP
import DescriptiveComplexity.Counting.DigitDefinable
import DescriptiveComplexity.Counting.Digits.SetArith
import DescriptiveComplexity.Counting.Digits.Tower
import DescriptiveComplexity.Counting.Digits.Formulas
import DescriptiveComplexity.Counting.Digits.Closure
import DescriptiveComplexity.Counting.Digits.SumSweep
import DescriptiveComplexity.Counting.Digits.ProdSem
import DescriptiveComplexity.Counting.Digits.ProdSweep
import DescriptiveComplexity.Counting.Digits.Bounds
import DescriptiveComplexity.Counting.Digits.Term
import DescriptiveComplexity.Counting.Digits.NormalForm
import DescriptiveComplexity.Counting.Independence
import DescriptiveComplexity.Counting.WeightedFacts
import DescriptiveComplexity.Counting.QuantitativeBinders
import DescriptiveComplexity.Counting.WeightedTerms
import DescriptiveComplexity.Problems.HornSat.Number
import DescriptiveComplexity.Problems.HornSat.NumberHardness
import DescriptiveComplexity.Problems.MachineNumber
import DescriptiveComplexity.Counting.Quantitative
import DescriptiveComplexity.Counting.QuantitativePull
import DescriptiveComplexity.Counting.Reduction
import DescriptiveComplexity.Counting.Restrict
import DescriptiveComplexity.Counting.QSO
import DescriptiveComplexity.Counting.QSOWitness
import DescriptiveComplexity.Counting.QSOQuantifiers
import DescriptiveComplexity.Counting.QSOSharpP
import DescriptiveComplexity.Counting.RelClosure
import DescriptiveComplexity.Counting.Subtractive
import DescriptiveComplexity.Counting.KernelPair
import DescriptiveComplexity.Counting.DecisionClasses
import DescriptiveComplexity.Counting.UnitWeights
import DescriptiveComplexity.Counting.WeightedWorlds
import DescriptiveComplexity.Permanent.Basic
import DescriptiveComplexity.Permanent.Minor
import DescriptiveComplexity.Permanent.Attach
import DescriptiveComplexity.Permanent.Xor
import DescriptiveComplexity.Permanent.AttachAll
import DescriptiveComplexity.Permanent.Flat
import DescriptiveComplexity.Permanent.CycNext
import DescriptiveComplexity.Permanent.Ladder
import DescriptiveComplexity.Permanent.Widths
import DescriptiveComplexity.SecondOrderTransitiveClosure
import DescriptiveComplexity.SecondOrderTransitiveClosurePull
import DescriptiveComplexity.PSpace
import DescriptiveComplexity.SecondOrderTransitiveClosureFree
import DescriptiveComplexity.FixedPointPartialSpace
import DescriptiveComplexity.FixedPointStepRel
import DescriptiveComplexity.FixedPointParam
import DescriptiveComplexity.FixedPointPartialMachine
import DescriptiveComplexity.AbiteboulVianuOrdered
import DescriptiveComplexity.Invariant.Pebble
import DescriptiveComplexity.Invariant.EquivK
import DescriptiveComplexity.Invariant.Stages
import DescriptiveComplexity.Invariant.OrderedPebble
import DescriptiveComplexity.Invariant.Structure
import DescriptiveComplexity.Invariant.Simulation
import DescriptiveComplexity.Invariant.OrderDef
import DescriptiveComplexity.Invariant.Backward
import DescriptiveComplexity.Invariant.Bare
import DescriptiveComplexity.Invariant.TwoPebble
import DescriptiveComplexity.Invariant.TwoInvariance
import DescriptiveComplexity.Invariant.TwoStages
import DescriptiveComplexity.FirstOrderDefinable
import DescriptiveComplexity.FirstOrderPull
import DescriptiveComplexity.Arithmetic
import DescriptiveComplexity.ArithmeticDefinable
import DescriptiveComplexity.ArithmeticFixedPoint
import DescriptiveComplexity.LogTime.Definable
import DescriptiveComplexity.LogTime.Bits
import DescriptiveComplexity.LogTime.Fields
import DescriptiveComplexity.LogTime.Pow
import DescriptiveComplexity.LogTime.Small
import DescriptiveComplexity.LogTime.Translate
import DescriptiveComplexity.LogTime.BitSum.Sizes
import DescriptiveComplexity.LogTime.BitSum.Blocks
import DescriptiveComplexity.LogTime.BitSum.Counter
import DescriptiveComplexity.LogTime.BitSum.Ones
import DescriptiveComplexity.LogTime.BitSum.Table
import DescriptiveComplexity.LogTime.BitSum.Sum
import DescriptiveComplexity.LogTime.BitSum.Level2
import DescriptiveComplexity.LogTime.BitSum.Level1
import DescriptiveComplexity.LogTime.BitSum.Columns
import DescriptiveComplexity.LogTime.BitSum.Times
import DescriptiveComplexity.LogTime.Machine
import DescriptiveComplexity.LogTime.BitLogic
import DescriptiveComplexity.LogTime.Simulate
import DescriptiveComplexity.LogTime.Arith
import DescriptiveComplexity.LogTime.Compile
import DescriptiveComplexity.LogTime
import DescriptiveComplexity.Games.Ehrenfeucht
import DescriptiveComplexity.Games.Bare
import DescriptiveComplexity.Games.Distance
import DescriptiveComplexity.Games.LinearOrder
import DescriptiveComplexity.TransitiveClosureFO
import DescriptiveComplexity.FixedPointOrderTransfer
import DescriptiveComplexity.FixedPointStratify
import DescriptiveComplexity.AbiteboulVianu
import DescriptiveComplexity.PSpaceCompl
import DescriptiveComplexity.PSpaceHierarchy
import DescriptiveComplexity.Exponential
import DescriptiveComplexity.Difference
import DescriptiveComplexity.Padding
import DescriptiveComplexity.EqPattern
import DescriptiveComplexity.OccurrenceOrder
import DescriptiveComplexity.OccurrencePrefix
import DescriptiveComplexity.OccurrenceFormulas
import DescriptiveComplexity.OccurrenceSlack
import DescriptiveComplexity.OccurrenceVar
import DescriptiveComplexity.Numbers
import DescriptiveComplexity.Machines
import DescriptiveComplexity.IsoGadget
import DescriptiveComplexity.TwoCopies
import DescriptiveComplexity.GadgetDouble
import DescriptiveComplexity.Degree
import DescriptiveComplexity.Problems
import DescriptiveComplexity.ClassDegrees
import DescriptiveComplexity.SecondOrderRelPull
import DescriptiveComplexity.FixedPointReduction
import DescriptiveComplexity.FixedPointReductionComposition
import DescriptiveComplexity.FixedPointExpand
import DescriptiveComplexity.FixedPointReductionClosure
import DescriptiveComplexity.FixedPointExpandLevels
import DescriptiveComplexity.FixedPointReductionStrict
import DescriptiveComplexity.TransitiveClosureParam
import DescriptiveComplexity.TransitiveClosureReduction
import DescriptiveComplexity.TransitiveClosureReductionDet
import DescriptiveComplexity.TransitiveClosureParamPull
import DescriptiveComplexity.TransitiveClosureTower
import DescriptiveComplexity.TransitiveClosureReductionComposition
import DescriptiveComplexity.TransitiveClosureReductionStrict
import DescriptiveComplexity.TransitiveClosureDecide
import DescriptiveComplexity.TransitiveClosureDecideFormula
import DescriptiveComplexity.TransitiveClosureDecideReach
import DescriptiveComplexity.TransitiveClosureDecideReachDet
import DescriptiveComplexity.TransitiveClosureFlatten
import DescriptiveComplexity.TransitiveClosureSentenceDecide
import DescriptiveComplexity.TransitiveClosureReductionClosure
import DescriptiveComplexity.TransitiveClosureReductionTrans
import DescriptiveComplexity.FixedPointReductionHierarchy
import DescriptiveComplexity.FixedPointStratifyPartial
import DescriptiveComplexity.FixedPointReductionSpace
import DescriptiveComplexity.Computability
import DescriptiveComplexity.Examples
-- The rows of the catalog table below cannot be broken across lines.
set_option linter.style.longLine false
/-!
# Descriptive complexity in Lean 4
A library for descriptive complexity built on Mathlib's `ModelTheory`:
machine-model-free hardness reductions and a logically-defined polynomial
hierarchy, in the style of Immerman's *Descriptive Complexity*
([Immerman 1999][immerman1999descriptive]).
Complexity theory is largely absent from Mathlib because formalizing a model
of computation with resource bounds is hard. The observation this library
rests on is that many classical NP-hardness reductions do not need the full
strength of a Turing machine: they are *first-order expressible*. Classically,
an FO reduction is computable in AC⁰ ⊆ LOGSPACE ⊆ PTIME, so exhibiting one is
strictly stronger than exhibiting a Karp reduction
([Karp 1972][karp1972reducibility]), while needing no machine model at all –
only first-order logic, which Mathlib already provides.
This page is the high-level map of the library, part by part. The `README`
gives the general pitch; the paper
[Senellart and Gnatenko 2026][senellart2026descriptive] presents the design and
the main results; the worked examples in
`DescriptiveComplexity.Examples.ConjunctiveQueries` (conjunctive-query
evaluation and containment) and `DescriptiveComplexity.Examples.GraphCrawling`
(Web data acquisition, with a cardinality threshold, a reachability
certificate and an ordered reduction) are the hands-on tutorials, with
`DescriptiveComplexity.Examples.ProbabilisticQueries` (query evaluation over
probabilistic databases, a hard query and an easy one) for the counting side;
individual declarations are documented on their own pages.
## The framework: problems, interpretations, reductions
* `DescriptiveComplexity.Interpretation` – a `DescriptiveComplexity.DecisionProblem`
is an isomorphism-invariant property of finite structures of a *relational*
language (invariance is baked into the notion, as is standard in descriptive
complexity; so is relationality, via an `IsRelational` instance argument –
the standing convention of the field, so every class equality below is a
statement about relational problems). A
`DescriptiveComplexity.FOInterpretation` is a tagged,
`dim`-dimensional first-order interpretation of one language in another,
and a `DescriptiveComplexity.FOReduction` (notation `P ≤ᶠᵒ Q`) is one that
maps yes-instances exactly to yes-instances, on the *finite* nonempty
structures – the only ones membership and hardness ever read. Tags replace
the linear order that textbook FO reductions use to encode constantly-many
sorts of elements.
* `DescriptiveComplexity.Composition` – the pullback of a formula through an
interpretation and the composition of interpretations, giving reflexivity
and transitivity of `≤ᶠᵒ` (a `Preorder` on problems, usable in `calc`).
* `DescriptiveComplexity.Ordered` and
`DescriptiveComplexity.OrderedComposition` – reductions over the ordered
expansion of the source language, `DescriptiveComplexity.OrderedFOReduction`
(notation `P ≤ᶠᵒ[≤] Q`): order-invariant FO(≤) reductions, correct on every
finite linearly ordered input. This is the standard notion of the field and
the home of gadget constructions that genuinely need an order.
`DescriptiveComplexity.OrderedReorder` lets such a reduction replace the
order of its input by any linear order it can define
(`DescriptiveComplexity.FOInterpretation.reorder`), which is how a problem
reading its output in the order of the universe is reached from one that
carries the order of significance as a relation.
* Logarithmic-space and polynomial-time reductions are *stronger* notions, and
need a logic capturing those classes to state: they appear below, as
`DescriptiveComplexity.TCReduction` (notation `P ≤ᵗᶜ Q`) and
`DescriptiveComplexity.LFPReduction` (notation `P ≤ˡᶠᵖ Q`), once the walk
and fixed-point layers are in place.
## Writing a problem down
Three authoring aids, used by the tutorials of
`DescriptiveComplexity.Examples` and by the catalog. They are macros and
commands: what they elaborate to is what one would have written by hand, so
they change nothing that reads the declarations they produce.
* `DescriptiveComplexity.Syntax` – a surface syntax for formulas, `fo%`.
Mathlib's `FirstOrder.Language.BoundedFormula` is locally nameless, so a
variable bound by the `k`-th enclosing block is written `Sum.inr i` under
`k - 1` applications of `Sum.inl`; `fo% ∀ x y, R(x, y) → ∃ z, S(y, z)` names
the variables instead and elaborates to the same `Formula.iAlls` term.
* `DescriptiveComplexity.Vocabulary` – `fo_language`, declaring a relational
language from a list of `name : arity` lines: the symbol inductive, the
`Language`, its `IsRelational` instance and the abbreviation naming each
symbol; and `fo_predicates`, the predicates reading those symbols off a
structure.
* `DescriptiveComplexity.Block` – `fo_block`, declaring a
`DescriptiveComplexity.SOBlock` and the vocabulary of a kernel: the index
type with its `Fintype` instance, the block, the summed language, and one
symbol of the sum for each symbol of the base vocabulary and each relation
variable.
## The abstract complexity layer
* `DescriptiveComplexity.Complexity` – `DescriptiveComplexity.ComplexityClass`,
with membership, hardness and completeness, closed by construction under
(ordered) FO reductions. Membership and hardness depend only on the
*finite* instances of a problem, making explicit that these statements say
nothing about infinite structures.
* `DescriptiveComplexity.Encoding` – bringing your own instance types: a
`DescriptiveComplexity.Encoding` bundles a concrete instance type, its declared
size, a computable encoding into finite structures, and polynomial bounds
*both ways* between size and universe – no padding, no compression – so an
encoding cannot be built size-dishonest. Semantic agreement is the separate
predicate `DescriptiveComplexity.Encoding.Faithful`. That the bounds have
teeth is a theorem: no unary encoding of subset-sum passes them
(`DescriptiveComplexity.no_unary_encoding`, in
`DescriptiveComplexity.Encoding.UnaryBlowup`).
* `DescriptiveComplexity.Encoding.BinarySubsetSum` – the positive contrast,
worked out in full and in both directions. The honest binary encoding of a
list of weights and a target (`DescriptiveComplexity.binarySubsetSumEncoding`),
its decoding lemmas and `DescriptiveComplexity.binarySubsetSumEncoding_faithful`
make `DescriptiveComplexity.knapsack_NP_complete` a statement about concrete
lists of binary-written numbers; `DescriptiveComplexity.bwDecoding` reads
*hardness* back the same way, and needs no well-formedness condition, a
structure whose order is not linear being a definite no-instance. Both rest
on `DescriptiveComplexity.hasSubsetSum_iff_index`, which reads the problem
along any injective indexing of the items, and on the
`DescriptiveComplexity.selection_toIndex`/`selection_ofIndex` pair that any
other problem quantifying over selections of items reuses.
* `DescriptiveComplexity.Decoding` – the decoding direction, for reading
*hardness* concretely: well-formedness conditions as decision problems
(`DescriptiveComplexity.DecisionProblem.ofSentence`, restricting a problem to
its non-junk instances as `W ⊓ P` with one-line upgrades of existing
completeness proofs), and computable decodings
(`DescriptiveComplexity.Decoding`) from concretely presented structures back
to concrete instances, with the same executable hygiene as the encoders.
Both tutorials – `DescriptiveComplexity.Examples.ConjunctiveQueries` and
`DescriptiveComplexity.Examples.GraphCrawling` – open with a concrete
instance type and its bundled encoding, and close the loop with a decoder
and a well-formed completeness theorem;
`DescriptiveComplexity.Problems.SubgraphIso.Encoding` does the same for a
problem of the catalog, with a decoder that needs no well-formedness
condition at all.
* `DescriptiveComplexity.Degree` – completeness *without a class*: the downward
closure `DescriptiveComplexity.ComplexityClass.below Q₀` of a fixed problem
under ordered FO reductions is itself a `ComplexityClass`, so
`(below Q₀).Complete P` is literally “`P` is `Q₀`-complete”, with no logic
anywhere – the notion behind “GI-complete”
(`DescriptiveComplexity.GI`, the degree of `DescriptiveComplexity.GraphIso`).
Hardness needs no new proof: `DescriptiveComplexity.CofinalHard` is already
parameterized by an arbitrary membership predicate. Completeness for a degree
is mutual reducibility
(`DescriptiveComplexity.ComplexityClass.complete_below_iff`), and the degree
depends only on the degree
(`DescriptiveComplexity.ComplexityClass.below_congr`). The construction is
checked against the classes that have complete problems, in
`DescriptiveComplexity.ClassDegrees`: `NP = below SAT`,
`coNP = below TAUT`, `PTIME = below HORN-SAT`, `NL = below 2SAT` and
`RE = below FINSAT` (`DescriptiveComplexity.NP_eq_below_sat` and siblings),
so “SAT-hardness is NP-hardness” is a lemma rather than folklore.
## The polynomial hierarchy, defined logically
* `DescriptiveComplexity.SecondOrder` (with `…Lift`, `…Pull`, `…Ordered`) –
existential/universal second-order definability with `k` quantifier-block
alternations.
* `DescriptiveComplexity.Hierarchy` – the levels `Σₖᵖ`/`Πₖᵖ` and `PH` as
complexity classes, via Fagin's ([Fagin 1974][fagin1974generalized]) and
Stockmeyer's ([Stockmeyer 1976][stockmeyer1976polynomial]) theorems. The
level inclusions and the duality `Πₖᵖ = co-Σₖᵖ` are proved, not assumed.
Level 0 is `DescriptiveComplexity.PTIME`, polynomial time, defined by the Horn
fragment SO-Horn (below); the level-0 statements that would amount to
closure under complement are the one thing the fragment does not give, and
are restricted to levels `≥ 1`. Everything remains a definition or a
theorem: the library declares **no axioms** (check with `#print axioms`).
## Polynomial time, by the Horn fragment
* `DescriptiveComplexity.SecondOrderHorn` – SO-Horn ([Grädel
1992][gradel1992capturing]): existential second-order logic whose kernel is a
conjunction of Horn clauses in the quantified relation variables, the
fragment that captures polynomial time on ordered structures. The kernel is
represented as *data* (`DescriptiveComplexity.HornProgram`, a list of clauses with a
first-order guard over the ordered expansion, body atoms and an optional
head), which is Grädel's clausal normal form and what a reduction consuming
such a definition needs to read.
* `DescriptiveComplexity.SecondOrderHornPull` – the pullback of an SO-Horn definition
through an interpretation *stays Horn*: the Horn condition constrains only
the second-order atoms, and an interpretation rewrites the
input-vocabulary ones, which live in the guard. This closure is what makes
`DescriptiveComplexity.PTIME` (in `DescriptiveComplexity.Hierarchy`) a genuine complexity
class, and hence level 0 of the hierarchy, *defined* by SO-Horn definability
just as NP is defined by `Σ₁`-definability. HORN-SAT is PTIME-complete – hard
by the Horn discharge, and a member by the Horn program that computes unit
propagation along the order – which also yields the four inclusions of level
0 into level 1, and with them the monotonicity of the hierarchy
(`DescriptiveComplexity.sigmaP_mono`, `DescriptiveComplexity.piP_mono`): the padding
step of `DescriptiveComplexity.Hierarchy` climbs only from level 1 up, its level-0
step being the Horn discharge. See `DescriptiveComplexity.Problems.HornSat` for what
is and is not claimed.
* `DescriptiveComplexity.Difference` – **the class DP**
(`DescriptiveComplexity.DP`), the conjunctions of an NP condition and a coNP one
([Papadimitriou & Yannakakis 1984][papadimitriou1984complexity]), with
`NP ⊆ DP` and `coNP ⊆ DP`. Closure under reductions is the interesting part:
the two halves of a DP definition are individually *not* order-invariant, so
an ordered reduction cannot be pulled back half by half in the usual way. The
order is instead quantified in opposite directions on the two sides –
existentially on the `Σ` half, universally on the `Π` half – whose conjunction
is again the pullback, each half then handled by the sentence-level order
elimination of `DescriptiveComplexity.SecondOrderOrdered`. The upper bounds
`DP ⊆ Σ₂ᵖ ∩ Π₂ᵖ` merge the two kernels into one alternation, in either block
order. SAT-UNSAT, the canonical DP problem, is defined in
`DescriptiveComplexity.Problems.SatUnsat` and proved DP-complete: *in* DP by
projecting each of its two sides onto a plain CNF instance and inheriting
definability from SAT, and DP-hard in
`DescriptiveComplexity.Problems.SatUnsat.Hardness` by running the Cook–Levin
discharge of the `Σ₁` half and of the complement of the `Π₁` half side by side
into one paired instance.
* `DescriptiveComplexity.FixedPoint` – FO(LFP) ([Immerman
1986][immerman1986relational]; [Vardi 1982][vardi1982complexity]), in the same
clausal style: a rule system defining a least fixed point, plus an
*unrestricted* first-order output sentence read at it. Because the output may
negate fixed-point atoms, FO(LFP) definability is closed under complement by
construction (`DescriptiveComplexity.LFPDefinable.compl`) – the one thing the Horn
fragment cannot do head-on – and every SO-Horn definition transports into it
(`DescriptiveComplexity.SigmaSOHornDefinable.lfpDefinable`).
* `DescriptiveComplexity.FixedPointHorn` – the converse translation, the hard half of
Grädel's equivalence: every FO(LFP) definition compiles back into the Horn
fragment, by deriving the *complement* of the fixed point stage by stage
along the order and evaluating the output sentence clausewise
(`DescriptiveComplexity.LFPDefinable.sigmaSOHornDefinable`). The two formalisms are
therefore interchangeable
(`DescriptiveComplexity.lfpDefinable_iff_sigmaSOHornDefinable`), which read against
the definition of the class is **Immerman–Vardi**, `PTIME = FO(≤, LFP)`
(`DescriptiveComplexity.lfpDefinable_iff_mem_PTIME`); SO-Horn definability
is closed under complement (`DescriptiveComplexity.SigmaSOHornDefinable.compl`), and
level 0 of the hierarchy collapses: `PiP 0 = SigmaP 0`
(`DescriptiveComplexity.piP_zero_eq`), polynomial time closed under complement. The
order-walking machinery shared with the HORN-SAT program lives in
`DescriptiveComplexity.OrderWalk`.
## The inflationary and partial fixed points
* `DescriptiveComplexity.FixedPointStep` – **one iteration skeleton for
FO(IFP) and FO(PFP)** (`DescriptiveComplexity.StepDef`): a block of relation
variables, one unrestricted first-order step formula per variable, an output
sentence. The two logics differ only in what a step does with the previous
stage – accumulate into it or replace it – so the stages, their
stabilization on finite structures (through the orbit pigeonholes of
`DescriptiveComplexity.Iterate`, a file free of library concepts), their
transport along isomorphisms and their pullback through an interpretation
are all built once, on `DescriptiveComplexity.StepDef.next` alone.
* `DescriptiveComplexity.SecondOrderBlockHom` – **morphisms of blocks**: an
arity-preserving map of relation variables induces a morphism of the
blocks' vocabularies, along which sentences transport
(`DescriptiveComplexity.SOBlock.realize_homSentence`) – the bookkeeping for
reading a formula written for one block inside a larger block containing a
copy of it, which the translations between the fixed-point logics need.
* `DescriptiveComplexity.FixedPointInflationary` – **FO(IFP)**
([Gurevich–Shelah 1986][gurevich1986fixed]; [Abiteboul–Vianu
1989][abiteboul1989fixpoint]): iterate inflationarily, read the output at
the limit. Ordered (`DescriptiveComplexity.IFPDefinable`) and order-free
(`DescriptiveComplexity.IFPDefinableFree`) definability are kept apart – for
the fixed-point logics, unlike for SO(TC), the two must differ or the
Abiteboul–Vianu theorem would be trivial. Closed under complement by
construction and under (ordered) reductions; FO(LFP) embeds by reading a
rule system as one simultaneous step
(`DescriptiveComplexity.LFPDefinable.ifpDefinable`), which needs no
positivity because inflation supplies the monotonicity.
* `DescriptiveComplexity.FixedPointInflationaryLFP` – **FO(≤, IFP) = FO(LFP)**
(`DescriptiveComplexity.ifpDefinable_iff_lfpDefinable`), whence the capture
theorem **FO(≤, IFP) = PTIME**
(`DescriptiveComplexity.ifpDefinable_iff_mem_PTIME`): an inflationary
definition compiles back into FO(LFP) by walking the stages
(`DescriptiveComplexity.FixedPointHorn`'s stage apparatus) with a *dual*
positive evaluator deriving truth and falsity of the step formulas'
subformulas per stage – inflation is what makes the complement of a stage
advance positively, which is precisely why PFP admits no such translation
and goes to SO(TC) instead. The output sentence survives unchanged modulo
the block injection, which is why the target is FO(LFP) and not SO-Horn.
* `DescriptiveComplexity.FixedPointPartial` – **FO(PFP)** ([Abiteboul–Vianu
1989][abiteboul1989fixpoint]): iterate by replacement, read the output at
the first stable stage – requiring convergence, a divergence convention
chosen deliberately and compared precisely with the textbook one
(`DescriptiveComplexity.StepDef.realize_pfpValue_iff`). FO(IFP) is contained
in it by disjoining each variable's own atom onto its step
(`DescriptiveComplexity.StepDef.inflate`) – the easy inclusion of
Abiteboul–Vianu, in both the ordered and the order-free form. The PSPACE
capture lives with the other PSPACE files, below.
* `DescriptiveComplexity.Invariant.Pebble`,
`DescriptiveComplexity.Invariant.EquivK`,
`DescriptiveComplexity.Invariant.Stages` – **the `≡ᵏ`-invariant layer**:
the `k`-pebble refinement over an abstract initial relation
(`DescriptiveComplexity.EquivK`, a greatest fixed point with its coinduction
principle `DescriptiveComplexity.le_equivK`, expansion lemma
`DescriptiveComplexity.equivK_inf_eq` and pair-substructure closure
`DescriptiveComplexity.equivK_of_pairSub`), its instantiation at agreement
on the atomic type over a relational structure – relative to a family of
relation symbols, since a definition only mentions finitely many
(`DescriptiveComplexity.StepDef.exists_usesRels`) – the `k`-variable
invariance lemma (`DescriptiveComplexity.realize_equivK` – a formula with
enough room for its quantifier depth cannot separate `≡ᵏ`-equivalent
tuples; no syntactic `k`-variable fragment is ever defined), and the
`≡ᵏ`-invariance of every inflationary and partial stage of a `StepDef`
within its variable budget
(`DescriptiveComplexity.StepDef.inflLimit_invariant`,
`DescriptiveComplexity.StepDef.partStage_invariant`).
* `DescriptiveComplexity.Invariant.OrderedPebble`,
`DescriptiveComplexity.Invariant.OrderDef` – **the canonical order on
`≡ᵏ`-classes**: the ordered pebble refinement, a strict order on `k`-tuples
growing as the classes split, whose incomparability is stage by stage the
pebble refinement (`DescriptiveComplexity.ordStage_invariant`) and at the
limit `≡ᵏ` (`DescriptiveComplexity.incompRel_ordK_eq`) – a linear order on
the classes, *inflationary by construction*, so computed by one relation
variable of a simultaneous induction (`DescriptiveComplexity.ordStepDef`,
with `DescriptiveComplexity.inflStage_ordStepDef` matching the two
round for round) and canonical because inflationary stages transport along
isomorphisms.
* `DescriptiveComplexity.Invariant.Structure`,
`DescriptiveComplexity.Invariant.Simulation`,
`DescriptiveComplexity.Invariant.Backward` – **the invariant structure
`Iᵏ A`** (`DescriptiveComplexity.InvMap`: the `≡ᵏ`-classes of `k`-tuples,
with atomic-type bits, substitution and rearrangement relations, and the
linear order induced by the canonical order,
`DescriptiveComplexity.invLinearOrder`) **and the two-way simulation**: the
pebble compiler (`DescriptiveComplexity.pebbleCompile`) runs a `k`-variable
induction over `A` on the classes –
`DescriptiveComplexity.StepDef.pfpHolds_invStepDef`, every quantifier
spending a pebble along a substitution relation – and the class compiler
(`DescriptiveComplexity.backCompile`) runs an induction over the *ordered*
invariant vocabulary back on `A`, each class variable becoming `k` element
variables and the order read off the (frozen) order variable
(`DescriptiveComplexity.StepDef.ifpHolds_backStepDef`).
* `DescriptiveComplexity.FixedPointStratify` – **stratification**: nested
inflationary inductions are one induction
(`DescriptiveComplexity.StepDef.ifpHolds_stratify`) – the second stratum,
a `StepDef` over the base vocabulary *expanded by the first stratum's
block*, is gated on an arity-`0` variable derived exactly when the first
stratum's step formulas add nothing, so it replays its own stages over the
frozen limit.
* `DescriptiveComplexity.FixedPointOrderTransfer` – **order relativization**:
FO(≤, IFP)/FO(≤, PFP) definability of `P` is order-free definability of
`DescriptiveComplexity.DecisionProblem.withOrder P` («the order symbol is a
linear order, and `P` holds on the reduct») over the ordered expansion, and
order-free definability implies ordered definability
(`DescriptiveComplexity.StepDef.liftOrder`).
## Reductions with a logic inside: FO(TC) and FO(LFP)
Every reduction above is first-order, hence computable in AC⁰; the textbook
notions for the classes from logarithmic space up are the *logarithmic-space*
and the *polynomial-time* reduction. Without machines, those are
interpretations whose formulas are written in a logic capturing that class –
Immerman's **FO(TC)** and **FO(LFP) reductions**, built here on the walk and
the inflationary layers above. They nest,
`≤ᶠᵒ[≤]` ⊆ `≤ᵈᵗᶜ` ⊆ `≤ᵗᶜ` ⊆ `≤ˡᶠᵖ`, with the first inclusion strict.
* `DescriptiveComplexity.FixedPointReduction` – a
`DescriptiveComplexity.LFPInterpretation` is a relativized first-order
interpretation whose formulas may read the value of a simultaneous
induction over the base structure, and a
`DescriptiveComplexity.LFPReduction` (notation `P ≤ˡᶠᵖ Q`) is one mapping
yes-instances exactly to yes-instances, for every linear order on the
input. Every first-order reduction is one
(`DescriptiveComplexity.FOReduction.toLFP`,
`DescriptiveComplexity.OrderedFOReduction.toLFP`,
`DescriptiveComplexity.RelOrderedFOReduction.toLFP`), which is the statement
that an FO reduction is in particular a polynomial-time reduction.
* `DescriptiveComplexity.FixedPointReductionComposition` – **transitivity**
(`DescriptiveComplexity.LFPReduction.trans`), i.e., the substitution
property of the logic: the outer induction pulls back through the inner
interpretation and the two inductions stratify into one
(`DescriptiveComplexity.StepDef.stratify`), while the interpretations
compose with the guarded pullback a definable domain requires.
* `DescriptiveComplexity.SecondOrderRelPull` – second-order definability pulls
back through a *relativized* interpretation
(`DescriptiveComplexity.SigmaSODefinable.of_relOrderedReduction` and its
universal twin), the transfer of assignments being a retraction rather than
a bijection: off-domain junk in a guess is never read.
* `DescriptiveComplexity.FixedPointExpand` – **an induction can be eliminated
from a `Σ₁` definition**
(`DescriptiveComplexity.sigmaSODefinable_of_ifpExpand`), by making the
guessed relations part of the vocabulary – over which the induction defines
a PTIME problem, hence a `Σ₁` one with no induction left – and merging the
two existential blocks into one.
* `DescriptiveComplexity.FixedPointReductionClosure` – PTIME, NP and coNP are
closed under `≤ˡᶠᵖ` (`DescriptiveComplexity.mem_PTIME_of_lfpReduction`,
`DescriptiveComplexity.mem_NP_of_lfpReduction`,
`DescriptiveComplexity.mem_coNP_of_lfpReduction`), each by a different
argument – stratification, the elimination above, complementation – and
`DescriptiveComplexity.CofinalHardLFP` states hardness under these
reductions, implied by the library's own
(`DescriptiveComplexity.CofinalHard.toLFP`).
* `DescriptiveComplexity.FixedPointExpandLevels` – the same elimination under a
quantifier prefix of **any** length and either polarity
(`DescriptiveComplexity.exists_expand_sorealize`): the blocks are peeled from
the outside in, each commuting with the expansion, and the recursion ends at
one block, where the induction becomes a quantifier of that block's own
polarity and merges into it – `DescriptiveComplexity.PTIME_subset_NP`
existentially, `DescriptiveComplexity.PTIME_subset_coNP` universally.
* `DescriptiveComplexity.FixedPointReductionHierarchy` – with it, **every
level of the polynomial hierarchy and `PH` itself** are closed under `≤ˡᶠᵖ`,
and so under `≤ᵗᶜ` and `≤ᵈᵗᶜ`
(`DescriptiveComplexity.mem_sigmaP_of_lfpReduction`,
`DescriptiveComplexity.mem_piP_of_lfpReduction`,
`DescriptiveComplexity.mem_PH_of_lfpReduction` and their siblings).
* `DescriptiveComplexity.FixedPointStratifyPartial` – **an inflationary
induction followed by a partial iteration is one partial iteration**
(`DescriptiveComplexity.StepDef.pfpHolds_stratifyPFP`). What a partial
iteration cannot do is gate itself; it does not have to, the gate being an
arity-`0` variable of the state that the inflationary stratum sets and the
partial stratum is conjoined with. This is the walk-with-a-preliminary-phase
of the SO(TC) reading, written as an iteration.
* `DescriptiveComplexity.FixedPointReductionSpace` – hence **PSPACE is closed
under `≤ˡᶠᵖ`** (`DescriptiveComplexity.mem_PSPACE_of_lfpReduction`, and so
under `≤ᵗᶜ` and `≤ᵈᵗᶜ`), which closes every class of this library from PTIME
to PSPACE under all four reduction notions.
* `DescriptiveComplexity.FixedPointReductionStrict` – the embedding of the
first-order reductions into these is **strict**, unconditionally:
`DescriptiveComplexity.EVEN` reduces to
`DescriptiveComplexity.NONEMPTYMARK` in FO(LFP) and by no first-order
reduction (`DescriptiveComplexity.exists_lfpReduction_not_orderedReduction`),
since the target is first-order definable and EVEN is not.
* `DescriptiveComplexity.TransitiveClosureParam` – the logarithmic-space
notion needs walks as *relations*, which
`DescriptiveComplexity.TCSpec` (a sentence) is not: a
`DescriptiveComplexity.ParamTCSpec` is a walk with parameters, and a finite
family of them is a block of relation variables holding their reachability
relations. Those relations are the value of one inflationary induction
(`DescriptiveComplexity.TCFamily.inflLimit_toStepDef`) – a walk is a fixed
point of a very restricted shape – and any existing `TCSpec` becomes a
formula over them (`DescriptiveComplexity.TCSpec.acceptsF`).
* `DescriptiveComplexity.TransitiveClosureReduction` – a
`DescriptiveComplexity.TCReduction` (notation `P ≤ᵗᶜ Q`) is an
interpretation whose formulas may read those relations. It is an FO(LFP)
reduction (`DescriptiveComplexity.TCReduction.toLFP`), so PTIME, NP and coNP
are closed under it as well, and so is **NL** – the closure the notion is
named for – by Immerman's normal form, proved below as an algebra of walks
(`DescriptiveComplexity.mem_NL_of_tcReduction`,
`DescriptiveComplexity.TransitiveClosureReductionClosure`). Composition with
a first-order reduction on the outside is proved
(`DescriptiveComplexity.TCReduction.trans_rel`,
`DescriptiveComplexity.TransitiveClosureReductionComposition`): the outer
reduction contributes no walks, so the composite consults the same ones.
**Transitivity with itself** is `DescriptiveComplexity.TCReduction.trans`
(`DescriptiveComplexity.TransitiveClosureReductionTrans`), so `≤ᵗᶜ` is a
reduction order.
* `DescriptiveComplexity.TransitiveClosureParamPull` – a walk on the
interpreted structure **is** a walk on the base one
(`DescriptiveComplexity.ParamTCSpec.comapRel`), its tuples spread over their
coordinates and the tags of its points carried in the mode. Over a definable
domain the encoding is no longer a bijection, so the pulled walk is guarded
and the correspondence
(`DescriptiveComplexity.ParamTCSpec.reachAt_comapRel_iff`) is stated between
in-domain nodes – which is where the formulas that read it evaluate it.
* `DescriptiveComplexity.TransitiveClosureTower` – what those pulled walks
are: a `DescriptiveComplexity.TCTower` is a list of families, each over the
vocabulary the ones below it expand, so its walks may read the reachability
relations of earlier walks. That is FO(TC) *with nesting*, and it costs
nothing – `DescriptiveComplexity.TCTower.inflLimit_toStepDef` says a tower's
relations are still the value of one inflationary induction, the
stratification (`DescriptiveComplexity.StepDef.stratify`) of its families'.
* `DescriptiveComplexity.TransitiveClosureReductionDet` – the *deterministic*
reading, `DescriptiveComplexity.DTCReduction` (notation `P ≤ᵈᵗᶜ Q`), which is
the many-one reduction of the textbooks: every walk is read through its
determinization (`DescriptiveComplexity.ParamTCSpec.det`, determinism as a
formula rather than as a hypothesis, exactly as
`DescriptiveComplexity.TCSpec.det`), and a walk that is already functional
loses nothing by it
(`DescriptiveComplexity.ParamTCSpec.reachAt_det_of_functional`). **LOGSPACE
is closed under it** (`DescriptiveComplexity.mem_LOGSPACE_of_dtcReduction`).
* **Immerman's normal form, as an algebra of walks.** A
`DescriptiveComplexity.Decider` (`DescriptiveComplexity.TransitiveClosureDecide`)
is a walk with two exits, `yes` and `no`, and parameters; it *decides* a
proposition when, from its start mode and any tuple, `yes` is reachable
exactly if the proposition holds and `no` exactly if it fails. Negation
swaps the exits, conjunction runs one decider after the other, and the
universal quantifier iterates a decider along the order with the bound
variable frozen into a coordinate – so every first-order formula over an
expansion by decided relations is decided
(`DescriptiveComplexity.Decider.exists_of_formula`,
`DescriptiveComplexity.TransitiveClosureDecideFormula`), and every
construction preserves *functionality*, which is what serves the
deterministic logic. The atoms are the reachability relations of walks:
`DescriptiveComplexity.ParamTCSpec.reachDecider`
(`DescriptiveComplexity.TransitiveClosureDecideReach`) runs the walk for
`yes` and, for `no`, the inductive-counting walk of
`DescriptiveComplexity.TransitiveClosureCompl` – **Immerman–Szelepcsényi with
parameters**, obtained from the sentence-level theorem by turning the
parameters into constants of the vocabulary
(`DescriptiveComplexity.constStructure`, `DescriptiveComplexity.toConst`,
`DescriptiveComplexity.fromConst`) rather than by touching the counting
machine; `DescriptiveComplexity.ParamTCSpec.detReachDecider`
(`DescriptiveComplexity.TransitiveClosureDecideReachDet`) follows the one
run of a determinized walk with a step budget counted over the walk's own
nodes, and is functional. A walk over an expansion whose steps are decided
is then **suspended** into a walk over the base
(`DescriptiveComplexity.ParamTCSpec.flat`,
`DescriptiveComplexity.TransitiveClosureFlatten`), the candidate successor
guessed (`DescriptiveComplexity.ParamTCSpec.reachAt_flat_iff`) or searched in
the order of nodes, which is functional and simulates a functional outer
walk (`DescriptiveComplexity.ParamTCSpec.reachAt_flat_iff_of_functional`);
and a sentence – some source reaches some target – is one decider
(`DescriptiveComplexity.ParamTCSpec.sentenceDecider`,
`DescriptiveComplexity.TransitiveClosureSentenceDecide`), hence one
`DescriptiveComplexity.TCSpec` (`DescriptiveComplexity.Decider.toSpec`).
`DescriptiveComplexity.TransitiveClosureReductionClosure` pulls the walk
deciding `Q` back through the reduction
(`DescriptiveComplexity.TCSpec.pullSpec`) and assembles the two closures,
`DescriptiveComplexity.TCDefinable.of_tcReduction` and
`DescriptiveComplexity.DTCDefinable.of_dtcReduction`, with coNL and
coLOGSPACE in their wake.
* `DescriptiveComplexity.TransitiveClosureReductionTrans` – **transitivity** of
`≤ᵗᶜ` (`DescriptiveComplexity.TCReduction.trans`) and of `≤ᵈᵗᶜ`
(`DescriptiveComplexity.DTCReduction.trans`), by the same pieces and no
normal form on formulas: the outer reduction's walks are pulled back through
the inner interpretation (`DescriptiveComplexity.TCInterpretation.pulled`),
flattened (`DescriptiveComplexity.TCInterpretation.flatFamily`) and added to
the inner family, and the inner interpretation is *extended* to the outer
family's vocabulary (`DescriptiveComplexity.TCInterpretation.CompositeBlock.extendOuter`),
a reachability atom of an outer walk being read as “the endpoints have
encodings between which the flat walk reaches”; the guarded composition
`DescriptiveComplexity.RelFOInterpretation.compRel` then substitutes those
formulas for the atoms, and produces exactly the outer reduction's input
(`DescriptiveComplexity.TCInterpretation.CompositeBlock.extendOuterLEquiv`).
The composite family is kept abstract
(`DescriptiveComplexity.TCInterpretation.CompositeBlock`) so that it may be
read as it is or through its determinization, which is the deterministic
case – where the pullback of a determinized walk is functional
(`DescriptiveComplexity.ParamTCSpec.comapRel_functional`), as the searching
flat walk requires.
* `DescriptiveComplexity.TransitiveClosureReductionStrict` – the same
separation two notions lower: EVEN reduces to
`DescriptiveComplexity.NONEMPTYMARK` in FO(≤, TC) and by no first-order
reduction (`DescriptiveComplexity.exists_tcReduction_not_orderedReduction`),
and indeed in FO(≤, DTC)
(`DescriptiveComplexity.exists_dtcReduction_not_orderedReduction`), the
parity walk never having a choice
(`DescriptiveComplexity.evenSpec_functional`) – so the gap opens already at
the deterministic logarithmic-space notion, with a walk along the order
rather than a fixed point. The same observation gives EVEN its FO(DTC)
definition (`DescriptiveComplexity.even_dtcDefinable`).
## Inexpressibility: Ehrenfeucht–Fraïssé games
The one part of the library that proves things logic *cannot* do, with no
complexity-theoretic assumption anywhere – the payoff a machine-first
development has no counterpart for.
* `DescriptiveComplexity.FirstOrderDefinable` – plain first-order
definability of a decision problem, order-free
(`DescriptiveComplexity.FODefinableFree`) and order-invariant
(`DescriptiveComplexity.FODefinable`), the bottom of every ladder above and
the notion these results refute.
* `DescriptiveComplexity.Games.Ehrenfeucht` – **the Ehrenfeucht–Fraïssé
game** ([Ehrenfeucht 1961][ehrenfeucht1961application]) between two
structures: legal positions (`DescriptiveComplexity.PartialIso`, agreement
on the atomic type read across two structures), the graded refinement
`DescriptiveComplexity.efStage` – whose rounds *append* a coordinate over
two structures, which is why it is not an instance of the `≡ᵏ` pebble
skeleton of `DescriptiveComplexity.Invariant.Pebble` – and **the
methodology lemma** (`DescriptiveComplexity.realize_sentence_of_efEquiv`):
`n`-round equivalent structures satisfy the same sentences of quantifier
rank at most `n`, the measure being the `DescriptiveComplexity.qdepth`
shared with the invariant layer. Everything below is a contrapositive of it.
* `DescriptiveComplexity.Games.Bare` – the strategy on **bare sets**: two
sets with at least `n` elements each are `n`-round equivalent
(`DescriptiveComplexity.efEquiv_bare`), so an order-free first-order
definable property of a bare set is constant beyond a threshold
(`DescriptiveComplexity.exists_card_bound_of_foDefinableFree`) – first-order
logic counts up to its quantifier rank and no further.
* `DescriptiveComplexity.Games.Distance`,
`DescriptiveComplexity.Games.LinearOrder` – **Ehrenfeucht's theorem on
linear orders**: two finite linear orders with at least `2 ^ n` elements
each are `n`-round equivalent (`DescriptiveComplexity.efEquiv_linearOrder`).
The duplicator's invariant is one equation per pair of points – equal
distances *up to truncation at* `2 ^ n` (`DescriptiveComplexity.truncAt`),
with the two ends of the order joined to the position as sentinels so that
distances to them are distances like any other – and a round is one
application of the answer lemma `DescriptiveComplexity.exists_answer`, where
the budget halves: copy the distance to the nearer neighbor, or, when both
are far, land in the middle of a gap the invariant makes twice as wide on
the other side.
* `DescriptiveComplexity.Invariant.Bare` – **the order no induction defines**:
over the empty vocabulary `≡ᵏ` is the equality pattern
(`DescriptiveComplexity.equivK_bare`, the pebble twin of
`DescriptiveComplexity.efStage_bare`), so a transposition of the universe
leaves it alone and every binary variable of an order-free inflationary
limit is symmetric – whence
`DescriptiveComplexity.not_isLinearOrder_inflLimit`: **no order-free
`StepDef` defines a linear order on a bare set**. This is the
order-invariance of the definability notions of this library as a theorem:
the order they are handed is not a convenience but something no
isomorphism-invariant logic can build. It is a statement about a defined
*relation*; the class-level one needs the two-structure game below, since
`≡ᵏ` relates tuples inside one structure.
* `DescriptiveComplexity.Invariant.TwoPebble`,
`DescriptiveComplexity.Invariant.TwoInvariance`,
`DescriptiveComplexity.Invariant.TwoStages` – **the `k`-pebble game between
two structures**, the pebble counterpart of the round game above and the
layer a *Boolean* query needs: the same chain, coinduction and stabilization
with the two sides in different types (`DescriptiveComplexity.EquivK₂`), the
`k`-variable invariance lemma across the pair
(`DescriptiveComplexity.realize_equivK₂`), the collapse on bare sets
(`DescriptiveComplexity.equivK₂_bare`: `k` pebbles cannot count past `k`,
whatever the two sizes), and the transfer of an inflationary induction stage
by stage (`DescriptiveComplexity.StepDef.inflStage_invariant₂`), so that its
output sentence cannot separate the two structures
(`DescriptiveComplexity.StepDef.ifpHolds_equivK₂`).
* `DescriptiveComplexity.Problems.Even` – **EVEN is not first-order
definable** (`DescriptiveComplexity.even_not_foDefinableFree`), and **not
even order-invariantly so** (`DescriptiveComplexity.even_not_foDefinable`):
over the empty vocabulary, deciding the parity of the universe is beyond
first-order logic however it is allowed to use a linear order. It is a
single walk along that order, though – step to the successor, flip a bit –
so it *is* FO(≤, TC) definable (`DescriptiveComplexity.even_tcDefinable`),
hence in `DescriptiveComplexity.NL` (`DescriptiveComplexity.even_mem_NL`).
Together with the trivial inclusion
(`DescriptiveComplexity.FODefinable.tcDefinable`, in
`DescriptiveComplexity.TransitiveClosureFO`: a sentence is the walk that
takes no step – and a walk with no step is deterministic for want of a
competitor, so the same construction gives
`DescriptiveComplexity.FODefinable.dtcDefinable`, the `FO(≤) ⊆ L` end of the
chain below) that is **`FO ⊊ FO(TC)`**, unconditionally
(`DescriptiveComplexity.exists_tcDefinable_not_foDefinable`) – a strict
inclusion proved outright, where every other separation in this library is
conditional. The same problem separates the *arithmetic* logic from the bare
order, in the other direction: EVEN **is** AC⁰ definable
(`DescriptiveComplexity.even_ac0Definable`), the greatest element having rank
`Nat.card A - 1`, whence **`FO(≤) ⊊ AC⁰`**
(`DescriptiveComplexity.exists_ac0Definable_not_foDefinable`). That is the
parity of the *universe*, i.e., of the input's length; the parity of a marked
*subset* is PARITY, the problem outside AC⁰, about which nothing here is
claimed – no AC⁰ lower bound is proved in this library. EVEN also settles the
*unordered* fixed-point question:
`DescriptiveComplexity.even_not_ifpDefinableFree`, whence
`DescriptiveComplexity.exists_mem_PTIME_not_ifpDefinableFree` – **order-free
FO(IFP) does not capture PTIME**, against
`DescriptiveComplexity.lfpDefinable_iff_mem_PTIME`, which says it does over
ordered structures. The order in every capture theorem here is doing real
work.
* `DescriptiveComplexity.Problems.Parity` – **PARITY**, the parity of a *marked
subset* rather than of the universe: the problem the AC⁰ lower bound is about,
in the catalog so that the distinction from EVEN is a definition and not a
warning. It is **in LOGSPACE** (`DescriptiveComplexity.parity_mem_LOGSPACE`) by
one deterministic walk – carry a bit, flip it at each marked element, a walk
functional outright so that determinizing is free – and **not first-order
definable** (`DescriptiveComplexity.parity_not_foDefinable`), EVEN being the
instance where everything is marked
(`DescriptiveComplexity.even_fo_reduction_parity`). With
`DescriptiveComplexity.even_ac0Definable` and
`DescriptiveComplexity.ac0Definable_mem_PTIME` that is three sides of
`AC⁰ ⊊ LOGSPACE`; the fourth, PARITY ∉ AC⁰, is the switching lemma
([Ajtai 1983][ajtai1983sigma11]; [Furst, Saxe & Sipser 1984][furst1984parity];
[Håstad 1986][hastad1986almost]) and is not proved here – this library proves
**no** AC⁰ lower bound.
## Nondeterministic logarithmic space, by the Krom fragment
* `DescriptiveComplexity.SecondOrderKrom` – SO-Krom ([Grädel
1992][gradel1992capturing]): the same clausal style with the *Krom* (2-CNF)
restriction in place of the Horn one, at most two second-order literals per
clause and of either sign (`DescriptiveComplexity.KromProgram`, whose literals carry
a sign and sit in two `Option` slots, so unit and goal clauses need no
special case). It captures nondeterministic logarithmic space on ordered
structures. Neither fragment contains the other: Horn clauses may be wide,
Krom clauses may have two positive literals – and the difference is exactly
determinism, a Horn program having a least model where a 2-CNF has none.
* `DescriptiveComplexity.SecondOrderKromPull` – the pullback stays Krom, for the reason
it stays Horn (the shape constrains second-order atoms; an interpretation
rewrites input-vocabulary ones, which live in the guard), so
`DescriptiveComplexity.NL` in `DescriptiveComplexity.LogSpace` is a genuine complexity
class. The pieces shared with the Horn pullback (atoms, guard pullback, tag
assignments) live in `DescriptiveComplexity.SecondOrder` and
`DescriptiveComplexity.SecondOrderPull`.
* `DescriptiveComplexity.LogSpace` – the class `DescriptiveComplexity.NL`. Its inclusion
in the classes above is *not* syntactic (a Krom kernel is not a Horn kernel)
and goes through the complete problem: `DescriptiveComplexity.NL_subset_PTIME` and
`DescriptiveComplexity.NL_subset_NP`, both downstream with 2SAT. That the class is
closed under complement – `NL = coNL` – is *not* the definitional duality
that gives `PiP k` from `SigmaP k` but Immerman–Szelepcsényi, proved in
`DescriptiveComplexity.ImmermanSzelepcsenyi` (`DescriptiveComplexity.NL_eq_coNL`).
* `DescriptiveComplexity.TransitiveClosure` – FO(TC) ([Immerman
1987][immerman1987languages]), the logic that captures NL on ordered
structures, in the same kernel-as-data style: a `DescriptiveComplexity.TCSpec` is an
arity, a finite *mode* component, a first-order transition formula on
`k`-tuples per pair of modes and two endpoint formulas, with
`Relation.ReflTransGen` supplying the closure. Modes are what tuples of
elements cannot supply – a one-element universe has one tuple – and play the
role tags play in an interpretation. It is the logic in which REACH is stated
head-on (`DescriptiveComplexity.reach_tcDefinable`) and in which
Immerman–Szelepcsényi is proved, the bridge that gives `REACH ∈ NL`, the
clausal fragments defining only the complement.
* `DescriptiveComplexity.TwoCnf` – the criterion for 2-satisfiability ([Aspvall,
Plass & Tarjan 1979][aspvall1979linear]) with no logic in it at all: over a
finite type of variables, a 2-CNF is satisfiable iff no literal reaches its
own negation and back in the implication graph. It is needed once for CNF
structures (2SAT ∈ PTIME) and once for the atoms of a Krom program (turning a
Krom definition into a transitive closure); the two differ only in what plays
the part of a variable.
* `DescriptiveComplexity.KromImplication` and
`DescriptiveComplexity.KromTransitiveClosure` – **the converse translation**: the
complement of an SO-Krom definable problem is FO(TC) definable
(`DescriptiveComplexity.TCDefinable.compl_of_sigmaSOKromDefinable`). A Krom program
instantiated in a structure *is* a 2-CNF, whose variables are the atoms of
its block at tuples of elements, so it is satisfiable exactly when no goal
clause fires and no literal reaches its own negation and back
(`DescriptiveComplexity.KromImpl.exists_holds_iff`); the second file expresses the
implication graph as first-order transition formulas
(`DescriptiveComplexity.KromTC.realize_edgeF`) and walks the cycle-witnessing graph
of `DescriptiveComplexity.TwoCnf.carryReach_iff`, the start literal, the current one
and the flag being the mode and the two atoms' arguments the two halves of
the tuple. With the direction below it gives `co-NL(Krom) = NL(TC)`
(`DescriptiveComplexity.mem_NL_iff_tcDefinable_compl`); `NL(Krom) = NL(TC)`, and
with it `REACH ∈ NL`, needs the complementation of FO(TC) itself, which is
`DescriptiveComplexity.TCDefinable.compl`.
* `DescriptiveComplexity.TransitiveClosureKrom` – the translation that *is* free:
the complement of an FO(TC) definable problem is SO-Krom definable
(`DescriptiveComplexity.SigmaSOKromDefinable.compl_of_tcDefinable`), hence in NL, by
the program guessing the nodes from which an accepting node is reachable, one
`k`-ary relation variable per mode. `DescriptiveComplexity.unreach_mem_NL` is its
single-mode, arity-one instance, written out by hand as a worked example.
* `DescriptiveComplexity.InductiveCounting` and `DescriptiveComplexity.TransitiveClosureCompl` –
**FO(TC) is closed under complement** (`DescriptiveComplexity.TCDefinable.compl`), by
inductive counting. The machine is combinatorial, on an abstract finite
linearly ordered node set: eight registers, each a node or a count read as a
rank, and four nested loops – the stages, the outer scan, the inner scan and
a certifying walk – that compute `|Rset (d+1)|` from `|Rset d|`, the count
check leaving a guessed set of layer nodes no room to be too small. The
first-order layer stores a register as one `k`-tuple beside a mode kept in
the control, so a configuration *is* a mode with an `8k`-tuple, and compiles
every atomic constraint of the machine into a formula once the modes are
known – mode-level conditions (“the least mode”, “this mode covers that
one”) being decided outside the formula.
* `DescriptiveComplexity.ImmermanSzelepcsenyi` – **`NL = coNL`**
(`DescriptiveComplexity.NL_eq_coNL`), assembled from the complementation of FO(TC)
and the two translations against the Krom fragment. It also gives what those
translations alone could not: NL *is* FO(TC)
(`DescriptiveComplexity.tcDefinable_iff_mem_NL`), the Krom fragment is closed under
complement, and `REACH ∈ NL` (`DescriptiveComplexity.reach_mem_NL`).
* `DescriptiveComplexity.TransitiveClosureReach` – **REACH is NL-complete**
(`DescriptiveComplexity.REACH_NL_complete`), the discharge of FO(TC) into its
canonical problem. Unlike the clausal discharges, this one emits nothing: the
graph of the walk of a `DescriptiveComplexity.TCSpec` already *is* a marked graph –
a node is a mode with a `k`-tuple, which is exactly the universe
`Tag × A^dim` of a tagged interpretation – so the three defining formulas are
the specification's own, relabeled
(`DescriptiveComplexity.reach_hard_of_tcDefinable`). No junk arises, so the
reduction needs no relativization; the one adjustment is
`DescriptiveComplexity.TCSpec.pad`, adding a spare mode so that the tag type is
nonempty, since a reduction must map nonempty structures to nonempty ones.
UNREACH is complete too (`DescriptiveComplexity.UNREACH_NL_complete`), by
complementing that reduction – which is again `NL = coNL`, each fragment
defining only one of the two problems head-on.
* `DescriptiveComplexity.TransitiveClosureDet` and
`DescriptiveComplexity.TransitiveClosurePull` – FO(DTC), and closure of both
reachability logics under reductions. Determinism is a *formula*, not a side
condition: a `DescriptiveComplexity.TCSpec` is read through
`DescriptiveComplexity.TCSpec.det`, which conjoins to each transition the statement
that no other transition leaves the current node – a finite conjunction over
the modes, the mode comparison being static. Every specification then denotes
a deterministic walk and nothing has to be preserved by a pullback, which is
what makes the closure argument syntactic. The pullback itself
(`DescriptiveComplexity.TCSpec.comap`) walks the interpreted structure while
writing everything on the base one: `k` tags ride along in the mode, the
coordinates flatten to a `k · d`-tuple, and the resulting bijection of nodes
carries steps to steps – whence determinism travels for free, “no competing
successor” being invariant under a bijection.
* `DescriptiveComplexity.DetLogSpace` – the class `DescriptiveComplexity.LOGSPACE`
(named in full, `L` being a vocabulary everywhere in this development),
defined by FO(DTC) definability. It is defined by an operator-as-data logic
rather than by the shape of a kernel, unlike PTIME and NL: no fragment of