Skip to content

Commit 4aba36b

Browse files
kwesiRutledgeKwesi Rutledge
andauthored
Added the Substitute() and SubstituteAccordingTo() methods for constr… (#18)
* Added the Substitute() and SubstituteAccordingTo() methods for constraints to simplify some operations * Upgraded the gonum dependency * Introducing Len() function for vector constraints * Updating github action to use newer version of Go * Added tests for ScalarConstraint's Substitute method * Fixed subtle bug in monomial's substitute according to method * Introduced string() method to constraint * Removing debugging statement * Add in tests for VectorConstraint.Substitute() * Adding tests for VectorConstraint.SubstituteAccordingTo * Added small test for ScalarConstraint.String method * Added tests for MatrixConstraint.Substitute and MatrixConstraint.SubstituteAccordingTo --------- Co-authored-by: Kwesi Rutledge <[email protected]>
1 parent fbfc97e commit 4aba36b

File tree

11 files changed

+939
-11
lines changed

11 files changed

+939
-11
lines changed

.github/workflows/coverage1.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
os: [ubuntu-latest, macos-latest, windows-latest]
17-
go: [1.19]
17+
go: [1.23]
1818
permissions:
1919
# Give the default GITHUB_TOKEN write permission to commit and push the
2020
# added or changed files to the repository.

go.mod

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

3-
go 1.21
3+
go 1.23.0
44

5-
require gonum.org/v1/gonum v0.14.0
5+
toolchain go1.23.8
6+
7+
require gonum.org/v1/gonum v0.16.0

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
2-
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
3-
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
4-
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
1+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
2+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=

symbolic/constraint.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ type Constraint interface {
1313
ConstrSense() ConstrSense
1414
Check() error
1515
IsLinear() bool
16+
Substitute(vIn Variable, seIn ScalarExpression) Constraint
17+
SubstituteAccordingTo(subMap map[Variable]Expression) Constraint
1618
}
1719

1820
func IsConstraint(c interface{}) bool {

symbolic/matrix_constraint.go

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

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

@@ -145,3 +146,48 @@ Description:
145146
func (mc MatrixConstraint) IsLinear() bool {
146147
return IsLinear(mc.RightHandSide) && IsLinear(mc.LeftHandSide)
147148
}
149+
150+
/*
151+
Substitute
152+
Description:
153+
154+
Substitutes the variable vIn with the scalar expression seIn
155+
*/
156+
func (mc MatrixConstraint) Substitute(vIn Variable, seIn ScalarExpression) Constraint {
157+
// Check that the constraint is well formed.
158+
err := mc.Check()
159+
if err != nil {
160+
panic(err)
161+
}
162+
163+
// Substitute the variable in the left hand side
164+
newLHS := mc.LeftHandSide.Substitute(vIn, seIn).(MatrixExpression)
165+
166+
// Substitute the variable in the right hand side
167+
newRHS := mc.RightHandSide.Substitute(vIn, seIn).(MatrixExpression)
168+
169+
return MatrixConstraint{newLHS, newRHS, mc.Sense}
170+
}
171+
172+
/*
173+
SubstituteAccordingTo
174+
Description:
175+
176+
Substitutes the variables in the map with the corresponding expressions
177+
in the given scalar constraint.
178+
*/
179+
func (mc MatrixConstraint) SubstituteAccordingTo(subMap map[Variable]Expression) Constraint {
180+
// Check that the constraint is well formed.
181+
err := mc.Check()
182+
if err != nil {
183+
panic(err)
184+
}
185+
186+
// Substitute the variable in the left hand side
187+
newLHS := mc.LeftHandSide.SubstituteAccordingTo(subMap).(MatrixExpression)
188+
189+
// Substitute the variable in the right hand side
190+
newRHS := mc.RightHandSide.SubstituteAccordingTo(subMap).(MatrixExpression)
191+
192+
return MatrixConstraint{newLHS, newRHS, mc.Sense}
193+
}

symbolic/monomial.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,11 +727,13 @@ func (m Monomial) SubstituteAccordingTo(subMap map[Variable]Expression) Expressi
727727

728728
// Algorithm
729729
// Create the monomial
730-
var out Expression = K(0.0)
730+
var out Expression = K(m.Coefficient)
731731

732732
// Iterate through each variable in the monomial
733-
for tempVar, tempExp := range subMap {
734-
out = out.Substitute(tempVar, tempExp.(ScalarExpression))
733+
for ii, varII := range m.VariableFactors {
734+
out = out.Multiply(
735+
varII.SubstituteAccordingTo(subMap).Power(m.Exponents[ii]),
736+
)
735737
}
736738

737739
// Return

symbolic/scalar_constraint.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,76 @@ func (sc ScalarConstraint) LinearEqualityConstraintRepresentation(wrt ...[]Varia
208208
// Return
209209
return C, d
210210
}
211+
212+
/*
213+
Substitute
214+
Description:
215+
216+
Substitutes the variable vIn with the scalar expression seIn in the
217+
given scalar constraint.
218+
*/
219+
func (sc ScalarConstraint) Substitute(vIn Variable, seIn ScalarExpression) Constraint {
220+
// Check that the constraint is well formed.
221+
err := sc.Check()
222+
if err != nil {
223+
panic(err)
224+
}
225+
226+
// Substitute the variable in the left hand side
227+
newLHS := sc.LeftHandSide.Substitute(vIn, seIn).(ScalarExpression)
228+
229+
// Substitute the variable in the right hand side
230+
newRHS := sc.RightHandSide.Substitute(vIn, seIn).(ScalarExpression)
231+
232+
// Return the new constraint
233+
return ScalarConstraint{
234+
LeftHandSide: newLHS,
235+
RightHandSide: newRHS,
236+
Sense: sc.Sense,
237+
}
238+
}
239+
240+
/*
241+
SubstituteAccordingTo
242+
Description:
243+
244+
Substitutes the variables in the map with the corresponding expressions
245+
in the given scalar constraint.
246+
*/
247+
func (sc ScalarConstraint) SubstituteAccordingTo(subMap map[Variable]Expression) Constraint {
248+
// Check that the constraint is well formed.
249+
err := sc.Check()
250+
if err != nil {
251+
panic(err)
252+
}
253+
254+
// Substitute the variable in the left hand side
255+
newLHS := sc.LeftHandSide.SubstituteAccordingTo(subMap).(ScalarExpression)
256+
257+
// Substitute the variable in the right hand side
258+
newRHS := sc.RightHandSide.SubstituteAccordingTo(subMap).(ScalarExpression)
259+
260+
// Return the new constraint
261+
return ScalarConstraint{
262+
LeftHandSide: newLHS,
263+
RightHandSide: newRHS,
264+
Sense: sc.Sense,
265+
}
266+
}
267+
268+
/*
269+
String
270+
Description:
271+
272+
Returns a string representation of the scalar constraint.
273+
*/
274+
func (sc ScalarConstraint) String() string {
275+
// Check that the constraint is well formed.
276+
err := sc.Check()
277+
if err != nil {
278+
panic(err)
279+
}
280+
281+
// Create the string representation
282+
return sc.LeftHandSide.String() + " " + sc.Sense.String() + " " + sc.RightHandSide.String()
283+
}

symbolic/vector_constraint.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,62 @@ func (vc VectorConstraint) LinearEqualityConstraintRepresentation(wrt ...[]Varia
257257
// Return the tuple
258258
return C, d
259259
}
260+
261+
/*
262+
Substitute
263+
Description:
264+
265+
Substitutes the variable vIn with the scalar expression seIn in the vector constraint.
266+
*/
267+
func (vc VectorConstraint) Substitute(vIn Variable, seIn ScalarExpression) Constraint {
268+
// Check that the constraint is well formed.
269+
err := vc.Check()
270+
if err != nil {
271+
panic(err)
272+
}
273+
274+
// Substitute the variable in the left and right hand sides.
275+
newLHS := vc.LeftHandSide.Substitute(vIn, seIn).(VectorExpression)
276+
newRHS := vc.RightHandSide.Substitute(vIn, seIn).(VectorExpression)
277+
278+
// Return the new constraint
279+
return VectorConstraint{newLHS, newRHS, vc.Sense}
280+
}
281+
282+
/*
283+
SubstituteAccordingTo
284+
Description:
285+
286+
Substitutes the variables in the map with the corresponding expressions
287+
*/
288+
func (vc VectorConstraint) SubstituteAccordingTo(subMap map[Variable]Expression) Constraint {
289+
// Check that the constraint is well formed.
290+
err := vc.Check()
291+
if err != nil {
292+
panic(err)
293+
}
294+
295+
// Substitute the variable in the left and right hand sides.
296+
newLHS := vc.LeftHandSide.SubstituteAccordingTo(subMap).(VectorExpression)
297+
newRHS := vc.RightHandSide.SubstituteAccordingTo(subMap).(VectorExpression)
298+
299+
// Return the new constraint
300+
return VectorConstraint{newLHS, newRHS, vc.Sense}
301+
}
302+
303+
/*
304+
Len
305+
Description:
306+
307+
Returns the length of the vector constraint.
308+
*/
309+
func (vc VectorConstraint) Len() int {
310+
// Check that the constraint is well formed.
311+
err := vc.Check()
312+
if err != nil {
313+
panic(err)
314+
}
315+
316+
// Return the length of the vector constraint.
317+
return vc.LeftHandSide.Len()
318+
}

0 commit comments

Comments
 (0)