Skip to content

Commit

Permalink
Merge pull request #6 from MatProGo-dev/kr-feature-problem1
Browse files Browse the repository at this point in the history
Introducing the Problem Object
  • Loading branch information
kwesiRutledge committed Feb 28, 2024
2 parents 3fdab38 + 01047eb commit 8f5ea00
Show file tree
Hide file tree
Showing 44 changed files with 2,205 additions and 567 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Go # The name of the workflow that will appear on Github

on:
push:
branches: [ main , kr-feature-multiply1 ]
branches: [ main , kr-feature-problem1 ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ code. Hopefully, this is avoided using this format.
* [ ] Decide whether or not we really need the Coeffs() method (What is it doing?)
* [ ] Write changes to all AtVec() methods to output both elements AND errors (so we can detect out of length calls)
* [ ] Determine whether or not to keep the Solution and Solver() interfaces in this module. It seems like they can be solver-specific.
* [ ] Introduce MatrixVar object
* [ ] Add Check() to:
* [ ] Expression
* [ ] ScalarExpression
* [ ] VectorExpression interfaces
* [ ] VectorExpression interfaces
* [ ] Add ToSymbolic() Method for ALL expressions
9 changes: 4 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module github.com/MatProGo-dev/MatProInterface.go

go 1.19
go 1.21

require (
github.com/hashicorp/go-version v1.6.0
gonum.org/v1/gonum v0.12.0
)
require gonum.org/v1/gonum v0.14.0

require github.com/MatProGo-dev/SymbolicMath.go v0.1.4
21 changes: 16 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs=
gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o=
gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY=
github.com/MatProGo-dev/SymbolicMath.go v0.0.0-20240104201035-f9a42f642121 h1:nnJVXcnTvAdkfR4kZRBw4Ot+KoL8S3PijlLTmKOooco=
github.com/MatProGo-dev/SymbolicMath.go v0.0.0-20240104201035-f9a42f642121/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
github.com/MatProGo-dev/SymbolicMath.go v0.1.0 h1:FUwLQZzZhtgGj6WKyuwQE74P9UYhgbNr5eD5f8zzuu8=
github.com/MatProGo-dev/SymbolicMath.go v0.1.0/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
github.com/MatProGo-dev/SymbolicMath.go v0.1.1 h1:YigpL7w5D8qLu0xzDAayMXePBh9LK0/w3ykvuoVZwXQ=
github.com/MatProGo-dev/SymbolicMath.go v0.1.1/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
github.com/MatProGo-dev/SymbolicMath.go v0.1.2 h1:9tYbiHWm0doXOSipd02pxtENqBU8WhmHTrDXetPW+ms=
github.com/MatProGo-dev/SymbolicMath.go v0.1.2/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
github.com/MatProGo-dev/SymbolicMath.go v0.1.3 h1:IeofFqvZ/jAO6LywlZR/UMl5t/KOyMAvvctVgTzvgHI=
github.com/MatProGo-dev/SymbolicMath.go v0.1.3/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
github.com/MatProGo-dev/SymbolicMath.go v0.1.4 h1:6DaDRYoANmKMkZL0uSUSx7Ibx8Hc9S6AX+7L0hIy1A4=
github.com/MatProGo-dev/SymbolicMath.go v0.1.4/go.mod h1:gKbGR/6sYWi2koMUEDIPWBPi6jQPELKle0ijIM+eaHU=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
12 changes: 12 additions & 0 deletions optim/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package optim

import (
"fmt"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
"gonum.org/v1/gonum/mat"
)

Expand Down Expand Up @@ -246,3 +247,14 @@ func (c K) Check() error {
func (c K) Transpose() Expression {
return c
}

/*
ToSymbolic
Description:
Converts the constant to a symbolic expression (i.e., one that uses the
symbolic math toolbox).
*/
func (c K) ToSymbolic() (symbolic.Expression, error) {
return symbolic.K(c), nil
}
52 changes: 52 additions & 0 deletions optim/constr_sense.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package optim

import "github.com/MatProGo-dev/SymbolicMath.go/symbolic"

// ConstrSense represents if the constraint x <= y, x >= y, or x == y. For easy
// integration with Gurobi, the senses have been encoding using a byte in
// the same way Gurobi encodes the constraint senses.
type ConstrSense byte

// Different constraint senses conforming to Gurobi's encoding.
const (
SenseEqual ConstrSense = '='
SenseLessThanEqual = '<'
SenseGreaterThanEqual = '>'
)

/*
ToSymbolic
Description:
Converts a constraint sense to a the appropriate representation
in the symbolic math toolbox.
*/
func (cs ConstrSense) ToSymbolic() symbolic.ConstrSense {
switch cs {
case SenseEqual:
return symbolic.SenseEqual
case SenseLessThanEqual:
return symbolic.SenseLessThanEqual
case SenseGreaterThanEqual:
return symbolic.SenseGreaterThanEqual
}
return '1'
}

/*
String
Description:
Returns the string representation of the constraint sense.
*/
func (cs ConstrSense) String() string {
switch cs {
case SenseEqual:
return "=="
case SenseLessThanEqual:
return "<="
case SenseGreaterThanEqual:
return ">="
}
return "UNRECOGNIZED ConstrSense"
}
2 changes: 2 additions & 0 deletions optim/constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Description:
type Constraint interface {
Left() Expression
Right() Expression
ConstrSense() ConstrSense
Check() error
}

func IsConstraint(c interface{}) bool {
Expand Down
5 changes: 5 additions & 0 deletions optim/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package optim

import (
"fmt"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
)

/*
Expand Down Expand Up @@ -52,6 +53,10 @@ type Expression interface {

// Comparison
Comparison(rightIn interface{}, sense ConstrSense, errors ...error) (Constraint, error)

//ToSymbolic
// Converts the expression to a symbolic expression (in SymbolicMath.go)
ToSymbolic() (symbolic.Expression, error)
}

/*
Expand Down
82 changes: 23 additions & 59 deletions optim/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package optim

import (
"fmt"
"time"
)

// Model represents the overall constrained linear optimization model to be
Expand All @@ -14,24 +13,12 @@ type Model struct {
Variables []Variable
Constraints []Constraint
Obj *Objective
ShowLog bool
TimeLimit time.Duration
}

// NewModel returns a new model with some default arguments such as not to show
// the log and no time limit.
// the log.
func NewModel(name string) *Model {
return &Model{Name: name, ShowLog: false}
}

//// ShowLog instructs the solver to show the log or not.
//func (m *Model) ShowLog(shouldShow bool) {
// m.ShowLog = shouldShow
//}

// SetTimeLimit sets the solver time limit for the model.
func (m *Model) SetTimeLimit(dur time.Duration) {
m.TimeLimit = dur
return &Model{Name: name}
}

/*
Expand Down Expand Up @@ -168,47 +155,24 @@ func (m *Model) SetObjective(e Expression, sense ObjSense) error {
return nil
}

//// Optimize optimizes the model using the given solver type and returns the
//// solution or an error.
//func (m *Model) Optimize(solver Solver) (*Solution, error) {
// // Variables
// var err error
//
// // Input Processing
// if len(m.Variables) == 0 {
// return nil, errors.New("no variables in model")
// }
//
// solver.ShowLog(m.ShowLog)
//
// if m.TimeLimit > 0 {
// solver.SetTimeLimit(m.TimeLimit.Seconds())
// }
//
// solver.AddVariables(m.Variables)
//
// for _, constr := range m.Constraints {
// solver.AddConstraint(constr)
// }
//
// mipSol, err := solver.Optimize()
// defer solver.DeleteSolver()
//
// if err != nil {
// return nil, fmt.Errorf("There was an issue while trying to optimize the model: %v", err)
// }
//
// if mipSol.Status != OptimizationStatus_OPTIMAL {
// errorMessage, err := mipSol.Status.ToMessage()
// if err != nil {
// return nil, fmt.Errorf("There was an issue converting optimization status to a message: %v", err)
// }
// return nil, fmt.Errorf(
// "[Code = %d] %s",
// mipSol.Status,
// errorMessage,
// )
// }
//
// return &mipSol, nil
//}
/*
Check
Description:
Checks the model for errors.
*/
func (m *Model) Check() error {
// Constants

// Verifiy that there is at least one variable in the model.
if len(m.Variables) == 0 {
return fmt.Errorf("the model has no variables!")
}

// It's okay if there are no constraints.

// It's okay if there is not an objective.

// All Checks have passed.
return nil
}
50 changes: 39 additions & 11 deletions optim/scalar_constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func (sc ScalarConstraint) Right() Expression {
return sc.RightHandSide
}

func (sc ScalarConstraint) ConstrSense() ConstrSense {
return sc.Sense
}

/*
IsLinear
Description:
Expand Down Expand Up @@ -106,14 +110,38 @@ func (sc ScalarConstraint) Simplify() (ScalarConstraint, error) {

}

// ConstrSense represents if the constraint x <= y, x >= y, or x == y. For easy
// integration with Gurobi, the senses have been encoding using a byte in
// the same way Gurobi encodes the constraint senses.
type ConstrSense byte

// Different constraint senses conforming to Gurobi's encoding.
const (
SenseEqual ConstrSense = '='
SenseLessThanEqual = '<'
SenseGreaterThanEqual = '>'
)
/*
Check
Description:
Checks the validity of the ScalarConstraint, this makes sure that:
- The Sense if either SenseEqual, SenseLessThanEqual, or SenseGreaterThanEqual
*/
func (sc ScalarConstraint) Check() error {
// Check sense
switch sc.Sense {
case SenseEqual:
break
case SenseLessThanEqual:
break
case SenseGreaterThanEqual:
break
default:
return fmt.Errorf("the constraint sense is not recognized.")
}

// Check left and right hand sides
err := sc.LeftHandSide.Check()
if err != nil {
return fmt.Errorf("left hand side of the constraint is not valid: %v", err)
}

// Check right hand side
err = sc.RightHandSide.Check()
if err != nil {
return fmt.Errorf("right hand side of the constraint is not valid: %v", err)
}

// Return
return nil
}
8 changes: 8 additions & 0 deletions optim/scalar_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package optim

import (
"fmt"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
)

// ScalarExpression represents a linear general expression of the form
Expand Down Expand Up @@ -58,6 +59,13 @@ type ScalarExpression interface {

//Transpose returns the transpose of the given vector expression
Transpose() Expression

//ToSymbolic Returns the symbolic version of the scalar expression
// (i.e., the expression when declared using the symbolic math toolbox).
ToSymbolic() (symbolic.Expression, error)

// Check, checks the expression for any errors
Check() error
}

// NewExpr returns a new expression with a single additive constant value, c,
Expand Down
28 changes: 28 additions & 0 deletions optim/scalar_linear_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package optim

import (
"fmt"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
"gonum.org/v1/gonum/mat"
)

Expand Down Expand Up @@ -421,3 +422,30 @@ Description:
func (sle ScalarLinearExpr) Transpose() Expression {
return sle
}

/*
ToSymbolic
Description:
Converts the constant to a symbolic expression (i.e., one that uses the
symbolic math toolbox).
*/
func (sle ScalarLinearExpr) ToSymbolic() (symbolic.Expression, error) {
// Check for errors
err := sle.Check()
if err != nil {
return nil, err
}

// Compute product of L and X
symX, err := sle.X.ToSymbolic()
if err != nil {
return nil, err
}

tempProduct := symbolic.VecDenseToKVector(sle.L).Transpose().Multiply(symX)

// Add C
return tempProduct.Plus(symbolic.K(sle.C)), nil

}

0 comments on commit 8f5ea00

Please sign in to comment.