Skip to content

Commit

Permalink
Export solver and related interfaces
Browse files Browse the repository at this point in the history
Signed-off-by: akihikokuroda [email protected]
  • Loading branch information
akihikokuroda committed Nov 9, 2022
1 parent e293fa3 commit d303cd9
Show file tree
Hide file tree
Showing 32 changed files with 689 additions and 665 deletions.
8 changes: 4 additions & 4 deletions cmd/dimacs/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (

"github.com/spf13/cobra"

"github.com/operator-framework/deppy/internal/constraints"
"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/internal/solver"
constraintsfactory "github.com/operator-framework/deppy/pkg/constraints/factory"
entitysourcefactory "github.com/operator-framework/deppy/pkg/entitysource/factory"
"github.com/operator-framework/deppy/pkg/solver/factory"
)

func NewDimacsCommand() *cobra.Command {
Expand Down Expand Up @@ -55,7 +55,7 @@ func solve(path string) error {
}

// build solver
so, err := solver.NewDeppySolver(entitysource.NewGroup(NewDimacsEntitySource(dimacs)), constraints.NewConstraintAggregator(NewDimacsConstraintGenerator(dimacs)))
so, err := factory.NewDeppySolver(entitysourcefactory.NewGroup(NewDimacsEntitySource(dimacs)), constraintsfactory.NewConstraintAggregator(NewDimacsConstraintGenerator(dimacs)))
if err != nil {
return err
}
Expand Down
17 changes: 8 additions & 9 deletions cmd/dimacs/dimacs_constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import (
"context"
"strings"

"github.com/operator-framework/deppy/internal/constraints"
"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/internal/sat"
"github.com/operator-framework/deppy/pkg/constraints"
"github.com/operator-framework/deppy/pkg/entitysource"
)

var _ constraints.ConstraintGenerator = &ConstraintGenerator{}
Expand All @@ -21,11 +20,11 @@ func NewDimacsConstraintGenerator(dimacs *Dimacs) *ConstraintGenerator {
}
}

