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); } }
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); } }
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); }
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(); }
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("分数の積分はあまり対応してない"); }
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); }
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); }
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); }
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); } } }
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(); }
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); }
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)); } } }
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); }