Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 0 additions & 117 deletions problem/solution.go

This file was deleted.

30 changes: 30 additions & 0 deletions solution/dummy_solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package solution

import solution_status "github.com/MatProGo-dev/MatProInterface.go/solution/status"

type DummySolution struct {
Values map[uint64]float64

// The objective for the solution
Objective float64

// Whether or not the solution is within the optimality threshold
Status solution_status.SolutionStatus

// The optimality gap returned from the solver. For many solvers, this is
// the gap between the best possible solution with integer relaxation and
// the best integer solution found so far.
// Gap float64
}

func (ds *DummySolution) GetOptimalValue() float64 {
return ds.Objective
}

func (ds *DummySolution) GetValueMap() map[uint64]float64 {
return ds.Values
}

func (ds *DummySolution) GetStatus() solution_status.SolutionStatus {
return ds.Status
}
39 changes: 39 additions & 0 deletions solution/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package solution

import (
"fmt"

solution_status "github.com/MatProGo-dev/MatProInterface.go/solution/status"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
)

const (
tinyNum float64 = 0.01
)

// Solution stores the solution of an optimization problem and associated
// metadata
type Solution interface {
GetOptimalValue() float64
GetValueMap() map[uint64]float64

// GetStatus
//
GetStatus() solution_status.SolutionStatus
}

func ExtractValueOfVariableWithID(s Solution, idx uint64) (float64, error) {
val, ok := s.GetValueMap()[idx]
if !ok {
return 0.0, fmt.Errorf(
"The idx \"%v\" was not in the variable map for the solution.",
idx,
)
}
return val, nil
}

func ExtractValueOfVariable(s Solution, v symbolic.Variable) (float64, error) {
idx := v.ID // Extract index of v
return ExtractValueOfVariableWithID(s, idx)
}
72 changes: 72 additions & 0 deletions solution/status/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package solution_status

import "fmt"

type SolutionStatus int

// OptimizationStatuses
const (
LOADED SolutionStatus = 1
OPTIMAL SolutionStatus = 2
INFEASIBLE SolutionStatus = 3
INF_OR_UNBD SolutionStatus = 4
UNBOUNDED SolutionStatus = 5
CUTOFF SolutionStatus = 6
ITERATION_LIMIT SolutionStatus = 7
NODE_LIMIT SolutionStatus = 8
TIME_LIMIT SolutionStatus = 9
SOLUTION_LIMIT SolutionStatus = 10
INTERRUPTED SolutionStatus = 11
NUMERIC SolutionStatus = 12
SUBOPTIMAL SolutionStatus = 13
INPROGRESS SolutionStatus = 14
USER_OBJ_LIMIT SolutionStatus = 15
WORK_LIMIT SolutionStatus = 16
)

