Beispiel #1
0
        public override INumber Eval(RuntimeData runtime)
        {
            MultipleFormula mf = new Expression.MultipleFormula();

            for (int i = 0; i < this.items.Count; i++)
            {
                var  res  = this.items[i].Eval(runtime);
                bool flag = false;
                for (int j = 0; j < mf.items.Count; j++)
                {
                    if (mf.items[j].CanJoin(runtime, res))
                    {
                        var itm = mf.items[j];
                        mf.items.RemoveAt(j);
                        mf.AddItem(runtime, itm.Multiple(runtime, res));
                        flag = true; break;
                    }
                }
                if (!flag)
                {
                    mf.AddItem(runtime, res);
                }
            }
            if (mf.items.Count == 1)
            {
                return(mf.items[0]);
            }
            else
            {
                return(mf);
            }
        }
Beispiel #2
0
 public override INumber ExecuteDiff(RuntimeData runtime, string t)
 {
     if (Runtime.Func.Differential.IsConstValue(runtime, this.Denominator))
     {
         var res = this.Numerator.ExecuteDiff(runtime, t);
         return(res);
     }
     else
     {
         AdditionFormula af = new Expression.AdditionFormula();
         {
             MultipleFormula mf = new Expression.MultipleFormula();
             mf.AddItem(runtime, this.Numerator.ExecuteDiff(runtime, t));
             mf.AddItem(runtime, this.Denominator);
             af.AddItem(runtime, mf);
         }
         {
             MultipleFormula mf = new Expression.MultipleFormula();
             mf.AddItem(runtime, Number.New(-1));
             mf.AddItem(runtime, this.Denominator.ExecuteDiff(runtime, t));
             mf.AddItem(runtime, this.Numerator);
             af.AddItem(mf);
         }
         Fraction f = new Expression.Fraction(
             this.Denominator.Power(runtime, Number.New(2)),
             af
             );
         return(f);
     }
 }
Beispiel #3
0
        public override INumber Integrate(RuntimeData runtime, string t)
        {
            // 参考 https://oshiete.goo.ne.jp/qa/2664611.html

            MultipleFormula mf = new Expression.MultipleFormula();

            mf.AddItem(runtime, new Variable(t));
            mf.AddItem(runtime, this);
            return(mf);
        }
Beispiel #4
0
        public virtual INumber Integrate(RuntimeData runtime, string t)
        {
            if (this is IConstParameter)
            {
                MultipleFormula mf = new Expression.MultipleFormula();
                mf.AddItem(runtime, this);
                mf.AddItem(runtime, new Variable(t));
                return(mf);
            }

            throw new NotImplementedException();
        }
Beispiel #5
0
        public override INumber Integrate(RuntimeData runtime, string t)
        {
            // 計算し易いように条件を最適化しておく
            var ress = this.Clone().Optimise(runtime);

            if (!(ress is Fraction))
            {
                return(ress.Integrate(runtime, t));
            }

            var res = ress as Fraction;



            // 特殊な定義: ∫(b / x^a)dx → b*log(x) / a
            // ∫(1 / x^2)dxとかはこの条件に当てはまらないので注意しないといけない
            if (runtime.IsConstValue(res.Numerator) &&
                ((res.Denominator is Variable && (res.Denominator as Variable).Name == t) ||
                 (res.Denominator is Member && (res.Denominator as Member).Text == t)) &&
                runtime.IsConstValue(res.Denominator.Pow))
            {
                MultipleFormula mf = new Expression.MultipleFormula();
                mf.AddItem(runtime, res.Numerator);
                mf.AddItem(runtime, new Fraction(res.Denominator.Pow, Number.New(1)));
                mf.AddItem(runtime, new FuncedINumber(
                               runtime.Functions["log"],
                               new INumber[] { new NaturalLogarithm(), res.Denominator }));
                if (runtime.Setting.DoOptimize)
                {
                    return(mf.Optimise(runtime));
                }
                else
                {
                    return(mf);
                }
            }

            // 分母も分子も定数しか含まれていない → 定数として扱う
            if (runtime.IsConstValue(res.Denominator) &&
                runtime.IsConstValue(res.Numerator))
            {
                MultipleFormula mf = new Expression.MultipleFormula();
                mf.AddItem(runtime, res);
                mf.AddItem(runtime, new Variable(t));
                return(mf);
            }

            // 事前に分母と分子に存在する定数を外に出して計算した方がいい
            runtime.Setting.Logger.AddInfo("分数の積分は申し訳程度にしか実装していません。");

            throw new NotImplementedException("分数の積分はあまり対応してない");
        }
