Skip to content

Commit 8f5ea00

Browse files
Merge pull request #6 from MatProGo-dev/kr-feature-problem1
Introducing the Problem Object
2 parents 3fdab38 + 01047eb commit 8f5ea00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2205
-567
lines changed

.github/workflows/coverage1.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Go # The name of the workflow that will appear on Github
22

33
on:
44
push:
5-
branches: [ main , kr-feature-multiply1 ]
5+
branches: [ main , kr-feature-problem1 ]
66
pull_request:
77
branches: [ main ]
88
# Allows you to run this workflow manually from the Actions tab

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ code. Hopefully, this is avoided using this format.
140140
* [ ] Decide whether or not we really need the Coeffs() method (What is it doing?)
141141
* [ ] Write changes to all AtVec() methods to output both elements AND errors (so we can detect out of length calls)
142142
* [ ] Determine whether or not to keep the Solution and Solver() interfaces in this module. It seems like they can be solver-specific.
143-
* [ ] Introduce MatrixVar object
144143
* [ ] Add Check() to:
145144
* [ ] Expression
146145
* [ ] ScalarExpression
147-
* [ ] VectorExpression interfaces
146+
* [ ] VectorExpression interfaces
147+
* [ ] Add ToSymbolic() Method for ALL expressions

go.mod

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
module github.com/MatProGo-dev/MatProInterface.go
22

3-
go 1.19
3+
go 1.21
44

5-
require (
6-
github.com/hashicorp/go-version v1.6.0
7-
gonum.org/v1/gonum v0.12.0
8-
)
5+
require gonum.org/v1/gonum v0.14.0
6+
7+
require github.com/MatProGo-dev/SymbolicMath.go v0.1.4

go.sum

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

optim/constant.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package optim
22

33
import (
44
"fmt"
5+
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
56
"gonum.org/v1/gonum/mat"
67
)
78