/*
ToMessage
Description:

Translates the code to the text meaning.
This comes from the status codes documentation: https://www.gurobi.com/documentation/9.5/refman/optimization_status_codes.html#sec:StatusCodes
*/
func (os SolutionStatus) ToMessage() (string, error) {
// Converts each of the statuses to a text message that is human readable.
switch os {
case LOADED:
return "Model is loaded, but no solution information is available.", nil
case OPTIMAL:
return "Model was solved to optimality (subject to tolerances), and an optimal solution is available.", nil
case INFEASIBLE:
return "Model was proven to be infeasible.", nil
case INF_OR_UNBD:
return "Model was proven to be either infeasible or unbounded. To obtain a more definitive conclusion, set the DualReductions parameter to 0 and reoptimize.", nil
case UNBOUNDED:
return "Model was proven to be unbounded. Important note: an unbounded status indicates the presence of an unbounded ray that allows the objective to improve without limit. It says nothing about whether the model has a feasible solution. If you require information on feasibility, you should set the objective to zero and reoptimize.", nil
case CUTOFF:
return "Optimal objective for model was proven to be worse than the value specified in the Cutoff parameter. No solution information is available.", nil
case ITERATION_LIMIT:
return "Optimization terminated because the total number of simplex iterations performed exceeded the value specified in the IterationLimit parameter, or because the total number of barrier iterations exceeded the value specified in the BarIterLimit parameter.", nil
case NODE_LIMIT:
return "Optimization terminated because the total number of branch-and-cut nodes explored exceeded the value specified in the NodeLimit parameter.", nil
case TIME_LIMIT:
return "Optimization terminated because the time expended exceeded the value specified in the TimeLimit parameter.", nil
case SOLUTION_LIMIT:
return "Optimization terminated because the number of solutions found reached the value specified in the SolutionLimit parameter.", nil
case INTERRUPTED:
return "Optimization was terminated by the user.", nil
case NUMERIC:
return "Optimization was terminated due to unrecoverable numerical difficulties.", nil
case SUBOPTIMAL:
return "Unable to satisfy optimality tolerances; a sub-optimal solution is available.", nil
case INPROGRESS:
return "An asynchronous optimization call was made, but the associated optimization run is not yet complete.", nil
case USER_OBJ_LIMIT:
return "User specified an objective limit (a bound on either the best objective or the best bound), and that limit has been reached.", nil
case WORK_LIMIT:
return "Optimization terminated because the work expended exceeded the value specified in the WorkLimit parameter.", nil
default:
return "", fmt.Errorf("The status with value %v is unrecognized.", os)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package problem
package solution_test

import (
"github.com/MatProGo-dev/MatProInterface.go/optim"
"github.com/MatProGo-dev/MatProInterface.go/problem"
"strings"
"testing"

"github.com/MatProGo-dev/MatProInterface.go/solution"
solution_status "github.com/MatProGo-dev/MatProInterface.go/solution/status"
"github.com/MatProGo-dev/SymbolicMath.go/symbolic"
)

/*
Expand All @@ -16,13 +18,13 @@ Description:

func TestSolution_ToMessage1(t *testing.T) {
// Constants
tempSol := problem.Solution{
tempSol := solution.DummySolution{
Values: map[uint64]float64{
0: 2.1,
1: 3.14,
},
Objective: 2.3,
Status: problem.OptimizationStatus_NODE_LIMIT,
Status: solution_status.NODE_LIMIT,
}

// Test the ToMessage() Call on this solution.
Expand All @@ -45,7 +47,7 @@ func TestSolution_ToMessage2(t *testing.T) {

// Test
for statusIndex := 1; statusIndex < statusMax; statusIndex++ {
tempStatus := problem.OptimizationStatus(statusIndex)
tempStatus := solution_status.SolutionStatus(statusIndex)

msg, err := tempStatus.ToMessage()
if err != nil {
Expand Down Expand Up @@ -94,33 +96,40 @@ Description:
*/
func TestSolution_Value1(t *testing.T) {
// Constants
tempSol := problem.Solution{
v1 := symbolic.NewVariable()
v2 := symbolic.NewVariable()

tempSol := solution.DummySolution{
Values: map[uint64]float64{
0: 2.1,
1: 3.14,
v1.ID: 2.1,
v2.ID: 3.14,
},
Objective: 2.3,
Status: problem.OptimizationStatus_NODE_LIMIT,
}
v1 := optim.Variable{
ID: 0, Lower: -optim.INFINITY, Upper: optim.INFINITY, Vtype: optim.Continuous,
}
v2 := optim.Variable{
ID: 1, Lower: -optim.INFINITY, Upper: optim.INFINITY, Vtype: optim.Continuous,
Status: solution_status.NODE_LIMIT,
}

// Algorithm
if tempSol.Value(v1) != 2.1 {
v1Val, err := solution.ExtractValueOfVariable(&tempSol, v1)
if err != nil {
t.Errorf("The value of the variable v1 could not be extracted; received error %v", err)
}

if v1Val != 2.1 {
t.Errorf(
"Expected v1 to have value 2.1; received %v",
tempSol.Value(v1),
v1Val,
)
}

if tempSol.Value(v2) != 3.14 {
v2Val, err := solution.ExtractValueOfVariable(&tempSol, v2)
if err != nil {
t.Errorf("The value of the variable v2 could not be extracted; received error %v", err)
}

if v2Val != 3.14 {
t.Errorf(
"Expected v2 to have value 3.14; received %v",
tempSol.Value(v2),
v2Val,
)
}

Expand Down