mirror of
https://github.com/mudler/luet.git
synced 2025-07-30 22:45:29 +00:00
Force the solver to look at the best match first
Add support clauses to force the solver to look after the best match first. Closes #29
This commit is contained in:
parent
0ccaf47f45
commit
d583fa8bf5
@ -386,7 +386,6 @@ func Best(set []Package) Package {
|
||||
}
|
||||
|
||||
func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db PackageDatabase) ([]bf.Formula, error) {
|
||||
// TODO: Expansion needs to go here - and so we ditch Resolvedeps()
|
||||
p, err := definitiondb.FindPackage(pack)
|
||||
if err != nil {
|
||||
p = pack // Relax failures and trust the def
|
||||
@ -400,11 +399,6 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
||||
|
||||
var formulas []bf.Formula
|
||||
for _, requiredDef := range p.GetRequires() {
|
||||
// TODO: Stabilize this. We allow any of those version to be selected,
|
||||
// at the price that they can't be selected alltogether.
|
||||
// This have the downside that we cannot specify a preference (e.g. The best matching)
|
||||
// unless we have a user-defined version. It means that the solver could
|
||||
// give different output between calls, but they are all legit as they respect the constraints.
|
||||
required, err := definitiondb.FindPackage(requiredDef)
|
||||
if err != nil {
|
||||
packages, err := definitiondb.FindPackages(requiredDef)
|
||||
@ -414,19 +408,43 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
||||
if len(packages) == 1 {
|
||||
required = packages[0]
|
||||
} else {
|
||||
var bb []bf.Formula
|
||||
var ALO, priorityConstraints []bf.Formula
|
||||
|
||||
// Try to prio best match
|
||||
// Force the solver to consider first our candidate (if does exists).
|
||||
// Then builds ALO and AMO for the requires.
|
||||
c, candidateErr := definitiondb.FindPackageCandidate(requiredDef)
|
||||
var C bf.Formula
|
||||
if candidateErr == nil {
|
||||
// We have a desired candidate, try to look a solution with that included first
|
||||
for _, o := range packages {
|
||||
encodedB, err := o.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
B := bf.Var(encodedB)
|
||||
if !o.Matches(c) {
|
||||
priorityConstraints = append(priorityConstraints, bf.Not(B))
|
||||
}
|
||||
}
|
||||
encodedC, err := c.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
C = bf.Var(encodedC)
|
||||
// Or the Candidate is true, or all the others might be not true
|
||||
// This forces the CDCL sat implementation to look first at a solution with C=true
|
||||
formulas = append(formulas, bf.Or(C, bf.Or(priorityConstraints...)))
|
||||
}
|
||||
|
||||
// AMO - At most one
|
||||
for _, o := range packages {
|
||||
encodedB, err := o.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
B := bf.Var(encodedB)
|
||||
bb = append(bb, B)
|
||||
// f, err := o.BuildFormula(definitiondb, db)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// formulas = append(formulas, f...)
|
||||
ALO = append(ALO, B)
|
||||
for _, i := range packages {
|
||||
encodedI, err := i.Encode(db)
|
||||
if err != nil {
|
||||
@ -434,16 +452,11 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
||||
}
|
||||
I := bf.Var(encodedI)
|
||||
if !o.Matches(i) {
|
||||
// formulas = append(formulas, bf.Or(I, B))
|
||||
formulas = append(formulas, bf.Or(bf.Not(I), bf.Not(B)))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
formulas = append(formulas, bf.Or(bb...))
|
||||
|
||||
formulas = append(formulas, bf.Or(ALO...)) // ALO - At least one
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -489,7 +502,6 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
||||
}
|
||||
}
|
||||
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
encodedB, err := required.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -359,6 +359,40 @@ var _ = Describe("Solver", func() {
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("Selects best version", func() {
|
||||
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{})
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D, D1, D2, E} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A, B})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: D1, Value: true}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Uninstalls simple package correctly", func() {
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
Loading…
Reference in New Issue
Block a user