Beispiel #6
0
        public override INumber Multiple(RuntimeData runtime, INumber val)
        {
            if (val is FuncedINumber && this.CanJoin(runtime, val))
            {
                var res = this.Clone();
                res.Pow = res.Pow.Add(runtime, val.Pow);
                return(res);
            }

            MultipleFormula mf = new Expression.MultipleFormula();

            mf.AddItem(runtime, val);
            mf.AddItem(runtime, this);
            return(mf);
        }
Beispiel #7
0
        public INumber ExecuteDiff(RuntimeData runtime, string t, INumber[] parameters)
        {
            var res = new FuncedINumber(runtime.Functions["sin"], parameters);

            MultipleFormula mf = new Expression.MultipleFormula();

            mf.AddItem(runtime, Number.New(-1));
            mf.AddItem(runtime, res);

            var vaDiff = parameters[0].ExecuteDiff(runtime, t);

            if (vaDiff.Equals(runtime, Number.New(0)))
            {
                return(mf);
            }

            mf.AddItem(runtime, vaDiff);
            return(mf);
        }
Beispiel #8
0
 public override INumber Multiple(RuntimeData runtime, INumber val)
 {
     if (val.ValueType == ValueType.Plus)
     {
         return(this == InfinityValue.value ? InfinityValue.value : InfinityValue.minusvalue);
     }
     else if (val.ValueType == ValueType.Minus)
     {
         return(this == InfinityValue.value ? InfinityValue.minusvalue : InfinityValue.value);
     }
     else   // val.ValueType == ValueType.Unknown
     {
         if (val is MultipleFormula)
         {
             var             res = this;
             MultipleFormula mf  = new Expression.MultipleFormula();
             for (int i = 0; i < (val as MultipleFormula).Items.Count; i++)
             {
                 var item = (val as MultipleFormula).Items[i];
                 if (item.ValueType == ValueType.Minus)
                 {
                     res = (res == InfinityValue.value) ? InfinityValue.minusvalue : InfinityValue.value;
                 }
                 if (item.ValueType == ValueType.Unknown)
                 {
                     mf.AddItem(runtime, item);
                 }
             }
             mf.AddItem(runtime, res);
             return(mf);
         }
         else
         {
             MultipleFormula mf = new MultipleFormula();
             mf.AddItem(runtime, this);
             mf.AddItem(runtime, val);
             return(mf);
         }
     }
 }
Beispiel #9
0
 public static MultipleFormula DiffPow(RuntimeData runtime, string t, INumber val)
 {
     if (!val.Pow.Equals(runtime, Number.New(1)))
     {
         var res = val.Pow.ExecuteDiff(runtime, t);
         if (!res.Equals(runtime, Number.New(0)))
         {
             // powの所に式が含まれているため対数微分法を使う必要がある
             throw new NotImplementedException("未実装: Powに式が含まれているため対数微分法を使って微分する必要あり");
         }
         else
         {
             MultipleFormula mf = new Expression.MultipleFormula();
             mf.AddItem(runtime, val.Pow);
             return(mf);
         }
     }
     return(null);
 }
