All Downloads are FREE. Search and download functionalities are using the official Maven repository.

expr.Derivative.scala Maven / Gradle / Ivy

package galileo.expr

import galileo.environment.Environment
import galileo.expr._
import galileo.trigonometry._
import galileo.linalg.Matrix
import galileo.tensor.Tensor

// dy / dx
// complete derivative
case class Derivative( y:Expr, x:Expr ) extends Expr {
	override def toString() = "deriv(" + y.toString() + "," + x.toString() + ")"
	def info(env:Option[Environment]=None) = this.toString()

	// This is interesting,
	// variables is only used for the chain rule -- not sure this function will ever be used
	def variables:List[Variable] = List() // To Be Determined
	// should we remove x from env before visiting?
	override def visit(env:Option[Environment]) = ( y.visit( env ), x.visit( env ) ) match{
		case (_,s:Statement) => ErrorExpr( "Can't derive with respect to " + s )
		case (_,m:Matrix) => ErrorExpr( "Can't derive with respect to " + m )
		case (_,t:Tensor) => ErrorExpr( "Can't derive with respect to " + t )
		case (Number(_),_) => Number( 0 )
		case (a:Variable, b:Variable ) if ( a == b ) => Number( 1 )
		case (a:Variable, b:Variable ) => Number( 0 ) // not a dependency
		case (s:Sum,b) => Sum( s.terms.map( term => Derivative( term, b ) ):_* ).visit()
		case (Product( e1, e2 ), b ) => Sum( 
			Product( e1, Derivative( e2, b ) ), 
			Product( Derivative( e1, b ), e2 )
		).visit()
		case (p:Product, b ) => {
			var terms:List[Expr] = Nil
			var leftFactors:List[Expr] = Nil
			for( i <- 0 until p.factors.size ) {
				val factor:Expr = p.factors( i )
				val rightFactors:List[Expr] = p.factors.takeRight( p.factors.size - i - 1 ).to[List]
				val term = Product( leftFactors ++ rightFactors :+ Derivative( factor, b ) ).visit()
				terms = terms :+ term
				leftFactors = leftFactors :+ factor  
			}
			Sum( terms ).visit()
		}
		// D(g/h) = ( D(g) h - g D( h ) ) / h^2
		case( Fraction(g,h),b:Variable) => h match {
			// common special case D( g/x^2)
			case Power(a,Number(2)) if( a == b ) => Fraction( Diff( Product( Derivative( g, b ), a ), Product( Number( 2 ), g ) ), Cube( a ) ).visit()
			case _ => Fraction( Diff( Product( Derivative( g, b ), h ), Product( g, Derivative( h, b ) ) ), Square( h ) ).visit()
		}

		case (ExpF1( e ), b ) => Product( ExpF1( e ), Derivative( e, b ) ).visit()
		case (LogF1( e ), b ) => Product( Power( e, Number( -1 ) ), Derivative( e, b ) ).visit()
		case (CosF1( e ), b ) => Product( Product( Number( -1 ), SinF1( e  ) ), Derivative( e, b ) ).visit()
		case (SinF1( e ), b ) => Product( CosF1( e  ), Derivative( e, b ) ).visit()
		case (TanF1( e ), b ) => Fraction( Product( Number( -1 ), Derivative( e, b ) ), Power( CosF1( e ), Number( 2 ) ) ).visit()
		// d f^g = f^g dg + g * f ^ ( g - 1 ) * df
		case (Power( o, e ), b ) => Sum(
			Product( e, Power( o, Sum( e, Number( -1 ) ) ), Derivative( o, b ) ),
			Product( Derivative( e, b ), Power( o, e ) )
		).visit()
		// Chain Rule
		/*
		case (_,e:Expr) => {
			e.variables()
		}
		*/
		/*
		case (Variable( name ), v: => if( name == v.name ) Number( 1 ) else Number( 0 )
		case Sum( e1, e2 ) => Sum( e1 derive v, e2 derive v )
		case Product( e1, e2 ) => Sum( Product( e1, e2 derive v), Product( e1 derive v, e2 ) )
		case Power( e1, e2 ) => Product( e2, Power( e1, Sum( e2, Number( -1 ) ) ) )
		case ExpF1( e ) => Product( ExpF1( e ), e derive v )
		case LogF1( e ) => Product( Power( e, Number( -1 ) ), e derive v )
		case CosF1( e ) => Product( Product( Number( -1 ), SinF1( e  ) ), e derive v )
		case SinF1( e ) => Product( CosF1( e  ), e derive v )
		*/
	} 
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy