Skip to content

Commit 85e0c61

Browse files
authored
improve HB.instance (#421)
speedup toposort and instance search
1 parent 8b1725c commit 85e0c61

File tree

9 files changed

+893
-158
lines changed

9 files changed

+893
-158
lines changed

.github/workflows/nix-action-coq-8.18.yml

Lines changed: 191 additions & 52 deletions
Large diffs are not rendered by default.

.github/workflows/nix-action-coq-8.19.yml

Lines changed: 451 additions & 41 deletions
Large diffs are not rendered by default.

.github/workflows/nix-action-coq-master.yml

Lines changed: 185 additions & 46 deletions
Large diffs are not rendered by default.

.nix/config.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
fourcolor.override.version = "master";
1212
odd-order.override.version = "master";
1313
mathcomp-finmap.override.version = "master";
14-
mathcomp.analyis.override.version = "hierarchy-builder";
14+
mathcomp-classical.override.version = "master";
15+
mathcomp-analysis.override.version = "master";
1516
reglang.override.version = "master";
1617
coq-bits.override.version = "master";
1718
deriving.override.version = "master";

.nix/coq-nix-toolbox.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"7e631f043d424ce82f3308824bf64fbfdee04c80"
1+
"816e3aa12d182f26fc6b173312ba46f2df727f90"

Changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased
44

5+
### General
6+
- **Speedup** `HB.instance` does not try to infer classes that inherit from
7+
a class that is known to have no instance (for the given type)
8+
- **Speedup** `toposort` on `gref` uses OCaml's maps and sets rather than lists
9+
510
## [1.7.0] - 2024-01-10
611

712
Compatible with

HB/common/database.elpi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ toposort-proj Proj ES In Out :- !, toposort-proj.acc Proj ES [] In Out.
179179
pred topo-find i:B, o:A.
180180
pred toposort-proj.acc i:(A -> B -> prop), i:list (pair B B), i:list B, i:list A, o:list A.
181181
toposort-proj.acc _ ES Acc [] Out :- !,
182-
std.map {std.toposort ES Acc} topo-find Out.
182+
std.map {std.gref.toposort ES Acc} topo-find Out.
183183
toposort-proj.acc Proj ES Acc [A|In] Out :- std.do![
184184
Proj A B,
185185
topo-find B A => toposort-proj.acc Proj ES [B|Acc] In Out
@@ -192,7 +192,7 @@ pred toposort-classes i:list classname, o:list classname.
192192
toposort-classes In Out :- std.do! [
193193
std.findall (sub-class C1_ C2_ _ _) SubClasses,
194194
std.map SubClasses toposort-classes.mk-class-edge ES,
195-
std.toposort ES In Out,
195+
std.gref.toposort ES In Out,
196196
].
197197

198198
pred findall-classes o:list class.

HB/common/stdpp.elpi

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,32 @@ toposort ES XS XS'' :-
9090
toporec ES XS [] [] _ XS',
9191
std.filter XS' (std.mem XS) XS''.
9292

93+
namespace gref {
94+
pred topovisit i: coq.gref.map coq.gref.set, i: classname, i: coq.gref.set, i: list classname, i: coq.gref.set, o: coq.gref.set, o: list classname, o: coq.gref.set.
95+
topovisit _ X VS PS PSS VS PS PSS :- coq.gref.set.mem X PSS, !.
96+
topovisit _ X VS _ _ _ _ _ :- coq.gref.set.mem X VS, !, halt "cycle detected.".
97+
topovisit ES X VS PS PSS VS' [X|PS'] PSS'' :-
98+
(coq.gref.map.find X ES M ; coq.gref.set.empty M),
99+
toporec ES {coq.gref.set.elements M} {coq.gref.set.add X VS} PS PSS VS' PS' PSS',
100+
coq.gref.set.add X PSS' PSS''.
101+
pred toporec i: coq.gref.map coq.gref.set, i: list classname, i: coq.gref.set, i: list classname, i: coq.gref.set, o: coq.gref.set, o: list classname, o: coq.gref.set.
102+
toporec _ [] VS PS PSS VS PS PSS.
103+
toporec ES [X|XS] VS PS PSS VS'' PS'' PSS'' :-
104+
topovisit ES X VS PS PSS VS' PS' PSS', toporec ES XS VS' PS' PSS' VS'' PS'' PSS''.
105+
106+
pred add-to-neighbours i:coq.gref.set, i:pair gref gref, i:coq.gref.map coq.gref.set, o:coq.gref.map coq.gref.set.
107+
add-to-neighbours VS (pr _ V) A A :- not(coq.gref.set.mem V VS), !.
108+
add-to-neighbours _ (pr K V) A A1 :- coq.gref.map.find K A L, !, coq.gref.map.add K {coq.gref.set.add V L} A A1.
109+
add-to-neighbours _ (pr K V) A A1 :- coq.gref.map.add K {coq.gref.set.add V {coq.gref.set.empty} } A A1.
110+
111+
pred toposort i:list (pair gref gref), i:list gref, o:list gref.
112+
toposort ES XS XS'' :- !, std.do! [
113+
std.fold XS {coq.gref.set.empty} coq.gref.set.add VS,
114+
std.fold ES {coq.gref.map.empty} (add-to-neighbours VS) EM,
115+
toporec EM XS {coq.gref.set.empty} [] {coq.gref.set.empty} _ XS'' _
116+
].
117+
}
118+
93119
pred time-do! i:list prop.
94120
time-do! [].
95121
time-do! [P|PS] :-

HB/instance.elpi

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,20 @@ declare-const Name BodySkel TyWPSkel CSL :- std.do! [
7878
acc-clauses current Clauses
7979
].
8080

81+
% [not-subclass-of X C] holds if C does not inherit from X
82+
pred not-subclass-of i:classname, i:class.
83+
not-subclass-of HasNoInstance (class C _ _) :- not(sub-class C HasNoInstance _ _).
84+
8185
% [declare-all T CL MCSTL] given a type T and a list of class definition
8286
% CL in topological order (from least dep to most) looks for classes
8387
% for which all the dependencies (mixins) were postulated so far and skips the
8488
% rest. For each fulfilled class it declares a local constant inhabiting the
8589
% corresponding structure and declares it canonical.
8690
% Each mixin used in order to fulfill a class is returned together with its name.
8791
pred declare-all i:term, i:list class, o:list (pair id constant).
92+
declare-all _ [] [].
93+
declare-all T [class _ Struct _|Rest] L :- has-instance T Struct, !,
94+
declare-all T Rest L.
8895
declare-all T [class Class Struct MLwP|Rest] [pr Name CS|L] :-
8996

9097
infer-class T Class Struct MLwP S Name STy Clauses,
@@ -95,19 +102,24 @@ declare-all T [class Class Struct MLwP|Rest] [pr Name CS|L] :-
95102

96103
Clauses => declare-all T Rest L.
97104

98-
declare-all T [_|Rest] L :- declare-all T Rest L.
99-
declare-all _ [] [].
105+
declare-all T [class HasNoInstance _ _|Rest] L :-
106+
% filter out classes we can't build for sure
107+
std.filter Rest (not-subclass-of HasNoInstance) Rest1,
108+
declare-all T Rest1 L.
100109

101110
% for generic types, we need first to instantiate them by giving them holes,
102111
% so they can be used to instantiate the classes
103112
pred declare-all-on-type-constructor i:term, i:list class, o:list (pair id constant).
104-
declare-all-on-type-constructor T [class Class Struct MLwP|Rest] [pr Name CS|L] :-
113+
declare-all-on-type-constructor _ [] [].
114+
declare-all-on-type-constructor TK [class _ Struct _|Rest] L :- saturate-type-constructor TK T, has-instance T Struct, !,
115+
declare-all-on-type-constructor TK Rest L.
116+
declare-all-on-type-constructor TK [class Class Struct MLwP|Rest] [pr Name CS|L] :-
105117

106118
%TODO: compute the arity of the Class subject and saturate up to that point
107119
% there may even be more than one possibility
108-
saturate-type-constructor T Ty,
120+
saturate-type-constructor TK T,
109121

110-
infer-class Ty Class Struct MLwP S Name _STy Clauses,
122+
infer-class T Class Struct MLwP S Name _STy Clauses,
111123

112124
!,
113125

@@ -116,20 +128,23 @@ declare-all-on-type-constructor T [class Class Struct MLwP|Rest] [pr Name CS|L]
116128

117129
decl-const-in-struct Name SC SCTy CS,
118130

119-
Clauses => declare-all-on-type-constructor T Rest L.
131+
Clauses => declare-all-on-type-constructor TK Rest L.
120132

121-
declare-all-on-type-constructor T [_|Rest] L :- declare-all-on-type-constructor T Rest L.
122-
declare-all-on-type-constructor _ [] [].
133+
declare-all-on-type-constructor TK [class HasNoInstance _ _|Rest] L :-
134+
% filter out classes we can't build for sure
135+
std.filter Rest (not-subclass-of HasNoInstance) Rest1,
136+
declare-all-on-type-constructor TK Rest1 L.
123137

124-
pred infer-class i:term, i:classname, i:gref, i:factories, o:term, o:string, o:term, o:list prop.
125-
infer-class T Class Struct MLwP S Name STy Clauses:- std.do![
126-
127-
if (not(has-CS-instance? T Struct))
128-
true % we build it
138+
pred has-instance i:term, i:structure.
139+
has-instance T Struct :-
140+
if (has-CS-instance? T Struct)
129141
(if-verbose (coq.say {header} "skipping already existing"
130142
{nice-gref->string Struct} "instance on"
131-
{coq.term->string T}),
132-
fail),
143+
{coq.term->string T}))
144+
fail. % we build it
145+
146+
pred infer-class i:term, i:classname, i:gref, i:factories, o:term, o:string, o:term, o:list prop.
147+
infer-class T Class Struct MLwP S Name STy Clauses:- std.do![
133148

134149
params->holes MLwP Params,
135150
get-constructor Class KC,

0 commit comments

Comments
 (0)