Beispiel #10
0
        private INumber DiffExecute(RuntimeData runtime, string t, INumber m, INumber param0, bool kaiki)
        {
            if (m is IConstParameter)
            {
                return(Number.New(0));
            }

            if (m is Variable)
            {
                Variable v = m.Clone() as Variable;
                if (v.Name == t)
                {
                    if (v.Pow.Equals(runtime, Number.New(1)))
                    {
                        return(v.Multi);
                    }
                    INumber multiple   = v.Multi.Multiple(runtime, v.Pow);
                    bool    powFormula = !(v.Pow is IConstParameter);
                    var     pow        = v.Pow;
                    v.Pow   = v.Pow.Subtract(runtime, Number.New(1));
                    v.Multi = multiple;

                    if (powFormula)
                    {
                        MultipleFormula mf = new Expression.MultipleFormula();
                        mf.AddItem(runtime, v);
                        mf.AddItem(runtime, ExecuteDiff(runtime, pow, t, param0));
                        return(mf);
                    }
                    else
                    {
                        if (runtime.Setting.DoOptimize)
                        {
                            return(v.Optimise(runtime));
                        }
                        else
                        {
                            return(v);
                        }
                    }
                }
                else
                {
                    if (kaiki)
                    {
                        throw new FunctionExecutionCancelException();
                    }

                    // y*(y')みたいな形にする
                    MultipleFormula mf = new Expression.MultipleFormula();
                    FunctionFormula ff = new Expression.FunctionFormula();
                    Formula         f  = new Formula()
                    {
                        Token = new Token("(", Analyzer.TokenType.Syntax)
                    };
                    var d = new Variable(new FuncCalc.Token(t, Analyzer.TokenType.Member));
                    mf.Items.Add(m);
                    ff.AddItem(runtime, new Member(new Token("diff", Analyzer.TokenType.Member)));
                    f.AddItem(runtime, d);
                    f.AddItem(runtime, new LineBreak(new Token(",", Analyzer.TokenType.Syntax)));
                    f.AddItem(runtime, v);
                    ff.AddItem(runtime, f);
                    mf.Items.Add(ff); // AddItemを使うと無限ループ
                    // return mf;
                    return(ff);
                }
            }

            throw new NotImplementedException();
        }
Beispiel #11
0
        public INumber ExecuteDiff(RuntimeData runtime, string t, INumber[] parameters)
        {
            // log(xy) => log(x) + log(y)
            if (parameters[1] is MultipleFormula)
            {
                AdditionFormula af = new Expression.AdditionFormula();
                foreach (var item in (parameters[1] as MultipleFormula).Items)
                {
                    af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], item }));
                }
                return(af);
            }
            if (parameters[1] is Fraction)
            {
                AdditionFormula af = new Expression.AdditionFormula();
                Fraction        f  = parameters[1] as Fraction;
                af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], f.Numerator }));
                af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], f.Denominator }).Multiple(runtime, Number.New(-1)));
                return(af);
            }

            // 普通のlogの微分
            if (parameters[0] is NaturalLogarithm)
            {
                NaturalLogarithm e = parameters[0] as NaturalLogarithm;
                if (e.Pow.Equals(runtime, Number.New(1)))
                {
                    var prm = parameters[1].ExecuteDiff(runtime, t);
                    if (prm.Equals(runtime, Number.New(0)) ||
                        prm.Equals(runtime, Number.New(1)))
                    {
                        return(new Fraction(
                                   parameters[1], Number.New(1)));
                    }
                    else
                    {
                        MultipleFormula mf = new Expression.MultipleFormula();
                        mf.AddItem(runtime, prm);
                        mf.AddItem(runtime, new Fraction(
                                       parameters[1], Number.New(1)));
                        return(mf);
                    }
                }
            }
            else if (!FuncCalc.Runtime.Func.Differential.IsConstValue(runtime, parameters[0]))
            {
                throw new RuntimeException("底に定数以外が含まれたlogの微分を行うことはできません。");
            }

            INumber param1Diff = parameters[1].ExecuteDiff(runtime, t);

            if (param1Diff.Equals(runtime, Number.New(0)))
            {
                param1Diff = Number.New(1);
            }

            MultipleFormula den = new MultipleFormula();

            den.AddItem(runtime, parameters[1]);
            den.AddItem(runtime, new FuncedINumber(this, new INumber[] { new NaturalLogarithm(), parameters[0] }));
            Fraction res = new Fraction(den, param1Diff);

            return(res);
        }