func (d *ConstraintGenerator) GetVariables(ctx context.Context, querier entitysource.EntityQuerier) ([]sat.Variable, error) {
func (d *ConstraintGenerator) GetVariables(ctx context.Context, querier entitysource.EntityQuerier) ([]constraints.IVariable, error) {
varMap := make(map[entitysource.EntityID]*constraints.Variable, len(d.dimacs.variables))
variables := make([]sat.Variable, 0, len(d.dimacs.variables))
variables := make([]constraints.IVariable, 0, len(d.dimacs.variables))
if err := querier.Iterate(ctx, func(entity *entitysource.Entity) error {
variable := constraints.NewVariable(sat.Identifier(entity.ID()))
variable := constraints.NewVariable(constraints.Identifier(entity.ID()))
variables = append(variables, variable)
varMap[entity.ID()] = variable
return nil
Expand All @@ -45,10 +44,10 @@ func (d *ConstraintGenerator) GetVariables(ctx context.Context, querier entityso
// TODO: check constraints haven't already been added to the variable
variable := varMap[entitysource.EntityID(strings.TrimPrefix(first, "-"))]
if strings.HasPrefix(first, "-") {
variable.AddConstraint(sat.Not())
variable.AddConstraint(constraints.Not())
} else {
// TODO: is this the right constraint here? (given that its an achoring constraint?)
variable.AddConstraint(sat.Mandatory())
variable.AddConstraint(constraints.Mandatory())
}
continue
}
Expand All @@ -59,7 +58,7 @@ func (d *ConstraintGenerator) GetVariables(ctx context.Context, querier entityso
negOperand := strings.HasPrefix(second, "-")

// TODO: this Or constraint is hacky as hell
variable.AddConstraint(sat.Or(sat.Identifier(strings.TrimPrefix(second, "-")), negSubject, negOperand))
variable.AddConstraint(constraints.Or(constraints.Identifier(strings.TrimPrefix(second, "-")), negSubject, negOperand))
first = second
}
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/dimacs/dimacs_source.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package dimacs

import (
"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/pkg/entitysource"
"github.com/operator-framework/deppy/pkg/entitysource/factory"
)

var _ entitysource.EntitySource = &EntitySource{}

type EntitySource struct {
*entitysource.CacheQuerier
entitysource.EntityQuerier
entitysource.EntityContentGetter
}

Expand All @@ -19,7 +20,7 @@ func NewDimacsEntitySource(dimacs *Dimacs) *EntitySource {
}

return &EntitySource{
CacheQuerier: entitysource.NewCacheQuerier(entities),
EntityQuerier: factory.NewCacheQuerier(entities),
EntityContentGetter: entitysource.NoContentSource(),
}
}
8 changes: 4 additions & 4 deletions cmd/sudoku/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

"github.com/spf13/cobra"

"github.com/operator-framework/deppy/internal/constraints"
"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/internal/solver"
constraintsfactory "github.com/operator-framework/deppy/pkg/constraints/factory"
entitysourcefactory "github.com/operator-framework/deppy/pkg/entitysource/factory"
"github.com/operator-framework/deppy/pkg/solver/factory"
)

func NewSudokuCommand() *cobra.Command {
Expand All @@ -24,7 +24,7 @@ func NewSudokuCommand() *cobra.Command {
func solve() error {
// build solver
sudoku := NewSudoku()
so, err := solver.NewDeppySolver(entitysource.NewGroup(sudoku), constraints.NewConstraintAggregator(sudoku))
so, err := factory.NewDeppySolver(entitysourcefactory.NewGroup(sudoku), constraintsfactory.NewConstraintAggregator(sudoku))
if err != nil {
return err
}
Expand Down
41 changes: 21 additions & 20 deletions cmd/sudoku/sudoku.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import (
"strconv"
"time"

"github.com/operator-framework/deppy/internal/constraints"
"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/internal/sat"
"github.com/operator-framework/deppy/pkg/constraints"
"github.com/operator-framework/deppy/pkg/entitysource"
"github.com/operator-framework/deppy/pkg/entitysource/factory"
)

var _ entitysource.EntitySource = &Sudoku{}

var _ constraints.ConstraintGenerator = &Sudoku{}

type Sudoku struct {
*entitysource.CacheQuerier
entitysource.EntityQuerier
entitysource.EntityContentGetter
}

Expand All @@ -42,22 +43,22 @@ func NewSudoku() *Sudoku {
}
}
return &Sudoku{
CacheQuerier: entitysource.NewCacheQuerier(entities),
EntityQuerier: factory.NewCacheQuerier(entities),
EntityContentGetter: entitysource.NoContentSource(),
}
}

func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQuerier) ([]sat.Variable, error) {
func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQuerier) ([]constraints.IVariable, error) {
// adapted from: https://github.com/go-air/gini/blob/871d828a26852598db2b88f436549634ba9533ff/sudoku_test.go#L10
variables := make(map[sat.Identifier]*constraints.Variable, 0)
inorder := make([]sat.Variable, 0)
variables := make(map[constraints.Identifier]*constraints.Variable, 0)
inorder := make([]constraints.IVariable, 0)
rand.Seed(time.Now().UnixNano())

// create variables for all number in all positions of the board
for row := 0; row < 9; row++ {
for col := 0; col < 9; col++ {
for n := 0; n < 9; n++ {
variable := constraints.NewVariable(sat.Identifier(GetID(row, col, n)))
variable := constraints.NewVariable(constraints.Identifier(GetID(row, col, n)))
variables[variable.Identifier()] = variable
inorder = append(inorder, variable)
}
Expand All @@ -67,16 +68,16 @@ func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQue
// add a clause stating that every position on the board has a number
for row := 0; row < 9; row++ {
for col := 0; col < 9; col++ {
ids := make([]sat.Identifier, 9)
ids := make([]constraints.Identifier, 9)
for n := 0; n < 9; n++ {
ids[n] = sat.Identifier(GetID(row, col, n))
ids[n] = constraints.Identifier(GetID(row, col, n))
}
// randomize order to create new sudoku boards every run
rand.Shuffle(len(ids), func(i, j int) { ids[i], ids[j] = ids[j], ids[i] })

// create clause that the particular position has a number
varID := sat.Identifier(fmt.Sprintf("%d-%d has a number", row, col))
variable := constraints.NewVariable(varID, sat.Mandatory(), sat.Dependency(ids...))
varID := constraints.Identifier(fmt.Sprintf("%d-%d has a number", row, col))
variable := constraints.NewVariable(varID, constraints.Mandatory(), constraints.Dependency(ids...))
variables[varID] = variable
inorder = append(inorder, variable)
}
Expand All @@ -86,10 +87,10 @@ func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQue
for n := 0; n < 9; n++ {
for row := 0; row < 9; row++ {
for colA := 0; colA < 9; colA++ {
idA := sat.Identifier(GetID(row, colA, n))
idA := constraints.Identifier(GetID(row, colA, n))
variable := variables[idA]
for colB := colA + 1; colB < 9; colB++ {
variable.AddConstraint(sat.Conflict(sat.Identifier(GetID(row, colB, n))))
variable.AddConstraint(constraints.Conflict(constraints.Identifier(GetID(row, colB, n))))
}
}
}
Expand All @@ -99,10 +100,10 @@ func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQue
for n := 0; n < 9; n++ {
for col := 0; col < 9; col++ {
for rowA := 0; rowA < 9; rowA++ {
idA := sat.Identifier(GetID(rowA, col, n))
idA := constraints.Identifier(GetID(rowA, col, n))
variable := variables[idA]
for rowB := rowA + 1; rowB < 9; rowB++ {
variable.AddConstraint(sat.Conflict(sat.Identifier(GetID(rowB, col, n))))
variable.AddConstraint(constraints.Conflict(constraints.Identifier(GetID(rowB, col, n))))
}
}
}
Expand All @@ -116,12 +117,12 @@ func (s Sudoku) GetVariables(ctx context.Context, querier entitysource.EntityQue
// all numbers
for n := 0; n < 9; n++ {
for i, offA := range offs {
idA := sat.Identifier(GetID(x+offA.x, y+offA.y, n))
idA := constraints.Identifier(GetID(x+offA.x, y+offA.y, n))
variable := variables[idA]
for j := i + 1; j < len(offs); j++ {
offB := offs[j]
idB := sat.Identifier(GetID(x+offB.x, y+offB.y, n))
variable.AddConstraint(sat.Conflict(idB))
idB := constraints.Identifier(GetID(x+offB.x, y+offB.y, n))
variable.AddConstraint(constraints.Conflict(idB))
}
}
}
Expand Down
19 changes: 7 additions & 12 deletions internal/constraints/constraint_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,27 @@ package constraints
import (
"context"

"github.com/operator-framework/deppy/internal/entitysource"
"github.com/operator-framework/deppy/internal/sat"
pkgconstraints "github.com/operator-framework/deppy/pkg/constraints"
"github.com/operator-framework/deppy/pkg/entitysource"
)

// ConstraintGenerator generates solver constraints given an entity querier interface
type ConstraintGenerator interface {
GetVariables(ctx context.Context, querier entitysource.EntityQuerier) ([]sat.Variable, error)
}

var _ ConstraintGenerator = &ConstraintAggregator{}
var _ pkgconstraints.ConstraintGenerator = &ConstraintAggregator{}

// ConstraintAggregator is a simple structure that aggregates different constraint generators
// and collects all generated solver constraints
type ConstraintAggregator struct {
constraintGenerators []ConstraintGenerator
constraintGenerators []pkgconstraints.ConstraintGenerator
}

func NewConstraintAggregator(constraintGenerators ...ConstraintGenerator) *ConstraintAggregator {
func NewConstraintAggregator(constraintGenerators []pkgconstraints.ConstraintGenerator) *ConstraintAggregator {
return &ConstraintAggregator{
constraintGenerators: constraintGenerators,
}
}

func (b *ConstraintAggregator) GetVariables(ctx context.Context, entityQuerier entitysource.EntityQuerier) ([]sat.Variable, error) {
func (b *ConstraintAggregator) GetVariables(ctx context.Context, entityQuerier entitysource.EntityQuerier) ([]pkgconstraints.IVariable, error) {
// TODO: refactor to scatter cather through go routines
variables := make([]sat.Variable, 0)
variables := make([]pkgconstraints.IVariable, 0)
for _, constraintGenerator := range b.constraintGenerators {
vars, err := constraintGenerator.GetVariables(ctx, entityQuerier)
if err != nil {
Expand Down
30 changes: 0 additions & 30 deletions internal/constraints/variable.go

This file was deleted.

24 changes: 14 additions & 10 deletions internal/entitysource/cache_querier.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
package entitysource

import "context"
import (
"context"

var _ EntityQuerier = &CacheQuerier{}
pkgentitysource "github.com/operator-framework/deppy/pkg/entitysource"
)

var _ pkgentitysource.EntityQuerier = &CacheQuerier{}

type CacheQuerier struct {
// TODO: separate out a cache
entities map[EntityID]Entity
entities map[pkgentitysource.EntityID]pkgentitysource.Entity
}

func NewCacheQuerier(entities map[EntityID]Entity) *CacheQuerier {
func NewCacheQuerier(entities map[pkgentitysource.EntityID]pkgentitysource.Entity) *CacheQuerier {
return &CacheQuerier{
entities: entities,
}
}

func (c CacheQuerier) Get(_ context.Context, id EntityID) *Entity {
func (c CacheQuerier) Get(_ context.Context, id pkgentitysource.EntityID) *pkgentitysource.Entity {
if entity, ok := c.entities[id]; ok {
return &entity
}
return nil
}

func (c CacheQuerier) Filter(_ context.Context, filter Predicate) (EntityList, error) {
resultSet := EntityList{}
func (c CacheQuerier) Filter(_ context.Context, filter pkgentitysource.Predicate) (pkgentitysource.EntityList, error) {
resultSet := pkgentitysource.EntityList{}
for _, entity := range c.entities {
if filter(&entity) {
resultSet = append(resultSet, entity)
Expand All @@ -32,8 +36,8 @@ func (c CacheQuerier) Filter(_ context.Context, filter Predicate) (EntityList, e
return resultSet, nil
}

func (c CacheQuerier) GroupBy(_ context.Context, fn GroupByFunction) (EntityListMap, error) {
resultSet := EntityListMap{}
func (c CacheQuerier) GroupBy(_ context.Context, fn pkgentitysource.GroupByFunction) (pkgentitysource.EntityListMap, error) {
resultSet := pkgentitysource.EntityListMap{}
for _, entity := range c.entities {
keys := fn(&entity)
for _, key := range keys {
Expand All @@ -43,7 +47,7 @@ func (c CacheQuerier) GroupBy(_ context.Context, fn GroupByFunction) (EntityList
return resultSet, nil
}

func (c CacheQuerier) Iterate(_ context.Context, fn IteratorFunction) error {
func (c CacheQuerier) Iterate(_ context.Context, fn pkgentitysource.IteratorFunction) error {
for _, entity := range c.entities {
if err := fn(&entity); err != nil {
return err
Expand Down
Loading

0 comments on commit d303cd9

Please sign in to comment.