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  }