@@ -246,3 +247,14 @@ func (c K) Check() error {
246247
func (c K) Transpose() Expression {
247248
return c
248249
}
250+
251+
/*
252+
ToSymbolic
253+
Description:
254+
255+
Converts the constant to a symbolic expression (i.e., one that uses the
256+
symbolic math toolbox).
257+
*/
258+
func (c K) ToSymbolic() (symbolic.Expression, error) {
259+
return symbolic.K(c), nil
260+
}

optim/constr_sense.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package optim
2+
3+
import "github.com/MatProGo-dev/SymbolicMath.go/symbolic"
4+
5+
// ConstrSense represents if the constraint x <= y, x >= y, or x == y. For easy
6+
// integration with Gurobi, the senses have been encoding using a byte in
7+
// the same way Gurobi encodes the constraint senses.
8+
type ConstrSense byte
9+
10+
// Different constraint senses conforming to Gurobi's encoding.
11+
const (
12+
SenseEqual ConstrSense = '='
13+
SenseLessThanEqual = '<'
14+
SenseGreaterThanEqual = '>'
15+
)
16+
17+
/*
18+
ToSymbolic
19+
Description:
20+
21+
Converts a constraint sense to a the appropriate representation
22+
in the symbolic math toolbox.
23+
*/
24+
func (cs ConstrSense) ToSymbolic() symbolic.ConstrSense {
25+
switch cs {
26+
case SenseEqual:
27+
return symbolic.SenseEqual
28+
case SenseLessThanEqual:
29+
return symbolic.SenseLessThanEqual
30+
case SenseGreaterThanEqual:
31+
return symbolic.SenseGreaterThanEqual
32+
}
33+
return '1'
34+
}
35+
36+
/*
37+
String
38+
Description:
39+
40+
Returns the string representation of the constraint sense.
41+
*/
42+
func (cs ConstrSense) String() string {
43+
switch cs {
44+
case SenseEqual:
45+
return "=="
46+
case SenseLessThanEqual:
47+
return "<="
48+
case SenseGreaterThanEqual:
49+
return ">="
50+
}
51+
return "UNRECOGNIZED ConstrSense"
52+
}

optim/constraint.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Description:
1010
type Constraint interface {
1111
Left() Expression
1212
Right() Expression
13+
ConstrSense() ConstrSense
14+
Check() error
1315
}
1416

1517
func IsConstraint(c interface{}) bool {

optim/expression.go

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

33
import (
44
"fmt"
5+
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
56
)
67

78
/*
@@ -52,6 +53,10 @@ type Expression interface {
5253

5354
// Comparison
5455
Comparison(rightIn interface{}, sense ConstrSense, errors ...error) (Constraint, error)
56+
57+
//ToSymbolic
58+
// Converts the expression to a symbolic expression (in SymbolicMath.go)
59+
ToSymbolic() (symbolic.Expression, error)
5560
}
5661

5762
/*

optim/model.go

Lines changed: 23 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package optim
22

33
import (
44
"fmt"
5-
"time"
65
)
76

87
// Model represents the overall constrained linear optimization model to be
@@ -14,24 +13,12 @@ type Model struct {
1413
Variables []Variable
1514
Constraints []Constraint
1615
Obj *Objective
17-
ShowLog bool
18-
TimeLimit time.Duration
1916
}
2017

2118
// NewModel returns a new model with some default arguments such as not to show
22-
// the log and no time limit.
19+
// the log.
2320
func NewModel(name string) *Model {
24-
return &Model{Name: name, ShowLog: false}
25-
}
26-
27-
//// ShowLog instructs the solver to show the log or not.
28-
//func (m *Model) ShowLog(shouldShow bool) {
29-
// m.ShowLog = shouldShow
30-
//}
31-
32-
// SetTimeLimit sets the solver time limit for the model.
33-
func (m *Model) SetTimeLimit(dur time.Duration) {
34-
m.TimeLimit = dur
21+
return &Model{Name: name}
3522
}
3623

3724
/*
@@ -168,47 +155,24 @@ func (m *Model) SetObjective(e Expression, sense ObjSense) error {
168155
return nil
169156
}
170157

171-
//// Optimize optimizes the model using the given solver type and returns the
172-
//// solution or an error.
173-
//func (m *Model) Optimize(solver Solver) (*Solution, error) {
174-
// // Variables
175-
// var err error
176-
//
177-
// // Input Processing
178-
// if len(m.Variables) == 0 {
179-
// return nil, errors.New("no variables in model")
180-
// }
181-
//
182-
// solver.ShowLog(m.ShowLog)
183-
//
184-
// if m.TimeLimit > 0 {
185-
// solver.SetTimeLimit(m.TimeLimit.Seconds())
186-
// }
187-
//
188-
// solver.AddVariables(m.Variables)
189-
//
190-
// for _, constr := range m.Constraints {
191-
// solver.AddConstraint(constr)
192-
// }
193-
//
194-
// mipSol, err := solver.Optimize()
195-
// defer solver.DeleteSolver()
196-
//
197-
// if err != nil {
198-
// return nil, fmt.Errorf("There was an issue while trying to optimize the model: %v", err)
199-
// }
200-
//
201-
// if mipSol.Status != OptimizationStatus_OPTIMAL {
202-
// errorMessage, err := mipSol.Status.ToMessage()
203-
// if err != nil {
204-
// return nil, fmt.Errorf("There was an issue converting optimization status to a message: %v", err)
205-
// }
206-
// return nil, fmt.Errorf(
207-
// "[Code = %d] %s",
208-
// mipSol.Status,
209-
// errorMessage,
210-
// )
211-
// }
212-
//
213-
// return &mipSol, nil
214-
//}
158+
/*
159+
Check
160+
Description:
161+
162+
Checks the model for errors.
163+
*/
164+
func (m *Model) Check() error {
165+
// Constants
166+
167+
// Verifiy that there is at least one variable in the model.
168+
if len(m.Variables) == 0 {
169+
return fmt.Errorf("the model has no variables!")
170+
}
171+
172+
// It's okay if there are no constraints.
173+
174+
// It's okay if there is not an objective.
175+
176+
// All Checks have passed.
177+
return nil
178+
}

optim/scalar_constraint.go

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func (sc ScalarConstraint) Right() Expression {
1919
return sc.RightHandSide
2020
}
2121

22+
func (sc ScalarConstraint) ConstrSense() ConstrSense {
23+
return sc.Sense
24+
}
25+
2226
/*
2327
IsLinear
2428
Description:
@@ -106,14 +110,38 @@ func (sc ScalarConstraint) Simplify() (ScalarConstraint, error) {
106110

107111
}
108112

109-
// ConstrSense represents if the constraint x <= y, x >= y, or x == y. For easy
110-
// integration with Gurobi, the senses have been encoding using a byte in
111-
// the same way Gurobi encodes the constraint senses.
112-
type ConstrSense byte
113-
114-
// Different constraint senses conforming to Gurobi's encoding.
115-
const (
116-
SenseEqual ConstrSense = '='
117-
SenseLessThanEqual = '<'
118-
SenseGreaterThanEqual = '>'
119-
)
113+
/*
114+
Check
115+
Description:
116+
117+
Checks the validity of the ScalarConstraint, this makes sure that:
118+
- The Sense if either SenseEqual, SenseLessThanEqual, or SenseGreaterThanEqual
119+
*/
120+
func (sc ScalarConstraint) Check() error {
121+
// Check sense
122+
switch sc.Sense {
123+
case SenseEqual:
124+
break
125+
case SenseLessThanEqual:
126+
break
127+
case SenseGreaterThanEqual:
128+
break
129+
default:
130+
return fmt.Errorf("the constraint sense is not recognized.")
131+
}
132+
133+
// Check left and right hand sides
134+
err := sc.LeftHandSide.Check()
135+
if err != nil {
136+
return fmt.Errorf("left hand side of the constraint is not valid: %v", err)
137+
}
138+
139+
// Check right hand side
140+
err = sc.RightHandSide.Check()
141+
if err != nil {
142+
return fmt.Errorf("right hand side of the constraint is not valid: %v", err)
143+
}
144+
145+
// Return
146+
return nil
147+
}

optim/scalar_expression.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package optim
22

33
import (
44
"fmt"
5+
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
56
)
67

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

5960
//Transpose returns the transpose of the given vector expression
6061
Transpose() Expression
62+
63+
//ToSymbolic Returns the symbolic version of the scalar expression
64+
// (i.e., the expression when declared using the symbolic math toolbox).
65+
ToSymbolic() (symbolic.Expression, error)
66+
67+
// Check, checks the expression for any errors
68+
Check() error
6169
}
6270

6371
// NewExpr returns a new expression with a single additive constant value, c,

optim/scalar_linear_expr.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package optim
22

33
import (
44
"fmt"
5+
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
56
"gonum.org/v1/gonum/mat"
67
)
78

@@ -421,3 +422,30 @@ Description:
421422
func (sle ScalarLinearExpr) Transpose() Expression {
422423
return sle
423424
}
425+
426+
/*
427+
ToSymbolic
428+
Description:
429+
430+
Converts the constant to a symbolic expression (i.e., one that uses the
431+
symbolic math toolbox).
432+
*/
433+
func (sle ScalarLinearExpr) ToSymbolic() (symbolic.Expression, error) {
434+
// Check for errors
435+
err := sle.Check()
436+
if err != nil {
437+
return nil, err
438+
}
439+
440+
// Compute product of L and X
441+
symX, err := sle.X.ToSymbolic()
442+
if err != nil {
443+
return nil, err
444+
}
445+
446+
tempProduct := symbolic.VecDenseToKVector(sle.L).Transpose().Multiply(symX)
447+
448+
// Add C
449+
return tempProduct.Plus(symbolic.K(sle.C)), nil
450+
451+
}

0 commit comments

Comments
 (0)