Download presentation
Presentation is loading. Please wait.
1
1 CS 410 Mastery in Programming Chapter 7 Hints for: Symbolic Differentiation Herbert G. Mayer, PSU CS status 7/26/2011
2
2 Syllabus Problem Assessment Problem Assessment Rules of First Derivative Rules of First Derivative Data Structures and Types Data Structures and Types Make Node Make Node Copy Tree Copy Tree Print Tree Print Tree Build Tree Build Tree Simplify Simplify Main Main References References
3
3 Problem Assessment Goal of this assignment is to design, code, and execute symbolic differentiation of mathematical formulae or equations These formulae are simple No partial differentiation Just differentiation w.r.t a single variable And that variable is pre-defined to be ‘x’ All numeric constants are integer, and of small value, i.e. single decimal digits Goal was not to focus on scanning, not on lexical analysis All symbolic names different from ‘x’ are constant, w.r.t. first order differentiation If two derivatives are needed, then the output of the first can serve as input to the second differentiation So all formulae are simple, yet the mathematical problem remains highly interesting
4
4 Problem Assessment When applying the rules of differentiation, the result can be a formula with numerous redundancies In such cases it is advised to simplify the result A careful programmer will actually submit the originally input formula f(x) to the same simplification algorithm Each formula input is terminated by a special symbol, the ‘$’ character For example: Input: 2*x+x*3+5+6*x$ Normalized input: ((((2*x)+(x*3))+5)+(6*x)) Output: (((((0*x)+(2*1))+((1*3)+(x*0)))+0)+((0*x)+(6*1))) Simplified output: 11
5
5 Rules of First Derivative f(x)f’(x) f(x) = variable != x f’(x) = 0 f(x) = constant f’(x) = 0 f(x) = x f’(x) = 1 f(x) = u(x) + v(x) f’(x) = u’(x) + v’(x) f(x) = u(x) - v(x) f’(x) = u(x) + v(x) f(x) = u(x) * v(x) f’(x) = u’(x)*v(x) + u(x)*v’(x) f(x) = u(x) / v(x) f’(x)= (u’(x)*v(x) -u(x)*v’(x))/v(x) 2 f(x) = ln(u(x)) f’(x) = u’(x) / u(x) f(x) = u(x) ^ v(x) f’(x) = u' * v * u ^ ( v - 1 ) + & u * v' * u ^ v Example: f(x) = x ^ x f’(x) = 1 * x * x^(x–1) + &x * 1 * x^x = x^x + &x * x^x = x^x + &x * x^x = (&x + 1) * x^x = (&x + 1) * x^x
6
6 Data Structures and Types Each formula is represented internally as a tree Pointed to by “root” Root’s type is pointer to structure of node type Each node is either A literal with a stored integer value –note: single digit A variable, which could be the select variable ‘x’ An operator, with the operator itself being stored, like ‘+’ ‘*’ And has all the following fields Class, specifying literal, variable, operator The single character Symbol, e.g. ‘x’ for the special variable The integer literal value LitVal to remember the integer value And node pointers Left and Right to the subtrees, if any It will be handy store special nodes such as common constants, e.g. the nodes fore the literal 0 and for the literal integer 1
7
7 Data Structures and Types // each node has 1 of these class states: // a literal, an identifier, or an operator. // Parenthesized expressions have been reduced typedef enum { Literal, Identifier, Operator } NodeClass; typedef struct NodeType * NodePtr;// forward announcement // now comes the actual node structure, // using the forward declared pointers. typedef struct NodeType { NodeClassClass;// 1 of the 3 classes. charSymbol;// stores ident or literal intLitVal;// if Literal, this is its value NodePtrLeft;// subtrees NodePtrRight;// subtrees } s_node_tp;
8
8 Make Node // malloc a new node off the heap. All fields passed in // and pass the pointer to the node to caller NodePtr Make( NodeClass Class, char Symbol, int value, NodePtr Left, NodePtr Right ) int value, NodePtr Left, NodePtr Right ) { // Make NodePtr Node = (NodePtr)malloc(sizeof( struct NodeType ) ); Node->Class = Class; Node->Symbol = Symbol; Node->LitVal = value; Node->Left = Left; Node->Right = Right; return Node; } //end Make
9
9 Copy Tree // recursively copy tree pointed to by Root. // Pass pointer to the copy to its caller NodePtr Copy( NodePtr Root ) { // Copy if ( Root == NULL ) { return NULL; }else{ return Make( Root->Class, Root->Symbol, Root->LitVal, Copy( Root->Left ), Copy( Root->Right ) ); } //end if } //end Copy
10
10 Print Tree void PrintTree( NodePtr Root ) { // PrintTree if ( Root != NULL ) { if ( Root != NULL ) { if ( Root->Class == Operator ) { printf( "(" ); } //end if PrintTree( Root->Left ); PrintTree( Root->Left ); if ( Root->Class == Literal ) { printf( "%d", Root->LitVal ); }else{ printf( "%c", Root->Symbol ); } //end if PrintTree( Root->Right ); if ( Root->Class == Operator ) { printf( ")" ); } //end if } //end if*/ } //end if*/ } //end PrintTree
11
11 Build Tree // parse expression and build tree // using Term() and higher priority functions/ops // all returning pointers to nodes. NodePtr Expression( ) { // Expression { // Expression NodePtr Left; NodePtr Left; char Op; char Op; Left = Term(); Left = Term(); while ( NextChar == '-' || NextChar == '+' ) { while ( NextChar == '-' || NextChar == '+' ) { Op = NextChar; Op = NextChar; GetNextChar(); GetNextChar(); Left = Make( Operator, Op, 0, Left, Term() ); Left = Make( Operator, Op, 0, Left, Term() ); } //end while } //end while return Left; return Left; } //end Expression
12
12 Build Tree NodePtr primary( ) { // primary char Symbol; char Symbol; NodePtr Temp; NodePtr Temp; Symbol = NextChar;// first_set = “ ‘(‘, ‘&’, IDENT, LIT } Symbol = NextChar;// first_set = “ ‘(‘, ‘&’, IDENT, LIT } GetNextChar(); GetNextChar(); if ( IsDigit( Symbol ) ) if ( IsDigit( Symbol ) ) return Make( Literal, Symbol, (int)( Symbol - '0' ), NULL, NULL ); else if ( IsLetter( Symbol ) ) { else if ( IsLetter( Symbol ) ) { } return Make( Identifier, tolower( Symbol ), 0, NULL, NULL ); } return Make( Identifier, tolower( Symbol ), 0, NULL, NULL ); }else if ( ‘( == Symbol ) { }else if ( ‘( == Symbol ) { Temp = Expression(); Temp = Expression(); if ( NextChar != ')' ) { if ( NextChar != ')' ) { printf( ") expected.\n" ); printf( ") expected.\n" ); }//end if }//end if GetNextChar(); GetNextChar(); return Temp; return Temp; }else if ( Symbol == '&' ) { return Make( Operator, '&', 0, NULL, primary() ); }else{ printf( "Illegal character '%c'.\n", Symbol ); printf( "Illegal character '%c'.\n", Symbol ); } //end if } //end primary
13
13 Derive, 1 NodePtr Derive( NodePtr Root ) { // Derive if ( NULL == Root ) { return NULL; }else{ switch ( Root->Class ) { case Literal: case Literal: return Make( Literal, '0', 0, NULL, NULL ); case Identifier: case Identifier: if ( ( Root->Symbol == 'x' ) || ( Root->Symbol == 'X' ) ) { return Make( Literal, '1', 1, NULL, NULL ); return Make( Literal, '1', 1, NULL, NULL );}else{ return Make( Literal, '0', 0, NULL, NULL ); return Make( Literal, '0', 0, NULL, NULL ); } //end if case Operator: switch ( Root->Symbol ) { switch ( Root->Symbol ) { case '+': case '-': return Make( Operator, Root->Symbol, 0, return Make( Operator, Root->Symbol, 0, Derive( Root->Left ), Derive( Root->Right ) ); Derive( Root->Left ), Derive( Root->Right ) );...
14
14 Derive, 2... case '*': return Make( Operator, '+', 0, return Make( Operator, '+', 0, Make( Operator, '*', 0, Derive( Root->Left ), Make( Operator, '*', 0, Derive( Root->Left ), Copy( Root->Right ) ), Make( Operator, '*', 0, Copy( Root->Left ), Make( Operator, '*', 0, Copy( Root->Left ), Derive( Root->Right ) ) ); case '/': return Make( Operator, '/', 0, return Make( Operator, '/', 0, Make( Operator, '-', 0, Make( Operator, '*', 0, Derive( Root->Left ), Make( Operator, '*', 0, Derive( Root->Left ), Copy( Root->Right ) ), Make( Operator, '*', 0, Copy( Root->Left ), Make( Operator, '*', 0, Copy( Root->Left ), Derive( Root->Right ) ) ), Make( Operator, '*', 0, Make( Operator, '*', 0, Copy( Root->Right ), Copy( Root->Right ) ) ); } //end switch...
15
15 Derive, 3 case '^': return return Make( Operator, '+', 0, Make( Operator, '+', 0, Make( Operator, '*', 0, Make( Operator, '*', 0, Derive( Root->Left ), Derive( Root->Left ), Make( Operator, '*', 0, Make( Operator, '*', 0, Copy( Root->Right ), Copy( Root->Right ), Make( Operator, '^', 0, Make( Operator, '^', 0, Copy( Root->Left ), Copy( Root->Left ), Make( Operator, '-', 0, Make( Operator, '-', 0, Copy( Root->Right ), Copy( Root->Right ), Copy( & OneNode ) ) ) ) ), Copy( & OneNode ) ) ) ) ), Make( Operator, '*', 0, Make( Operator, '*', 0, Make( Operator, '&', 0, Make( Operator, '&', 0, NULL, NULL, Copy( Root->Left ) ), Copy( Root->Left ) ), Derive( Root->Right ) ), Derive( Root->Right ) ), Make( Operator, '^', 0, Make( Operator, '^', 0, Copy( Root->Left ), Copy( Root->Left ), Copy( Root->Right ) ) ) ); Copy( Root->Right ) ) ) ); case '&': if ( Root->Left != NULL ) { if ( Root->Left != NULL ) { printf( "ln has only one operand.\n" ); printf( "ln has only one operand.\n" ); } //end if } //end if
16
16 Opportunities for Simplification # Original expression Simplified expression 1 x + 0 x 2 0 + x x 3 x - 0 x 4 x - x 0 5 x * 0 0 6 0 * x 0 7 x * 1 x 8 1 * x x 9 x / x 1 10 x / 1 x 11 x ^ 1 x 12 x ^ 0 1 13 & 1 0
17
17 Simplify, 1 NodePtr Simplify( NodePtr Root ) { // Simplify int val = 0; if ( !Root ) { return Root; return Root;}else{ switch ( Root->Class ) { switch ( Root->Class ) { case Literal: case Literal: case Identifier: case Identifier: return Root; case Operator: case Operator: Root->Left = Simplify( Root->Left ); Root->Left = Simplify( Root->Left ); Root->Right = Simplify( Root->Right ); Root->Right = Simplify( Root->Right ); switch ( Root->Symbol ) { switch ( Root->Symbol ) { case '+': case '+': if ( IsLit( '0', Root->Left ) ) { if ( IsLit( '0', Root->Left ) ) { return Root->Right; }else if ( IsLit( '0', Root->Right ) ) { }else if ( IsLit( '0', Root->Right ) ) { return Root->Left; }else if ( BothLit( Root->Left, Root->Right ) ) { val = Root->Left->LitVal + Root->Right->LitVal; return Make( Literal, (char)( val + '0' ), val, NULL, NULL ); }else{ return Root; // no other simplifiction for ‘+’ } //end if...
18
18 Simplify, 2... case '-': if ( IsLit( '0', Root->Right ) ) { if ( IsLit( '0', Root->Right ) ) { return Root->Left; return Root->Left; }else if ( BothLit( Root->Left, Root->Right ) ) { }else if ( BothLit( Root->Left, Root->Right ) ) { val = Root->Left->LitVal - Root->Right->LitVal; val = Root->Left->LitVal - Root->Right->LitVal; return Make( Literal, (char)( val + '0' ), val, NULL, NULL ); return Make( Literal, (char)( val + '0' ), val, NULL, NULL ); }else if ( IsEqual( Root->Left, Root->Right ) ) { }else if ( IsEqual( Root->Left, Root->Right ) ) { return & NullNode; return & NullNode; }else{ }else{ return Root; return Root; } //end if } //end if case '*': if ( IsLit( '1', Root->Left ) ) { if ( IsLit( '1', Root->Left ) ) { return Root->Right; return Root->Right; }else if ( IsLit( '1', Root->Right ) ) { }else if ( IsLit( '1', Root->Right ) ) { return Root->Left; return Root->Left; }else if ( IsLit( '0', Root->Left ) || IsLit( '0', Root->Right ) ) { }else if ( IsLit( '0', Root->Left ) || IsLit( '0', Root->Right ) ) { return & NullNode; return & NullNode; }else{ }else{ return Root; return Root; }//end if }//end if case '/': if ( IsLit( '1', Root->Right ) ) { if ( IsLit( '1', Root->Right ) ) { return Root->Left; return Root->Left; }else if ( IsLit( '0', Root->Left ) ) { }else if ( IsLit( '0', Root->Left ) ) { return & NullNode; return & NullNode; }else if ( IsEqual( Root->Left, Root->Right ) ) { }else if ( IsEqual( Root->Left, Root->Right ) ) { return & OneNode; return & OneNode; }else{ }else{ return Root; return Root; } //end if } //end if case '^': case '^': if ( IsLit( '0', Root->Right ) ) { if ( IsLit( '0', Root->Right ) ) { return & OneNode; return & OneNode; }else if ( IsLit( '1', Root->Right ) ) { }else if ( IsLit( '1', Root->Right ) ) { return Root->Left; return Root->Left; }else{ }else{ return Root; return Root; } //end if } //end if......
19
19 Two Equal Trees // return true only if both subtrees left and right are equal bool IsEqual( NodePtr Left, NodePtr Right ) { // IsEqual if ( ( !Left ) && ( !Right ) ) { if ( ( !Left ) && ( !Right ) ) { return TRUE; return TRUE; }else if ( NULL == Left ) { }else if ( NULL == Left ) { // Right is known to be not NULL // Right is known to be not NULL return FALSE; return FALSE; }else if ( NULL == Right ) { }else if ( NULL == Right ) { // Left is known to be NOT NULL // Left is known to be NOT NULL return FALSE; return FALSE; }else if ( ( Left->Class == Literal ) && ( Right->Class == Literal ) ) { }else if ( ( Left->Class == Literal ) && ( Right->Class == Literal ) ) { return ( Left->LitVal ) == ( Right->LitVal ); return ( Left->LitVal ) == ( Right->LitVal ); }else if ( ( Left->Class == Identifier ) && ( Right->Class == Identifier )){ }else if ( ( Left->Class == Identifier ) && ( Right->Class == Identifier )){ return ( Left->Symbol ) == ( Right->Symbol ); return ( Left->Symbol ) == ( Right->Symbol ); }else{ }else{ // must be Operator; same? // must be Operator; same? if ( ( Left->Symbol ) == ( Right->Symbol ) ) { if ( ( Left->Symbol ) == ( Right->Symbol ) ) { // IsEqual if both subtrees are equal // IsEqual if both subtrees are equal return ( IsEqual( Left->Left, Right->Left ) && return ( IsEqual( Left->Left, Right->Left ) && IsEqual( Left->Right, Right->Right ) ) || IsEqual( Left->Right, Right->Right ) ) || ( is_associative( Left->Symbol ) && ( is_associative( Left->Symbol ) && IsEqual( Left->Left, Right->Right ) && IsEqual( Left->Left, Right->Right ) && IsEqual( Left->Right, Right->Left ) ); IsEqual( Left->Right, Right->Left ) ); }else{ }else{ return FALSE; return FALSE; } //end if } //end if printf( "Impossible to reach in IsEqual.\n" ); printf( "Impossible to reach in IsEqual.\n" ); } //end IsEqual
20
20 main() int main () { // main: Differentiation NodePtr root = NULL; Initialize(); Initialize(); root = Expression(); VERIFY( ( NextChar == '$' ), "$ expected, not found\n" ); SHOW( " original f(x) = ", root ); root = Simplify( root ); SHOW( " Simplified f(x) = ", root ); root = Derive( root ); SHOW( " derived f'(x) = ", root ); root = Simplify( root ); root = Simplify( root ); SHOW( " reduced f'(x) = ", root ); Or else: print_tree( simplify( derive( simplify( expression( root ))))); return 0; } //end main: Differentiation
21
21 References Differentiation rules, implementation code samples: http://www.codeproject.com/KB/recipes/Differentiati on.aspx More code samples in Lisp: http://mitpress.mit.edu/sicp/full- text/sicp/book/node39.html
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.