Skip to content

Commit 72429c2

Browse files
kwesiRutledgeKwesi Rutledge
and
Kwesi Rutledge
authored
Introduced Some Basic Substitution Features (#12)
* Adding the New Required Methods Substitute and SubstituteAccordingTo to Expression object * Adding the Substitute and SubstituteAccordingTo methods to Constant-like objects * Introduced Power Function (need tests!) * Introduced Substitution Functions * Reverted substitution map to use map[Variable]Expression and introduced checking function for it * Added Tests for Variable.Substitute and a few other functions * Added Tests for KMatrix Substitute, Degree, SubstituteAccordingTo, and Power * Added Tests for Concretizing Vector Expressions * Added Tests for Checking Substitution Map * Added Tests for MonomialVector.Minus * Added Tests for MonomialVector.Degree and MonomialVector.Power * Added Tests for MatrixExpression.ConcretizeMatrixExpression * Added Tests for Variable.Power, Variable.SubstituteAccordingTo * Added Tests for Monomial.Minus * Added Tests for Monomial.Minus * Modified coverage file so that we don't consider the examples directory * Removed extraneous switch in Monomial.Minus + modified the IsVectorExpression and IsMatrixExpression * Modified ToVectorExpression as well * Added More Tests for Monomial.Multiply() and Monomial.DerivativeWrt() * Added Tests for ScalarExpression.ScalarPowerTemplate * Updated ConstantMatrix.Multiply to accept more types + added tests for more Polynomial functions * Added Tests for MatrixSubstituteTemplate and MatrixPowerTemplate * Simplified Some of VectorExpression functions and added tests for error handling in VectorExpression templates * Modified VariableVector.Minus() (to simplify it) and tested it * Added Simple Test of Power Function * Added Simple Test of MonomialMatrix.Substitute and MonomialMatrix.Minus Functions * Changed how we concretize matrix and vectors of monomials * Added tests for MonomialMatrix.SubstituteAccordingTo --------- Co-authored-by: Kwesi Rutledge <[email protected]>
1 parent 451b14c commit 72429c2

37 files changed

+5665
-108
lines changed

Diff for: .github/workflows/coverage1.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636

3737
- name: Test Coverage
3838
run: |
39-
go test -v -cover ./... -coverprofile coverage.out -coverpkg ./...
39+
go test -v -cover $(go list ./... | grep -v /examples/) -coverprofile coverage.out -coverpkg ./...
4040
go tool cover -func coverage.out -o coverage2.out
4141
4242
- name: Upload coverage reports to Codecov

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ This project was motivated by the need for a symbolic math package for defining
6464
optimization and control theory problems in Go, but symbolic mathematics is a topic that covers
6565
a wide range of applications. If this tool is not useful for your purpose, then you might
6666
find one of the following projects more helpful:
67+
6768
While other symbolic math libraries exist for Go, they typically focus on:
6869
- Computer Algebra Systems that will help you get a final expression (in text) from
6970
arbitrary math input (often in text) \[[expreduce](https://github.com/corywalker/expreduce),[sm](https://github.com/Konstantin8105/sm)\]
7071
- Implementing Algorithms from [Domain-Specific Languages of Mathematics](https://github.com/DSLsofMath/DSLsofMath)
7172
Course \[[gosymbol](https://github.com/victorbrun/gosymbol/tree/main)\]
73+
- Machine Learning and algorithms needed to perform automatic differentiation \[[gorgonia](https://github.com/gorgonia/gorgonia)\]

Diff for: smErrors/negative_exponent.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package smErrors
2+
3+
import "fmt"
4+
5+
/*
6+
negative_exponent.go
7+
Description:
8+
9+
Functions related to the negative exponent error.
10+
*/
11+
12+
// Type Definition
13+
type NegativeExponentError struct {
14+
Exponent int
15+
}
16+
17+
// Error
18+
func (e NegativeExponentError) Error() string {
19+
return fmt.Sprintf("received negative exponent (%v); expected non-negative exponent", e.Exponent)
20+
}

Diff for: symbolic/constant.go

+34
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ func (c K) Plus(rightIn interface{}) Expression {
121121
// Convert to VectorExpression
122122
ve, _ := ToVectorExpression(right)
123123
return ve.Plus(c)
124+
case mat.Dense:
125+
return c.Plus(DenseToKMatrix(right))
126+
case *mat.Dense:
127+
return c.Plus(DenseToKMatrix(*right))
124128
case KMatrix, VariableMatrix, MonomialMatrix, PolynomialMatrix:
125129
// Convert to MatrixExpression
126130
me, _ := ToMatrixExpression(right)
@@ -379,3 +383,33 @@ Description:
379383
func (c K) String() string {
380384
return fmt.Sprintf("%v", float64(c))
381385
}
386+
387+
/*
388+
Substitute
389+
Description:
390+
391+
Substitutes the variable vIn with the expression eIn.
392+
*/
393+
func (c K) Substitute(vIn Variable, eIn ScalarExpression) Expression {
394+
return c
395+
}
396+
397+
/*
398+
SubstituteAccordingTo
399+
Description:
400+
401+
Substitutes the variables in the map with the corresponding expressions.
402+
*/
403+
func (c K) SubstituteAccordingTo(subMap map[Variable]Expression) Expression {
404+
return c
405+
}
406+
407+
/*
408+
Power
409+
Description:
410+
411+
Computes the power of the constant.
412+
*/
413+
func (c K) Power(exponent int) Expression {
414+
return ScalarPowerTemplate(c, exponent)
415+
}

Diff for: symbolic/constant_matrix.go

+73
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,23 @@ func (km KMatrix) Plus(e interface{}) Expression {
142142

143143
return km.Plus(rightAsVM) // Reuse VariableMatrix case
144144

145+
case mat.Dense:
146+
return km.Plus(DenseToKMatrix(right)) // Reuse KMatrix case
147+
148+
case *mat.Dense:
149+
return km.Plus(*right) // Reuse mat.Dense case
150+
151+
case KMatrix:
152+
// Create the result matrix
153+
var result KMatrix = make([][]K, nR)
154+
for rIndex := 0; rIndex < nR; rIndex++ {
155+
result[rIndex] = make([]K, nC)
156+
for cIndex := 0; cIndex < nC; cIndex++ {
157+
result[rIndex][cIndex] = km[rIndex][cIndex] + right[rIndex][cIndex]
158+
}
159+
}
160+
return result
161+
145162
case VariableMatrix:
146163
// Create the result matrix
147164
var result PolynomialMatrix = make([][]Polynomial, nR)
@@ -257,6 +274,32 @@ func (km KMatrix) Multiply(e interface{}) Expression {
257274

258275
case K:
259276
return km.Multiply(float64(right)) // Reuse float64 case
277+
case Polynomial:
278+
// Choose the correct output type based on the size of km
279+
nR, nC := km.Dims()[0], km.Dims()[1]
280+
switch {
281+
case (nR == 1) && (nC == 1):
282+
// If the output is a scalar, return a scalar
283+
return km[0][0].Multiply(right)
284+
case nC == 1:
285+
// If the output is a vector, return a vector
286+
var outputVec PolynomialVector = make([]Polynomial, nR)
287+
for rIndex := 0; rIndex < nR; rIndex++ {
288+
outputVec[rIndex] = km[rIndex][0].Multiply(right.Copy()).(Polynomial)
289+
}
290+
return outputVec
291+
default:
292+
// If the output is a matrix, return a matrix
293+
var outputMat PolynomialMatrix = make([][]Polynomial, nR)
294+
for rIndex := 0; rIndex < nR; rIndex++ {
295+
outputMat[rIndex] = make([]Polynomial, nC)
296+
for cIndex := 0; cIndex < nC; cIndex++ {
297+
outputMat[rIndex][cIndex] = km[rIndex][cIndex].Multiply(right.Copy()).(Polynomial)
298+
}
299+
}
300+
return outputMat
301+
}
302+
260303
case *mat.VecDense:
261304
// Use gonum's built-in multiplication function
262305
var product mat.VecDense
@@ -673,3 +716,33 @@ Description:
673716
func (km KMatrix) Degree() int {
674717
return 0
675718
}
719+
720+
/*
721+
Substitute
722+
Description:
723+
724+
Substitutes all occurrences of variable vIn with the expression eIn.
725+
*/
726+
func (km KMatrix) Substitute(vIn Variable, eIn ScalarExpression) Expression {
727+
return km
728+
}
729+
730+
/*
731+
SubstituteAccordingTo
732+
Description:
733+
734+
Substitutes all occurrences of the variables in the map with the corresponding expressions.
735+
*/
736+
func (km KMatrix) SubstituteAccordingTo(subMap map[Variable]Expression) Expression {
737+
return km
738+
}
739+
740+
/*
741+
Power
742+
Description:
743+
744+
Raises the constant matrix to the power of the input integer.
745+
*/
746+
func (km KMatrix) Power(exponent int) Expression {
747+
return MatrixPowerTemplate(km, exponent)
748+
}

Diff for: symbolic/constant_vector.go

+30
Original file line numberDiff line numberDiff line change
@@ -591,3 +591,33 @@ Description:
591591
func (kv KVector) Degree() int {
592592
return 0
593593
}
594+
595+
/*
596+
Substitute
597+
Description:
598+
599+
Substitutes all occurrences of variable vIn with the expression eIn.
600+
*/
601+
func (kv KVector) Substitute(vIn Variable, eIn ScalarExpression) Expression {
602+
return kv
603+
}
604+
605+
/*
606+
SubstituteAccordingTo
607+
Description:
608+
609+
Substitutes all occurrences of the variables in the map with the corresponding expressions.
610+
*/
611+
func (kv KVector) SubstituteAccordingTo(subMap map[Variable]Expression) Expression {
612+
return kv
613+
}
614+
615+
/*
616+
Power
617+
Description:
618+
619+
Raises the scalar expression to the power of the input integer.
620+
*/
621+
func (kv KVector) Power(exponent int) Expression {
622+
return VectorPowerTemplate(kv, exponent)
623+
}

Diff for: symbolic/constraint.go

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Constraint interface {
1212
Right() Expression
1313
ConstrSense() ConstrSense
1414
Check() error
15+
IsLinear() bool
1516
}
1617

1718
func IsConstraint(c interface{}) bool {

Diff for: symbolic/expression.go

+10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ type Expression interface {
5555

5656
// String returns a string representation of the expression
5757
String() string
58+
59+
// Substitute returns the expression with the variable vIn replaced with the expression eIn
60+
Substitute(vIn Variable, eIn ScalarExpression) Expression
61+
62+
// SubstituteAccordingToMap returns the expression with the variables in the map replaced with the corresponding expressions
63+
SubstituteAccordingTo(subMap map[Variable]Expression) Expression
64+
65+
// Power
66+
// Raises the scalar expression to the power of the input integer
67+
Power(exponent int) Expression
5868
}
5969

6070
/*

0 commit comments

Comments
 (0)