Beispiel #12
0
        public override INumber Integrate(RuntimeData runtime, string t)
        {
            // このメンバーの名前がtと同じだった場合
            if (this.Text == t)
            {
                if (this.Pow is IConstParameter)
                {
                    // x^a

                    // 1/(a + 1)
                    MultipleFormula mf = new Expression.MultipleFormula();
                    mf.AddItem(runtime, new Fraction(this.Pow.Add(runtime, Number.New(1)), Number.New(1)));

                    // x~(a+1)
                    var cln = this.Clone(); cln.Pow = cln.Pow.Add(runtime, Number.New(1));
                    mf.AddItem(runtime, cln);

                    return(mf);
                }
                else
                {
                    throw new NotImplementedException("べき乗が定数ではない変数の積分は未実装です。");
                }
            }
            else     // このメンバーの名前がtとは違う場合

            {
                var res = runtime.GetData(this.Token);
                if (res is Member)
                {
                    throw new NotImplementedException("話が違う");
                }

                if (res is Variable)
                {
                    if ((res as Variable).Name == this.Text)
                    {
                        // yをxで微分しようとしている場合

                        // tとres(それぞれ違う名前の変数)がそれぞれ関係ないならば成り立つ
                        runtime.AddLogCondition("UnrelationWith", new Variable(t), res);

                        // resを定数として扱って積分する
                        // 参考: (2)~(3)の部分 http://www.geisya.or.jp/~mwm48961/electro/multi_integral3.htm
                        MultipleFormula mf = new Expression.MultipleFormula();
                        mf.AddItem(runtime, res);
                        mf.AddItem(runtime, new Variable(t));
                        return(mf);
                    }
                    else
                    {
                        // yからまた別の変数が出てきちゃった場合
                        return(res.Integrate(runtime, t));
                    }
                }
                else
                {
                    return(res.Integrate(runtime, t));
                }
            }
        }
Beispiel #13
0
        public INumber TryDivide(RuntimeData runtime, INumber val, out bool result)
        {
            // IConstParameterで割ろうとした場合はBase.Divideでも対応できるのでここでは割愛する

            // メンバー(変数)で割ろうとした場合
            Variable v = val as Variable;

            if (v != null || (v = val.Eval(runtime) as Variable) is Variable)
            {
                var me = this.Clone() as MultipleFormula;

                for (int i = 0; i < me.items.Count; i++)
                {
                    var item = me.items[i];
                    if (item is MultipleFormula)
                    {
                        throw new FuncCalcException("MultipleFormulaの中にMultipleFormulaが含まれています。", this);
                    }

                    if (item is Variable)
                    {
                        var res = item.Divide(runtime, v);
                        if (res is Number && (res as Number).Value == 1)
                        {
                            me.items.RemoveAt(i);
                            result = true;
                            return(me);
                        }
                        me.items[i] = res;
                        result      = true;
                        return(me);
                    }
                }
            }
            if (val is MultipleFormula)
            {
                MultipleFormula den  = new Expression.MultipleFormula();
                INumber         num  = this.Clone() as MultipleFormula;
                MultipleFormula f    = val as MultipleFormula;
                bool            flag = false;

                for (int i = 0; i < f.items.Count; i++)
                {
                    var  ex = f.items[i];
                    bool dv_res; INumber res;
                    res = (num as MultipleFormula).TryDivide(runtime, ex, out dv_res);
                    if (dv_res)
                    {
                        flag = true;
                        if (res is MultipleFormula)
                        {
                            num = res as MultipleFormula;
                        }
                        else
                        {
                            num = res;
                            for (int j = i + 1; j < f.items.Count; j++)
                            {
                                den.AddItem(runtime, f.items[j]);
                            }
                            break;
                        }
                    }
                    else
                    {
                        den.AddItem(runtime, ex);
                    }
                }
                if (!flag)
                {
                    result = false; return(null);
                }
                else
                {
                    result = true;

                    // numの条件判定はdenより先に行う
                    if (num is MultipleFormula)
                    {
                        INumber d = den;
                        if (den.items.Count == 0)
                        {
                            return(num);
                        }
                        if (den.items.Count == 1)
                        {
                            d = den.items[0];
                        }

                        if ((num as MultipleFormula).items.Count == 0)
                        {
                            return(new Fraction(d, Number.New(1)));
                        }
                        if ((num as MultipleFormula).items.Count == 1)
                        {
                            return(new Fraction(d, (num as MultipleFormula).items[0]));
                        }
                    }

                    // 最低限の形で返す
                    if (den.items.Count == 0)
                    {
                        return(num);
                    }
                    if (den.items.Count == 1)
                    {
                        var res = new Fraction(den.items[0], num);
                        if (runtime.Setting.DoOptimize)
                        {
                            return(res.Optimise(runtime));
                        }
                        else
                        {
                            return(res);
                        }
                    }

                    return(new Fraction(den, num));
                }
            }

            result = false;
            return(null);
        }