github.com/cowsed/Parser@v0.0.0-20211216032244-48b10019d380/simplify.go (about) 1 package parser 2 3 import "fmt" 4 5 //Simplify simplifies a+b 6 //Do something similar with add and subtract to what is done with multiplication 7 //get list of a addends and subtractants and simplify that list down by combining like terms, then turn it back into tree 8 func (a Adder) Simplify() Expression { 9 aIs0 := false 10 bIs0 := false 11 aIsConst := false 12 bIsConst := false 13 14 aVal := 0.0 15 bVal := 0.0 16 A := a.A.Simplify() 17 B := a.B.Simplify() 18 switch v := A.(type) { 19 case Constant: 20 aIsConst = true 21 aVal = v.Value 22 if v.Value == 0 { 23 aIs0 = true 24 } 25 } 26 switch v := B.(type) { 27 case Constant: 28 bIsConst = true 29 bVal = v.Value 30 if v.Value == 0 { 31 bIs0 = true 32 } 33 } 34 if aIsConst && bIsConst { 35 return Constant{aVal + bVal} 36 } 37 //Identity 0+0=0, 0+x=x 38 if aIs0 && bIs0 { 39 return Constant{0} 40 } else if aIs0 { 41 return B 42 } else if bIs0 { 43 return A 44 } 45 46 return a 47 } 48 49 //Simplify simplifies a-b 50 func (s Subtractor) Simplify() Expression { 51 aIs0 := false 52 bIs0 := false 53 A := s.A.Simplify() 54 B := s.B.Simplify() 55 switch v := A.(type) { 56 case Constant: 57 if v.Value == 0 { 58 aIs0 = true 59 } 60 } 61 switch v := B.(type) { 62 case Constant: 63 if v.Value == 0 { 64 bIs0 = true 65 } 66 } 67 if aIs0 && bIs0 { 68 return Constant{0} 69 } else if aIs0 { 70 return Multiplier{ 71 A: Constant{-1}, 72 B: B, 73 } 74 } else if bIs0 { 75 return A 76 } 77 return s 78 } 79 80 //Simplify simplifies A*B 81 func (m Multiplier) Simplify() Expression { 82 aIs0 := false 83 bIs0 := false 84 aIs1 := false 85 bIs1 := false 86 aIsConst := false 87 bIsConst := false 88 aVal := 0.0 89 bVal := 0.0 90 //aSymbol := "" 91 //bSymbol := "" 92 93 fmt.Println("Simplifying multiplication{", m.String()) 94 A := m.A.Simplify() 95 B := m.B.Simplify() 96 fmt.Println("Simplifying multiplication2}", Multiplier{A, B}) 97 98 fmt.Printf("A: %v\n", A) 99 fmt.Printf("B: %v\n", B) 100 //Get data to check for identity rules (1*x=x, 0*x=0) 101 switch v := A.(type) { 102 case Constant: 103 aIsConst = true 104 aVal = v.Value 105 aIs0 = v.Value == 0 106 aIs1 = v.Value == 1 107 case Variable: 108 //aSymbol = v.Symbol 109 } 110 switch v := B.(type) { 111 case Constant: 112 bIsConst = true 113 bVal = v.Value 114 bIs0 = v.Value == 0 115 bIs1 = v.Value == 1 116 case Variable: 117 //bSymbol = v.Symbol 118 } 119 120 //Check Identity rules 121 if aIs0 || bIs0 { 122 fmt.Println("ZEROS", m.String()) 123 return Constant{0} 124 } else if aIs1 { 125 return B 126 } else if bIs1 { 127 return A 128 } 129 //Other possibillities 130 if aIsConst && bIsConst { 131 return Constant{aVal * bVal} 132 } else if aIsConst { 133 return Multiplier{ 134 Constant{aVal}, 135 B, 136 } 137 138 } else if bIsConst { 139 return Multiplier{ 140 A: A, 141 B: Constant{bVal}, 142 } 143 } 144 145 ////Simplify x*x to x^2 146 //if aSymbol == bSymbol && aSymbol != "" { 147 // return Powerer{ 148 // Base: Variable{aSymbol}, 149 // Exponent: Constant{2}, 150 // } 151 //} 152 //while If Mul*Div or Mul*mul or Mul*div 153 //list of numerators, list of denominators 154 //Variable and degree, if its just Variable{x} turn it into x^1 so later can subtract 155 156 //CurrentElement := m 157 //Numerator, Denominator := ListMuls(CurrentElement, true) 158 //fmt.Printf("Numerator: %v\n", Numerator) 159 //fmt.Printf("Denominator: %v\n", Denominator) 160 ////Turn them into powers 161 //simplified := SimplifyFraction(Numerator, Denominator) 162 // 163 //return simplified 164 //for { 165 // switch type of Current element a,b 166 // if is mul or div, follow that branch 167 // if not, add to numerator or denominator, break out of that branch 168 // 169 //} 170 171 fmt.Println("Never Simplified") 172 return Multiplier{ 173 A: A, 174 B: B, 175 } 176 } 177 178 //ListMuls lists all the multiples in the numerator and denominator in the expression 179 //Fix Division 180 //if !Num2Num, in divisions, things that say they go in num go to denom and vice versa 181 //Call next level with things reversed 182 //tmrw implement outer case divider such that it puts a in num and b in denom and also sorts it out with its children 183 func ListMuls(e Expression, NumToNum bool) ([]Expression, []Expression) { 184 num := []Expression{} 185 denom := []Expression{} 186 switch v := e.(type) { 187 case Multiplier: 188 fmt.Println("Multiplication count muls") 189 n2, d2 := ListMuls(v.A, NumToNum) 190 n3, d3 := ListMuls(v.B, NumToNum) 191 if NumToNum { 192 num = append(num, n2...) 193 denom = append(denom, d2...) 194 num = append(num, n3...) 195 denom = append(denom, d3...) 196 197 } else { 198 num = append(num, d2...) 199 denom = append(denom, n2...) 200 num = append(num, d3...) 201 denom = append(denom, n3...) 202 203 } 204 205 case Divider: 206 fmt.Println("DIVIDERERER") 207 n2, d2 := ListMuls(v.A, NumToNum) 208 209 n3, d3 := ListMuls(v.B, NumToNum) 210 if NumToNum { 211 num = append(num, n2...) 212 denom = append(denom, d2...) 213 num = append(num, d3...) 214 denom = append(denom, n3...) 215 } else { 216 num = append(num, d2...) 217 denom = append(denom, n2...) 218 num = append(num, n3...) 219 denom = append(denom, d3...) 220 221 } 222 fmt.Println("num============================================", num) 223 fmt.Println("denom============================================", denom) 224 225 default: 226 num = append(num, v) 227 } 228 229 return num, denom 230 } 231 232 //Simplify simplifies a/b 233 func (d Divider) Simplify() Expression { 234 bIs1 := false 235 aIs0 := false 236 aVal := 0.0 237 bVal := 0.0 238 aIsConst := false 239 bIsConst := false 240 A := d.A.Simplify() 241 B := d.B.Simplify() 242 fmt.Println("Simplifying devision of ", A, "/", B) 243 switch v := A.(type) { 244 case Constant: 245 aIsConst = true 246 aVal = v.Value 247 aIs0 = v.Value == 0 248 } 249 switch v := B.(type) { 250 case Constant: 251 bIsConst = true 252 bVal = v.Value 253 bIs1 = v.Value == 0 254 } 255 //Identities 256 if bIs1 { 257 return A 258 } else if aIs0 { 259 return Constant{0} 260 } else if aIsConst && bIsConst { 261 //const over const simplifies to const 262 return Constant{aVal / bVal} 263 } 264 ////Get list of numerator and denominator 265 //Numerator, Denominator := ListMuls(d, true) 266 ////Numerator2, Denominator2 := ListMuls(B, false) 267 ////Numerator = append(Numerator, Numerator2...) 268 ////Denominator = append(Denominator, Denominator2...) 269 //fmt.Println("Divider num", Numerator) 270 //fmt.Println("Divider denom", Denominator) 271 //fmt.Printf("For dividing num: %v, denom: %v\n", Numerator, Denominator) 272 // 273 //simplified := SimplifyFraction(Numerator, Denominator) 274 //return simplified 275 ////Didn't simplify 276 return Divider{ 277 A: A, 278 B: B, 279 } 280 } 281 282 //SimplifyFraction simplifies a fraction 283 func SimplifyFraction(Numerator, Denominator []Expression) Expression { 284 degreeCounts := map[Expression][]Expression{} 285 coefficientsInNum := []float64{} 286 coefficientsInDenom := []float64{} 287 288 //simplifiedDenom := []Expression{} 289 fmt.Printf("Numerator: %v\n", Numerator) 290 291 for _, e := range Numerator { 292 switch v := e.(type) { 293 case Powerer: 294 //if is var to power, add power to degreecounts, 295 //if is something else to power, use its string representation as key and add degree 296 297 degreeCounts[v.Base] = append(degreeCounts[v.Base], v.Exponent) 298 case Variable: 299 degreeCounts[v] = append(degreeCounts[v], Constant{1}) 300 case Constant: 301 coefficientsInNum = append(coefficientsInNum, v.Value) 302 default: 303 degreeCounts[v] = append(degreeCounts[v], Constant{1}) 304 fmt.Println("Counting degree of ", v.String()) 305 306 } 307 } 308 for _, e := range Denominator { 309 switch v := e.(type) { 310 case Powerer: 311 //if is var to power, subtract power to degreecounts, 312 degreeCounts[v] = append(degreeCounts[v], Multiplier{A: Constant{-1}, B: v.Exponent}) 313 case Variable: 314 fmt.Println("Variavle in denom") 315 degreeCounts[v] = append(degreeCounts[v], Constant{-1}) 316 case Constant: 317 coefficientsInDenom = append(coefficientsInDenom, v.Value) 318 default: 319 //simplifiedNum = append(simplifiedNum, v) 320 degreeCounts[v] = append(degreeCounts[v], Constant{-1}) 321 fmt.Println("Counting degree of ", v.String()) 322 323 } 324 } 325 326 //Find the product of all the coeffecients 327 CoeffecientProduct := 1.0 328 for i := range coefficientsInNum { 329 CoeffecientProduct *= coefficientsInNum[i] 330 } 331 for i := range coefficientsInDenom { 332 CoeffecientProduct /= coefficientsInDenom[i] 333 } 334 335 fmt.Printf("degreeCounts: %v\n", degreeCounts) 336 fmt.Printf("prod: %v\n", CoeffecientProduct) 337 338 parts := []Expression{} 339 for k, v := range degreeCounts { 340 if len(v) == 1 { 341 parts = append(parts, k.Simplify()) 342 continue 343 } else if len(v) == 2 { 344 parts = append(parts, Powerer{Base: k, Exponent: Adder{ 345 A: v[0], 346 B: v[1], 347 }}.Simplify()) 348 } else { 349 degree := Adder{ 350 A: v[0], 351 B: v[1], 352 } 353 for i := 2; i < len(v); i++ { 354 degree = Adder{ 355 A: degree, 356 B: v[i], 357 } 358 } 359 360 parts = append(parts, Powerer{ 361 Base: k, 362 Exponent: degree, 363 }.Simplify()) 364 } 365 } 366 fmt.Printf("parts: %v\n", parts) 367 if len(parts) == 0 { 368 return Constant{CoeffecientProduct} 369 } else if len(parts) == 1 { 370 return Multiplier{ 371 A: Constant{CoeffecientProduct}, 372 B: parts[0], 373 }.Simplify() 374 } else { 375 prevProduct := Multiplier{ 376 A: parts[0], 377 B: parts[1], 378 } 379 for i := 2; i < len(parts); i++ { 380 prevProduct = Multiplier{ 381 A: prevProduct, 382 B: parts[i], 383 } 384 } 385 return Multiplier{ 386 A: Constant{CoeffecientProduct}, 387 B: prevProduct, 388 } //.Simplify() 389 } 390 } 391 392 //Simplify simplifies a powerer 393 func (p Powerer) Simplify() Expression { 394 One := Constant{1} 395 Zero := Constant{0} 396 397 if p.Exponent.Simplify() == One { 398 return p.Base 399 } else if p.Exponent.Simplify() == Zero { 400 return Constant{1} 401 } 402 return Powerer{ 403 Base: p.Base.Simplify(), 404 Exponent: p.Exponent.Simplify(), 405 } 406 } 407 408 //Simplify simplifies ln(a) 409 func (n NaturalLogger) Simplify() Expression { 410 return NaturalLogger{n.A.Simplify()} 411 } 412 413 //Simplify simplifies a constant. can't really simplify it at all 414 func (c Constant) Simplify() Expression { 415 return c 416 } 417 418 //Simplify simplifies a variable. can't really simplify it at all 419 func (v Variable) Simplify() Expression { 420 return v 421 } 422 423 //Simplify simplifies cos(a) 424 func (c Coser) Simplify() Expression { 425 return Coser{c.A.Simplify()} 426 } 427 428 //Simplify simplifies sin(a) 429 func (s Siner) Simplify() Expression { 430 return Siner{s.A.Simplify()} 431 }