2012-09-02

SCIP in C++11 ― 2.3.2節その2


代数操作その2:中置記法による代数操作:問題2.58a

問題2.58aは順番が変わるだけで簡単。
人間にはだいぶ見やすくなるなあ。
ただ2.58bはなんか切りがなくて、あまり興味も持てないのでパス。

----
//sum?
const bool isSum(const List& x)
{return(isPair(x) && isEq("+",cadr(x)));}

//addend
const List addend(const List& x)
{return(car(x));}

//augend
const List augend(const List& x)
{return(caddr(x));}


//make-sum
const List makeSum(const List& a1, const List& a2)
{
    if(isEqNumber(a1,0)){return(a2);}
    else if(isEqNumber(a2,0)){return(a1);}
    else if(isNumber(a1)&&isNumber(a2)){return(a1+a2);}
    return(makeExpression(a1,"+",a2));
}

//product?
const bool isProduct(const List& x)
{return(isPair(x) && isEq("*",cadr(x)));}

//multiplier
const List multiplier(const List& x)
{return(car(x));}

//multoplicand
const List multiplicand(const List& x)
{return(caddr(x));}


//make-product
const List makeProduct(const List& m1, const List& m2)
{
    if(isEqNumber(m1,0)||isEqNumber(m2,0)){return(makeNumber(0));}
    else if(isEqNumber(m1,1)){return(m2);}
    else if(isEqNumber(m2,1)){return(m1);}
    else if(isNumber(m1)&&isNumber(m2)){
        return(m1*m2);
    }else if(isNumber(m2)){
        return(makeExpression(m2,"*",m1));
    }
    return(makeExpression(m1,"*",m2));
}


//exponentiation?
const bool isExponentiation(const List& x)
{return(isPair(x) && isEq("**",cadr(x)));}

//base
const List base(const List& x)
{return(car(x));}

//exponent
const List exponent(const List& x)
{return(caddr(x));}

//make-sum
const List makeExponentiation(const List& b, const List& e)
{
    if(isEqNumber(b,0)){return(makeNumber(0));}
    else if(isEqNumber(e,0)){return(makeNumber(1));}
    else if(isEqNumber(e,1)){return(e);}
    else if(isNumber(e)&&isNumber(b)){
        return(power(b,e));
    }
    return(makeExpression(b,"**",e));
}
//---------abstraction barrier---------

//deriv
const List derivative(const List& expression,
                      const List& variable)
{
    if(isNumber(expression)){return(makeNumber(0));}
    else if(isVariable(expression)){
        if(isSameVariable(expression,variable)){
            return(makeNumber(1));
        }else{
            return(makeNumber(0));
        }
    }else if(isSum(expression)){
        return(makeSum
               (derivative(addend(expression),variable),
                derivative(augend(expression),variable)));
    }else if(isProduct(expression)){
        return(makeSum
               (makeProduct
                (multiplier(expression),
                 derivative(multiplicand(expression),variable)),
                makeProduct
                (derivative(multiplier(expression),variable),
                 multiplicand(expression))));
    }else if(isExponentiation(expression)){
        return(makeProduct
               (exponent(expression),
                makeProduct
                (makeExponentiation
                 (base(expression),
                  exponent(expression)+makeNumber(-1)),
                 derivative(base(expression),variable))));
    }
   
    cerr<<"unknown exoression type --- DERIV "<<expression<<endl;
    return(makeExpression());
}
template<typename LeafType>
const List derivative(const List& expression,
                      const LeafType& variable)
{return(derivative(expression,makeSymbol(variable)));}



int main(int argc, char** argv)
{
    const string variable("x");

    const auto polynomial1(makeExpression("x","+",3));
    cout<<"(deriv "<<expString(polynomial1)
        <<" "<<variable<<")="
        <<expString(derivative(polynomial1,variable))<<endl;
   
    const auto polynomial2(makeExpression("x","*","y"));
    cout<<"(deriv "<<expString(polynomial2)
        <<" "<<variable<<")="
        <<expString(derivative(polynomial2,variable))<<endl;
   
    const auto polynomial3
        (makeExpression
         (makeExpression("x","*","y"),"*",
          makeExpression("x","+",3)));
    cout<<"(deriv "<<expString(polynomial3)
        <<" "<<variable<<")="
        <<expString(derivative(polynomial3,variable))<<endl;

    const auto polynomial4
        (makeExpression("x","**","4"));
    cout<<"(deriv "<<expString(polynomial4)
        <<" "<<variable<<")="
        <<expString(derivative(polynomial4,variable))<<endl;


    const auto polynomial5
        (makeExpression(makeExpression("x","**","4"),"+",
                        makeExpression
                        (3,"*",makeExpression("x","**",3))));
    cout<<"(deriv "<<expString(polynomial5)
        <<" "<<variable<<")="
        <<expString(derivative(polynomial5,variable))<<endl;


    return(0);
}
----
出力
----
(deriv (x + 3) x)=1
(deriv (x * y) x)=y
(deriv ((x * y) * (x + 3)) x)=((x * y) + (y * (x + 3)))
(deriv (x ** 4) x)=(4 * (x ** 3))
(deriv ((x ** 4) + (3 * (x ** 3))) x)=((4 * (x ** 3)) + (3 * (3 * (x ** 2))))

0 件のコメント :

コメントを投稿