From 8a16f3fe066bd2d341eca236023ed1819a33ee52 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:56:28 +0000 Subject: [PATCH 1/2] Initial plan From f8bd25a4d6f8eae2eaf7815305bcebb8efc2b6af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Oct 2025 19:03:01 +0000 Subject: [PATCH 2/2] Add FindValueOfExpression function to solution package Co-authored-by: kwesiRutledge <9002730+kwesiRutledge@users.noreply.github.com> --- solution/solution.go | 36 ++++++ testing/solution/solution_test.go | 183 ++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) diff --git a/solution/solution.go b/solution/solution.go index 8dc5b42..7c9d0bf 100644 --- a/solution/solution.go +++ b/solution/solution.go @@ -37,3 +37,39 @@ func ExtractValueOfVariable(s Solution, v symbolic.Variable) (float64, error) { idx := v.ID // Extract index of v return ExtractValueOfVariableWithID(s, idx) } + +// FindValueOfExpression evaluates a symbolic expression using the values from a solution. +// It substitutes all variables in the expression with their values from the solution +// and returns the resulting scalar value. +func FindValueOfExpression(s Solution, expr symbolic.Expression) (float64, error) { + // Get all variables in the expression + vars := expr.Variables() + + // Create a substitution map from variables to their constant values + subMap := make(map[symbolic.Variable]symbolic.Expression) + for _, v := range vars { + val, err := ExtractValueOfVariable(s, v) + if err != nil { + return 0.0, fmt.Errorf( + "failed to extract value for variable %v: %w", + v.ID, + err, + ) + } + subMap[v] = symbolic.K(val) + } + + // Substitute all variables with their values + resultExpr := expr.SubstituteAccordingTo(subMap) + + // Type assert to K (constant) to extract the float64 value + resultK, ok := resultExpr.(symbolic.K) + if !ok { + return 0.0, fmt.Errorf( + "expected substituted expression to be a constant, got type %T", + resultExpr, + ) + } + + return float64(resultK), nil +} diff --git a/testing/solution/solution_test.go b/testing/solution/solution_test.go index 8a3da5e..3ec822c 100644 --- a/testing/solution/solution_test.go +++ b/testing/solution/solution_test.go @@ -134,3 +134,186 @@ func TestSolution_Value1(t *testing.T) { } } + +/* +TestSolution_FindValueOfExpression1 +Description: + + This function tests whether we can evaluate a simple linear expression + using the solution values. +*/ +func TestSolution_FindValueOfExpression1(t *testing.T) { + // Constants + v1 := symbolic.NewVariable() + v2 := symbolic.NewVariable() + + tempSol := solution.DummySolution{ + Values: map[uint64]float64{ + v1.ID: 2.0, + v2.ID: 3.0, + }, + Objective: 2.3, + Status: solution_status.OPTIMAL, + } + + // Create expression: 2*v1 + 3*v2 = 2*2.0 + 3*3.0 = 4.0 + 9.0 = 13.0 + expr := v1.Multiply(symbolic.K(2.0)).Plus(v2.Multiply(symbolic.K(3.0))) + + // Algorithm + result, err := solution.FindValueOfExpression(&tempSol, expr) + if err != nil { + t.Errorf("FindValueOfExpression returned an error: %v", err) + } + + expected := 13.0 + if result != expected { + t.Errorf( + "Expected expression value to be %v; received %v", + expected, + result, + ) + } +} + +/* +TestSolution_FindValueOfExpression2 +Description: + + This function tests whether we can evaluate a constant expression. +*/ +func TestSolution_FindValueOfExpression2(t *testing.T) { + // Constants + tempSol := solution.DummySolution{ + Values: map[uint64]float64{}, + Objective: 2.3, + Status: solution_status.OPTIMAL, + } + + // Create constant expression: 42.0 + expr := symbolic.K(42.0) + + // Algorithm + result, err := solution.FindValueOfExpression(&tempSol, expr) + if err != nil { + t.Errorf("FindValueOfExpression returned an error: %v", err) + } + + expected := 42.0 + if result != expected { + t.Errorf( + "Expected expression value to be %v; received %v", + expected, + result, + ) + } +} + +/* +TestSolution_FindValueOfExpression3 +Description: + + This function tests whether we can evaluate an expression with a single variable. +*/ +func TestSolution_FindValueOfExpression3(t *testing.T) { + // Constants + v1 := symbolic.NewVariable() + + tempSol := solution.DummySolution{ + Values: map[uint64]float64{ + v1.ID: 5.5, + }, + Objective: 2.3, + Status: solution_status.OPTIMAL, + } + + // Create expression: v1 + 10 = 5.5 + 10 = 15.5 + expr := v1.Plus(symbolic.K(10.0)) + + // Algorithm + result, err := solution.FindValueOfExpression(&tempSol, expr) + if err != nil { + t.Errorf("FindValueOfExpression returned an error: %v", err) + } + + expected := 15.5 + if result != expected { + t.Errorf( + "Expected expression value to be %v; received %v", + expected, + result, + ) + } +} + +/* +TestSolution_FindValueOfExpression4 +Description: + + This function tests whether we get an error when a variable is missing + from the solution. +*/ +func TestSolution_FindValueOfExpression4(t *testing.T) { + // Constants + v1 := symbolic.NewVariable() + v2 := symbolic.NewVariable() + + tempSol := solution.DummySolution{ + Values: map[uint64]float64{ + v1.ID: 2.0, + // v2 is missing + }, + Objective: 2.3, + Status: solution_status.OPTIMAL, + } + + // Create expression: v1 + v2 + expr := v1.Plus(v2) + + // Algorithm + _, err := solution.FindValueOfExpression(&tempSol, expr) + if err == nil { + t.Errorf("Expected FindValueOfExpression to return an error for missing variable, but got nil") + } +} + +/* +TestSolution_FindValueOfExpression5 +Description: + + This function tests whether we can evaluate a more complex expression + with multiple operations. +*/ +func TestSolution_FindValueOfExpression5(t *testing.T) { + // Constants + v1 := symbolic.NewVariable() + v2 := symbolic.NewVariable() + v3 := symbolic.NewVariable() + + tempSol := solution.DummySolution{ + Values: map[uint64]float64{ + v1.ID: 1.0, + v2.ID: 2.0, + v3.ID: 3.0, + }, + Objective: 2.3, + Status: solution_status.OPTIMAL, + } + + // Create expression: (v1 + v2) * v3 + 5 = (1.0 + 2.0) * 3.0 + 5 = 3.0 * 3.0 + 5 = 9.0 + 5 = 14.0 + expr := v1.Plus(v2).Multiply(v3).Plus(symbolic.K(5.0)) + + // Algorithm + result, err := solution.FindValueOfExpression(&tempSol, expr) + if err != nil { + t.Errorf("FindValueOfExpression returned an error: %v", err) + } + + expected := 14.0 + if result != expected { + t.Errorf( + "Expected expression value to be %v; received %v", + expected, + result, + ) + } +}