Skip to content

Commit c29d02e

Browse files
committed
Introducing the IsLinear methods for OptimizationProblem and Objective
1 parent 12fbd43 commit c29d02e

File tree

3 files changed

+132
-2
lines changed

3 files changed

+132
-2
lines changed

problem/objective.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,13 @@ type Objective struct {
1414
func NewObjective(e symbolic.Expression, sense ObjSense) *Objective {
1515
return &Objective{e, sense}
1616
}
17+
18+
/*
19+
IsLinear
20+
Description:
21+
22+
This method returns true if the objective is linear, false otherwise.
23+
*/
24+
func (o *Objective) IsLinear() bool {
25+
return symbolic.IsLinear(o.Expression)
26+
}

problem/optimization_problem.go

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

33
import (
44
"fmt"
5+
56
"github.com/MatProGo-dev/MatProInterface.go/optim"
67
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
78
)
@@ -301,3 +302,29 @@ func (op *OptimizationProblem) Check() error {
301302
// All Checks Passed!
302303
return nil
303304
}
305+
306+
/*
307+
IsLinear
308+
Description:
309+
310+
Checks if the optimization problem is linear.
311+
Per the definition of a linear optimization problem, the problem is linear if and only if:
312+
1. The objective function is linear (i.e., a constant or an affine combination of variables).
313+
2. All constraints are linear (i.e., an affine combination of variables in an inequality or equality).
314+
*/
315+
func (op *OptimizationProblem) IsLinear() bool {
316+
// Check Objective
317+
if !op.Objective.IsLinear() {
318+
return false
319+
}
320+
321+
// Check Constraints
322+
for _, constraint := range op.Constraints {
323+
if !constraint.IsLinear() {
324+
return false
325+
}
326+
}
327+
328+
// All Checks Passed!
329+
return true
330+
}

testing/problem/optimization_problem_test.go

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ Description:
99

1010
import (
1111
"fmt"
12+
"strings"
13+
"testing"
14+
1215
"github.com/MatProGo-dev/MatProInterface.go/optim"
1316
"github.com/MatProGo-dev/MatProInterface.go/problem"
1417
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
1518
"gonum.org/v1/gonum/mat"
16-
"strings"
17-
"testing"
1819
)
1920

2021
/*
@@ -1019,3 +1020,95 @@ func TestOptimizationProblem_Check2(t *testing.T) {
10191020
}
10201021
}
10211022
}
1023+
1024+
/*
1025+
TestOptimizationProblem_IsLinear1
1026+
Description:
1027+
1028+
Tests the IsLinear function with a simple problem
1029+
that has a constant objective and a single, linear constraint.
1030+
*/
1031+
func TestOptimizationProblem_IsLinear1(t *testing.T) {
1032+
// Constants
1033+
p1 := problem.NewProblem("TestOptimizationProblem_IsLinear1")
1034+
v1 := p1.AddVariable()
1035+
c1 := v1.LessEq(1.0)
1036+
k1 := symbolic.K(1.0)
1037+
1038+
p1.Constraints = append(p1.Constraints, c1)
1039+
1040+
// Create good objective
1041+
p1.Objective = *problem.NewObjective(
1042+
k1, problem.SenseFind,
1043+
)
1044+
1045+
// Algorithm
1046+
isLinear := p1.IsLinear()
1047+
if !isLinear {
1048+
t.Errorf("expected the problem to be linear; received non-linear")
1049+
}
1050+
}
1051+
1052+
/*
1053+
TestOptimizationProblem_IsLinear2
1054+
Description:
1055+
1056+
Tests the IsLinear function with a simple problem
1057+
that has a linear objective containing 3 variables and two lienar constraints,
1058+
each containing one variable.
1059+
*/
1060+
func TestOptimizationProblem_IsLinear2(t *testing.T) {
1061+
// Constants
1062+
p1 := problem.NewProblem("TestOptimizationProblem_IsLinear2")
1063+
vv1 := p1.AddVariableVector(3)
1064+
c1 := vv1.AtVec(0).LessEq(1.0)
1065+
c2 := vv1.AtVec(1).LessEq(1.0)
1066+
1067+
// Add constraints
1068+
p1.Constraints = append(p1.Constraints, c1)
1069+
p1.Constraints = append(p1.Constraints, c2)
1070+
1071+
// Create good objective
1072+
p1.Objective = *problem.NewObjective(
1073+
vv1.Transpose().Multiply(symbolic.OnesVector(3)),
1074+
problem.SenseMinimize,
1075+
)
1076+
1077+
// Algorithm
1078+
isLinear := p1.IsLinear()
1079+
if !isLinear {
1080+
t.Errorf("expected the problem to be linear; received non-linear")
1081+
}
1082+
}
1083+
1084+
/*
1085+
TestOptimizationProblem_IsLinear3
1086+
Description:
1087+
1088+
Tests the IsLinear function with a simple problem
1089+
that has a quadratic objective containing 3 variables and two lienar constraints,
1090+
each containing one variable.
1091+
*/
1092+
func TestOptimizationProblem_IsLinear3(t *testing.T) {
1093+
// Constants
1094+
p1 := problem.NewProblem("TestOptimizationProblem_IsLinear3")
1095+
vv1 := p1.AddVariableVector(3)
1096+
c1 := vv1.AtVec(0).LessEq(1.0)
1097+
c2 := vv1.AtVec(1).LessEq(1.0)
1098+
1099+
// Add constraints
1100+
p1.Constraints = append(p1.Constraints, c1)
1101+
p1.Constraints = append(p1.Constraints, c2)
1102+
1103+
// Create good objective
1104+
p1.Objective = *problem.NewObjective(
1105+
vv1.Transpose().Multiply(vv1),
1106+
problem.SenseMaximize,
1107+
)
1108+
1109+
// Algorithm
1110+
isLinear := p1.IsLinear()
1111+
if isLinear {
1112+
t.Errorf("expected the problem to be non-linear; received linear")
1113+
}
1114+
}

0 commit comments

Comments
 (0)