1 |
On sob, 2017-07-08 at 16:12 +0200, Alexis Ballier wrote: |
2 |
> On Sat, 08 Jul 2017 11:43:39 +0200 |
3 |
> Michał Górny <mgorny@g.o> wrote: |
4 |
> |
5 |
> > Hi, everyone. |
6 |
> > |
7 |
> > I think the affairs have settled enough and I've finished filling |
8 |
> > in the pre-GLEP for REQUIRED_USE auto-enforcing. It's got all |
9 |
> > the algorithms, rationale and separated reference implementation. |
10 |
> > |
11 |
> > If there are no major concerns raised, I will soon start working |
12 |
> > on writing an optimized implementation for pkgcore/pkgcheck |
13 |
> > and integrating the verification algos with the CI. |
14 |
> > |
15 |
> > The pre-GLEP for review is here: |
16 |
> > |
17 |
> > https://wiki.gentoo.org/wiki/User:MGorny/GLEP:ReqUse |
18 |
> |
19 |
> |
20 |
> Constraint group reordering algorithm |
21 |
> |
22 |
> I really think we should only consider REQUIRED_USE with forced/masked |
23 |
> useflags instantiated there. And ban (in repoman) REQUIRED_USE that |
24 |
> contain some "False": "a? ( b )" with 'a' free and 'b' masked is |
25 |
> perfectly ok now but it hides a serious problem in the package/profile. |
26 |
> Instantiating this would give: "a? ( False )" and be an error |
27 |
> just like we have depend.bad & co. This is independent of auto |
28 |
> solving or not, it's already wrong. |
29 |
|
30 |
As I've already explained you multiple times, this obtains *exactly |
31 |
the same* effect. However, it's much simpler when it's done like this |
32 |
because it makes it possible to reuse the already defined algorithms |
33 |
instead of having to precisely define how to preprocess REQUIRED_USE for |
34 |
this and cover all the corner cases. |
35 |
|
36 |
> Reordering is a dangerous path as we've already seen since it can |
37 |
> create unexpected loops for the solver. |
38 |
|
39 |
Freeform reordering is dangerous, and I've removed that already. |
40 |
Reordering restricted to immutables can not cause any issues that any |
41 |
other solution wouldn't cause. |
42 |
|
43 |
> Working on instantiated REQUIRED_USE constraints would probably |
44 |
> simplify quite a bit your GLEP too: you already have the "Verifying |
45 |
> that the constraints do not alter immutable flags" part that roughly |
46 |
> does the same thing as instantiating, except if you assume it's already |
47 |
> true you can skip the reordering. |
48 |
|
49 |
Except that the reordering can be described in 2 points, and so can be |
50 |
the immutability verification. Please prove that you can provide |
51 |
a simpler explanation that doesn't fail in any of the corner cases. |
52 |
|
53 |
> Concept for transforming REQUIRED_USE into implications |
54 |
> |
55 |
> Ok, now I probably understand better the concept of common prefix. I'm |
56 |
> definitely biased here, but I would feel better with a more recursive |
57 |
> presentation of it. Assume we have 'validate(list of clauses)'; |
58 |
> basically, the common prefix idea is that for an implication 'foo? |
59 |
> ( consequences = list of clauses )' you first validate the consequences |
60 |
> as if it were a REQUIRED_USE (so that the subtree rooted at foo is |
61 |
> not self-conflicting) and then consider the whole thing as a clause. |
62 |
> The idea would then be to have similar checks as to what you've written |
63 |
> but working on trees (ASTs) instead of flattened clauses. This would |
64 |
> avoid having to deal with unique identities (these would come for free) |
65 |
> and IMHO would be easier to understand. |
66 |
> I'm not sure how to do this though, I'll ping you when I have some idea. |
67 |
|
68 |
Well, the problem of common prefix is quite complex, and I'm not even |
69 |
sure if it's really worth more consideration. After all, we're prettych |
70 |
much talking about doing: |
71 |
|
72 |
a? ( !a ... ) |
73 |
|
74 |
which has extremely low usability and even lower likeness of occurring. |
75 |
|
76 |
> One big advantage of working on ASTs is that it becomes trivial to |
77 |
> suggest a proper reordering. |
78 |
|
79 |
Reordering is never a trivial problem. Unless I'm missing something, it |
80 |
is technically possible that a 'reordering' will actually require a sub- |
81 |
item being moved out of the containing group. |
82 |
|
83 |
And to be honest, I find the output of the verification script in this |
84 |
regard quite useful. That is, it saying 'X affects Y, so it needs to go |
85 |
before it' is quite clear to me. I don't think most developers would |
86 |
actually need to script to pinpoint a specific location for every single |
87 |
constraint. |
88 |
|
89 |
> ------- |
90 |
> |
91 |
> Restrictions on REQUIRED_USE format |
92 |
> |
93 |
> I still fail to see the point here. One can simply apply the rewriting |
94 |
> you suggest below and be done with it. Rationale is not very convincing |
95 |
> to me: |
96 |
> |
97 |
> - avoiding unpredictable results of automatic flag adjustments: |
98 |
> A deterministic algorithm is, by definition, predictable. |
99 |
|
100 |
s/unpredictable/surprising/? |
101 |
|
102 |
The goal is for it do something that the developer *not reading |
103 |
the spec* could reasonably predict happening. |
104 |
|
105 |
> - improving readability of REQUIRED_USE constraints: |
106 |
> No need for a restriction for that. If people want to shoot |
107 |
> themselves in the foot, it is not a PMS problem. I see that |
108 |
> like proposing death penalty for those who commit suicide :) |
109 |
|
110 |
This is not PMS. This is a GLEP which serves both the purpose of |
111 |
a technical specification with extended rationale and a policy document. |
112 |
|
113 |
> - keeping the specification and implementation relatively simple: |
114 |
> You already define everything for working without restriction. |
115 |
> Plus, unlimited implication nesting has the same complexity. |
116 |
|
117 |
No, I don't. I don't cover the meaning of nested groups and things just |
118 |
explode when they come into game. |
119 |
|
120 |
> ------- |
121 |
> |
122 |
> |
123 |
> Do you have numbers on the checker run on all inputs from gentoo-x86 ? |
124 |
> Since we're dealing with heuristics those are particularly important to |
125 |
> validate we're not rejecting too many constructs. |
126 |
|
127 |
I think I've mentioned that a few times in the GLEP. The validation |
128 |
and verification bits were tested on all REQUIRED_USE cases from a few |
129 |
days ago. For the former, all cases are listed in rationale. For |
130 |
the latter, the reference implementation has test cases for every |
131 |
construct that triggered an issue, including the false positives that |
132 |
were fixed. I've only skipped a few that were completely redundant (e.g. |
133 |
different versions of the same package that added 1-2 irrelevant items). |
134 |
|
135 |
The solver was tested on all combinations of most of the corner cases. I |
136 |
have only skipped those that would require humongous number of |
137 |
combinations. |
138 |
|
139 |
I haven't tested all combinations of masked/forced flags from |
140 |
the profiles though. I plan to do this by implementing it in pkgcheck. |
141 |
I will also have better performance reports based on optimized |
142 |
algorithms and real use. |
143 |
|
144 |
-- |
145 |
Best regards, |
146 |
Michał Górny |