Skip to content

Commit 451b14c

Browse files
Merge pull request #10 from MatProGo-dev/kr-feature-panics1
Introducing More Methods for PolynomialLike objects and Many More Tests
2 parents fd793a8 + 4c88229 commit 451b14c

34 files changed

+3571
-277
lines changed

Diff for: smErrors/dimension_error.go

+23
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,29 @@ func CheckDimensionsInAddition(left, right MatrixLike) error {
7070
return nil
7171
}
7272

73+
/*
74+
CheckDimensionsInSubtraction
75+
Description:
76+
77+
This function checks that the dimensions of the left and right expressions
78+
*/
79+
func CheckDimensionsInSubtraction(left, right MatrixLike) error {
80+
// Check that the size of columns in left and right agree
81+
dimsAreMatched := (left.Dims()[0] == right.Dims()[0]) && (left.Dims()[1] == right.Dims()[1])
82+
dimsAreMatched = dimsAreMatched || IsScalarExpression(left)
83+
dimsAreMatched = dimsAreMatched || IsScalarExpression(right)
84+
85+
if !dimsAreMatched {
86+
return DimensionError{
87+
Operation: "Minus",
88+
Arg1: left,
89+
Arg2: right,
90+
}
91+
}
92+
// If dimensions match, then return nothing.
93+
return nil
94+
}
95+
7396
/*
7497
CheckDimensionsInMultiplication
7598
Description:

Diff for: symbolic/constant.go

+68-18
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,17 @@ func (c K) Plus(rightIn interface{}) Expression {
9292
panic(fmt.Errorf("error in second argument to %v.Plus: %v", c, err))
9393
}
9494

95-
err = smErrors.CheckDimensionsInAddition(c, rightAsE)
96-
if err != nil {
97-
panic(err)
98-
}
95+
// Dimension checks should be fine because c is a scalar.
96+
//err = smErrors.CheckDimensionsInAddition(c, rightAsE)
97+
//if err != nil {
98+
// panic(err)
99+
//}
99100
}
100101

101102
// Switching based on input type
102103
switch right := rightIn.(type) {
104+
case int:
105+
return c.Plus(K(right))
103106
case float64:
104107
return c.Plus(K(right))
105108
case K:
@@ -114,10 +117,14 @@ func (c K) Plus(rightIn interface{}) Expression {
114117
return c.Plus(VecDenseToKVector(right))
115118
case *mat.VecDense:
116119
return c.Plus(VecDenseToKVector(*right))
117-
case KVector:
118-
return right.Plus(c)
119-
case PolynomialVector:
120-
return right.Plus(c)
120+
case KVector, VariableVector, MonomialVector, PolynomialVector:
121+
// Convert to VectorExpression
122+
ve, _ := ToVectorExpression(right)
123+
return ve.Plus(c)
124+
case KMatrix, VariableMatrix, MonomialMatrix, PolynomialMatrix:
125+
// Convert to MatrixExpression
126+
me, _ := ToMatrixExpression(right)
127+
return me.Plus(c)
121128
}
122129

123130
// Default response is a panic
@@ -129,6 +136,45 @@ func (c K) Plus(rightIn interface{}) Expression {
129136
)
130137
}
131138

139+
/*
140+
Minus
141+
Description:
142+
143+
This function subtracts the current expression from another and returns the resulting expression.
144+
*/
145+
func (c K) Minus(rightIn interface{}) Expression {
146+
// Input Processing
147+
if IsExpression(rightIn) {
148+
rightAsE, _ := ToExpression(rightIn)
149+
err := rightAsE.Check()
150+
if err != nil {
151+
panic(fmt.Errorf("error in second argument to %v.Minus: %v", c, err))
152+
}
153+
154+
//err = smErrors.CheckDimensionsInSubtraction(c, rightAsE)
155+
//if err != nil {
156+
// panic(err)
157+
//}
158+
159+
// Use Minus function
160+
return Minus(c, rightAsE)
161+
}
162+
163+
// Switching based on input type
164+
switch right := rightIn.(type) {
165+
case float64:
166+
return c.Minus(K(right))
167+
}
168+
169+
// Default response is a panic
170+
panic(
171+
smErrors.UnsupportedInputError{
172+
FunctionName: "K.Minus",
173+
Input: rightIn,
174+
},
175+
)
176+
}
177+
132178
// LessEq returns a less than or equal to (<=) constraint between the
133179
// current expression and another
134180
func (c K) LessEq(rightIn interface{}) Constraint {
@@ -172,14 +218,10 @@ func (c K) Comparison(rhsIn interface{}, sense ConstrSense) Constraint {
172218
case float64:
173219
// Use the version of Comparison for K
174220
return c.Comparison(K(right), sense)
175-
case K:
176-
return ScalarConstraint{c, right, sense}
177-
case Variable:
178-
return ScalarConstraint{c, right, sense}
179-
case Monomial:
180-
return ScalarConstraint{c, right, sense}
181-
case Polynomial:
182-
return ScalarConstraint{c, right, sense}
221+
case K, Variable, Monomial, Polynomial:
222+
// Cast right to scalar expression
223+
se, _ := ToScalarExpression(right)
224+
return ScalarConstraint{c, se, sense}
183225
case mat.VecDense:
184226
// Convert to KVector
185227
return c.Comparison(VecDenseToKVector(right), sense)
@@ -235,18 +277,26 @@ func (c K) Multiply(term1 interface{}) Expression {
235277

236278
// Input Processing
237279
if IsExpression(term1) {
238-
// Check dimensions
280+
// Cast to expression
239281
term1AsE, _ := ToExpression(term1)
240-
err := smErrors.CheckDimensionsInMultiplication(c, term1AsE)
282+
err := term1AsE.Check()
241283
if err != nil {
242284
panic(err)
243285
}
286+
287+
//// Check dimensions (not necessary for scalar K)
288+
//err := smErrors.CheckDimensionsInMultiplication(c, term1AsE)
289+
//if err != nil {
290+
// panic(err)
291+
//}
244292
}
245293

246294
// Algorithm
247295
switch right := term1.(type) {
248296
case float64:
249297
return c.Multiply(K(right))
298+
case int:
299+
return c.Multiply(K(right))
250300
case K:
251301
return c * right
252302
case Variable:

Diff for: symbolic/constant_matrix.go

+61
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,57 @@ func (km KMatrix) Plus(e interface{}) Expression {
166166
)
167167
}
168168

169+
/*
170+
Minus
171+
Description:
172+
173+
Subtraction of the constant matrix with another expression.
174+
*/
175+
func (km KMatrix) Minus(e interface{}) Expression {
176+
// Input Processing
177+
err := km.Check()
178+
if err != nil {
179+
panic(err)
180+
}
181+
182+
if IsExpression(e) {
183+
rightAsE, _ := ToExpression(e)
184+
185+
// Check expression
186+
err = rightAsE.Check()
187+
if err != nil {
188+
panic(err)
189+
}
190+
191+
// Check Dimensions
192+
err = smErrors.CheckDimensionsInSubtraction(km, rightAsE)
193+
if err != nil {
194+
panic(err)
195+
}
196+
197+
// Use Expression method
198+
return Minus(km, rightAsE)
199+
}
200+
201+
// Algorithm
202+
switch right := e.(type) {
203+
case float64:
204+
return km.Minus(K(right)) // Reuse K case
205+
case mat.Dense:
206+
return km.Minus(DenseToKMatrix(right)) // Reuse KMatrix case
207+
case *mat.Dense:
208+
return km.Minus(*right) // Reuse mat.Dense case
209+
}
210+
211+
// If we reach this point, the input is not recognized
212+
panic(
213+
smErrors.UnsupportedInputError{
214+
FunctionName: "KMatrix.Minus",
215+
Input: e,
216+
},
217+
)
218+
}
219+
169220
/*
170221
Multiply
171222
Description:
@@ -612,3 +663,13 @@ func (km KMatrix) ToPolynomialMatrix() PolynomialMatrix {
612663
// Return
613664
return pm
614665
}
666+
667+
/*
668+
Degree
669+
Description:
670+
671+
The degree of a constant matrix is always 0.
672+
*/
673+
func (km KMatrix) Degree() int {
674+
return 0
675+
}

Diff for: symbolic/constant_vector.go

+64
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ func (kv KVector) Plus(rightIn interface{}) Expression {
138138
case K:
139139
// Return Addition
140140
return kv.Plus(float64(right))
141+
case Variable:
142+
// Create a new polynomial vector
143+
var pvOut PolynomialVector
144+
for _, element := range kv {
145+
pvOut = append(pvOut, element.Plus(right).(Polynomial))
146+
}
147+
return pvOut
141148

142149
case *mat.VecDense:
143150
return kv.Plus(VecDenseToKVector(*right)) // Convert to KVector
@@ -166,6 +173,53 @@ func (kv KVector) Plus(rightIn interface{}) Expression {
166173
}
167174
}
168175

176+
/*
177+
Minus
178+
Description:
179+
180+
Subtracts the current expression from another and returns the resulting expression
181+
*/
182+
func (kv KVector) Minus(e interface{}) Expression {
183+
// Input Processing
184+
err := kv.Check()
185+
if err != nil {
186+
panic(err)
187+
}
188+
189+
if IsExpression(e) {
190+
// Check right
191+
eAsE, _ := ToExpression(e)
192+
err = eAsE.Check()
193+
if err != nil {
194+
panic(err)
195+
}
196+
197+
// Check dimensions
198+
err = smErrors.CheckDimensionsInSubtraction(kv, eAsE)
199+
if err != nil {
200+
panic(err)
201+
}
202+
}
203+
204+
// Algorithm
205+
switch right := e.(type) {
206+
case float64:
207+
return kv.Minus(K(right)) // Reuse K case
208+
case mat.VecDense:
209+
return kv.Minus(VecDenseToKVector(right)) // Convert to KVector
210+
case *mat.VecDense:
211+
return kv.Minus(VecDenseToKVector(*right)) // Convert to KVector
212+
}
213+
214+
// Default response is a panic
215+
panic(
216+
smErrors.UnsupportedInputError{
217+
FunctionName: "KVector.Minus",
218+
Input: e,
219+
},
220+
)
221+
}
222+
169223
/*
170224
LessEq
171225
Description:
@@ -527,3 +581,13 @@ Description:
527581
func (kv KVector) ToPolynomialVector() PolynomialVector {
528582
return kv.ToMonomialVector().ToPolynomialVector()
529583
}
584+
585+
/*
586+
Degree
587+
Description:
588+
589+
The degree of a constant matrix is always 0.
590+
*/
591+
func (kv KVector) Degree() int {
592+
return 0
593+
}

Diff for: symbolic/expression.go

+56
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ type Expression interface {
2121
// expression
2222
Plus(rightIn interface{}) Expression
2323

24+
// Minus subtracts an expression from the current one and returns the resulting
25+
// expression
26+
Minus(rightIn interface{}) Expression
27+
2428
// Multiply multiplies the current expression to another and returns the
2529
// resulting expression
2630
Multiply(rightIn interface{}) Expression
@@ -108,3 +112,55 @@ func ToExpression(e interface{}) (Expression, error) {
108112
},
109113
)
110114
}
115+
116+
/*
117+
Minus
118+
Description:
119+
120+
subtracts the current expression from another and returns the resulting expression
121+
*/
122+
func Minus(left, right Expression) Expression {
123+
return left.Plus(
124+
right.Multiply(-1.0),
125+
)
126+
}
127+
128+
/*
129+
IsLinear
130+
Description:
131+
132+
Determines whether an input object is a
133+
valid linear expression.
134+
In math, this means that the polynomial like expression
135+
has a degree less than or equal to 1.
136+
*/
137+
func IsLinear(e Expression) bool {
138+
// Input Processing
139+
if !IsPolynomialLike(e) {
140+
return false // Not a polynomial like expression, so it can't be linear
141+
}
142+
143+
eAsPL, _ := ToPolynomialLike(e)
144+
145+
return eAsPL.Degree() <= 1
146+
}
147+
148+
/*
149+
IsQuadratic
150+
Description:
151+
152+
Determines whether or not an input object is a
153+
valid Quadratic Expression.
154+
In math, this means that the polynomial like expression
155+
has a degree less than or equal to 2.
156+
*/
157+
func IsQuadratic(e Expression) bool {
158+
// Input Processing
159+
if !IsPolynomialLike(e) {
160+
return false // Not a polynomial like expression, so it can't be linear
161+
}
162+
163+
eAsPL, _ := ToPolynomialLike(e)
164+
165+
return eAsPL.Degree() <= 2
166+
}

0 commit comments

Comments
 (0)