public static Lst <Monomial> Sum(Monomial monomial, Lst <Monomial> monomials, Style style) { if (monomial.IsZero()) { return(monomials); } if (monomials is Cons <Monomial> cons) { if (cons.head.SameFactors(monomial)) { Flow sumCoeff = OpFlow.Op(cons.head.coefficient, "+", monomial.coefficient).Normalize(style); if (sumCoeff.IsNumber(0.0)) { return(cons.tail); } else { return(Monomial.Cons(new Monomial(sumCoeff, monomial.factors, style), cons.tail)); } } else { return(Monomial.Cons(cons.head, Sum(monomial, cons.tail, style))); } } else { return(Monomial.Singleton(monomial)); } }
public Flow RateFunction(ReactionValue reaction) { Flow monomial = NumberFlow.numberFlowOne; if (reaction.rate is MassActionNumericalRate) { double rate = ((MassActionNumericalRate)reaction.rate).Rate(this.temperature); foreach (SpeciesValue sp in sample.stateMap.species) { int spStoichio = reaction.Stoichiometry(sp.symbol, reaction.reactants); monomial = OpFlow.Op("*", monomial, OpFlow.Op("^", new SpeciesFlow(sp.symbol), new NumberFlow(spStoichio))); } monomial = OpFlow.Op("*", new NumberFlow(rate), monomial); } else if (reaction.rate is MassActionFlowRate) { Flow rate = (reaction.rate as MassActionFlowRate).rateFunction; foreach (SpeciesValue sp in sample.stateMap.species) { int spStoichio = reaction.Stoichiometry(sp.symbol, reaction.reactants); monomial = OpFlow.Op("*", monomial, OpFlow.Op("^", new SpeciesFlow(sp.symbol), new NumberFlow(spStoichio))); } monomial = OpFlow.Op("*", rate, monomial); } else if (reaction.rate is GeneralFlowRate) { monomial = (reaction.rate as GeneralFlowRate).rateFunction; } else { throw new Error("RateFunction"); } return(monomial); }
public static Flow ToFlow(Lst <Factor> factors, Lst <Polynomize.Equation> eqs, Style style) { if (factors is Cons <Factor> cons) { return(OpFlow.Op(cons.head.ToFlow(eqs, style), "*", ToFlow(cons.tail, eqs, style))); } else { return(Flow.one); } }
public static Flow ToFlow(Lst <Factor> factors) { if (factors is Cons <Factor> cons) { return(cons.tail is Nil <Factor>?cons.head.ToFlow() : OpFlow.Op(cons.head.ToFlow(), "*", ToFlow(cons.tail))); } else { return(new NumberFlow(1.0)); } }
public static Flow ToFlow(Lst <Monomial> monomials, Lst <Polynomize.Equation> eqs, Style style) { if (monomials is Cons <Monomial> cons) { return(OpFlow.Op(cons.head.ToFlow(eqs, style), "+", ToFlow(cons.tail, eqs, style))); } else { return(Flow.zero); } }
public Flow ToFlow() { if (power == 0) { return(new NumberFlow(1.0)); } if (power == 1) { return(variable); } return(OpFlow.Op(variable, "^", new NumberFlow(power))); }
public static SampleValue MassCompileSample(Symbol outSymbol, SampleValue inSample, Netlist netlist, Style style) { //inSample.Consume(null, 0, null, netlist, style); // this prevents simulating a sample and its massaction version in succession List <ReactionValue> inReactions = inSample.RelevantReactions(netlist, style); CRN inCrn = new CRN(inSample, inReactions); Gui.Log(Environment.NewLine + inCrn.FormatNice(style)); (Lst <Polynomize.ODE> odes, Lst <Polynomize.Equation> eqs) = Polynomize.FromCRN(inCrn); (Lst <Polynomize.PolyODE> polyOdes, Lst <Polynomize.Equation> polyEqs) = Polynomize.PolynomizeODEs(odes, eqs.Reverse(), style); Gui.Log("Polynomize:" + Environment.NewLine + Polynomize.PolyODE.Format(polyOdes, style) + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(polyEqs, style)); (Lst <Polynomize.PolyODE> posOdes, Lst <Polynomize.Equation> posEqs, Dictionary <Symbol, SpeciesFlow> dict, Lst <Positivize.Subst> substs) = Positivize.PositivizeODEs(polyOdes, polyEqs, style); Gui.Log("Positivize:" + Environment.NewLine + Polynomize.PolyODE.Format(posOdes, style) + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(posEqs, style)); Lst <ReactionValue> outReactions = Hungarize.ToReactions(posOdes, style); Gui.Log("Hungarize:" + Environment.NewLine + outReactions.FoldR((r, s) => { return(r.FormatNormal(style) + Environment.NewLine + s); }, "") + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(posEqs, style)); SampleValue outSample = new SampleValue(outSymbol, new StateMap(outSymbol, new List <SpeciesValue> { }, new State(0, lna: inSample.stateMap.state.lna)), new NumberValue(inSample.Volume()), new NumberValue(inSample.Temperature()), produced: true); netlist.Emit(new SampleEntry(outSample)); posOdes.Each(ode => { Flow initFlow = Polynomize.Equation.ToFlow(ode.var, posEqs, style).Normalize(style); double init; if (initFlow is NumberFlow num) { init = num.value; } else { throw new Error("Cannot generate a simulatable sample because initial values contain constants (but the symbolic version has been generated assuming constants are nonnegative)."); } if (init < 0) { throw new Error("Negative initial value of Polynomized ODE for: " + Polynomize.Lookup(ode.var, eqs, style).Format(style) + " = " + init + Environment.NewLine + Polynomize.Equation.Format(eqs, style)); } outSample.stateMap.AddDimensionedSpecies(new SpeciesValue(ode.var.species, -1.0), init, 0.0, "M", outSample.Volume(), style); }); outReactions.Each(reaction => { netlist.Emit(new ReactionEntry(reaction)); }); substs.Each(subst => { ReportEntry report = new ReportEntry(null, OpFlow.Op(subst.plus, "-", subst.minus), null, outSample); outSample.AddReport(report); }); foreach (KeyValuePair <Symbol, SpeciesFlow> keypair in dict) { ReportEntry report = new ReportEntry(null, keypair.Value, null, outSample); outSample.AddReport(report); } ; return(outSample); }
public static Lst <ReactionValue> ToReactions(SpeciesFlow variable, Monomial monomial, Lst <ReactionValue> rest, Style style) { if (monomial.IsZero()) { return(rest); } else { int decide = Polynomial.DecideNonnegative(monomial.coefficient, style); if (decide == 1) // positive monomials { RateValue rate; if (monomial.coefficient is NumberFlow num) { rate = new MassActionNumericalRate(num.value); } else { rate = new MassActionFlowRate(monomial.coefficient); } return(new Cons <ReactionValue>( new ReactionValue( Factor.ToList(monomial.factors), Factor.ToList(Factor.Product(new Factor(variable, 1), monomial.factors)), rate), rest)); } else if (decide == -1) // negative monomials { RateValue rate; if (monomial.coefficient is NumberFlow num) { rate = new MassActionNumericalRate(-num.value); } else { rate = new MassActionFlowRate(OpFlow.Op("-", monomial.coefficient).Normalize(style)); } return(new Cons <ReactionValue>( new ReactionValue( Factor.ToList(monomial.factors), Factor.ToList(Factor.Quotient(monomial.factors, new Factor(variable, 1), style)), rate), rest)); } else { throw new Error("MassActionCompiler: aborted because it cannot determine the sign of this expression: " + monomial.coefficient.Format(style)); } } }
public static Lst <Monomial> Product(Monomial monomial, Lst <Monomial> monomials, Style style) { //Gui.Log("IN Product([" + monomial.Format(style) + "], [" + Format(monomials, style) + "])"); Lst <Monomial> result; if (monomials is Cons <Monomial> cons) { result = Sum(new Monomial(OpFlow.Op(cons.head.coefficient, "*", monomial.coefficient), Factor.Product(cons.head.factors, monomial.factors), style), Product(monomial, cons.tail, style), style); } else { result = Monomial.nil; } //Gui.Log("OUT Product([" + monomial.Format(style) + "], [" + Format(monomials, style) + "]) = [" + Format(result, style) + "]"); return(result); }
public (SpeciesValue[] vars, Flow[] flows) MeanFlow() { SpeciesValue[] vars = new SpeciesValue[sample.Count()]; Flow[] flows = new Flow[sample.Count()]; for (int speciesIx = 0; speciesIx < flows.Length; speciesIx++) { vars[speciesIx] = sample.stateMap.species[speciesIx]; Flow polynomial = NumberFlow.numberFlowZero; foreach (ReactionValue reaction in this.reactions) { int netStoichiometry = reaction.NetStoichiometry(vars[speciesIx].symbol); Flow monomial = (netStoichiometry == 0) ? NumberFlow.numberFlowZero : OpFlow.Op("*", new NumberFlow(netStoichiometry), RateFunction(reaction)); polynomial = OpFlow.Op("+", polynomial, monomial); } flows[speciesIx] = polynomial; } return(vars, flows); }
public Flow[,] Jacobian(Style style) { int speciesNo = sample.Count(); Flow[,] jacobian = new Flow[speciesNo, speciesNo]; for (int speciesI = 0; speciesI < speciesNo; speciesI++) { SpeciesValue variableI = sample.stateMap.species[speciesI]; for (int speciesK = 0; speciesK < speciesNo; speciesK++) { SpeciesValue variableK = sample.stateMap.species[speciesK]; Flow polynomial = NumberFlow.numberFlowZero; foreach (ReactionValue reaction in this.reactions) { int netStoichiometryI = reaction.NetStoichiometry(variableI.symbol); if (reaction.rate is MassActionNumericalRate) { int stoichiometryK = reaction.Stoichiometry(variableK.symbol, reaction.reactants); Flow monomial = (netStoichiometryI == 0 || stoichiometryK == 0) ? NumberFlow.numberFlowZero : OpFlow.Op("*", OpFlow.Op("*", new NumberFlow(netStoichiometryI), new NumberFlow(stoichiometryK)), OpFlow.Op("/", RateFunction(reaction), new SpeciesFlow(variableK.symbol))); polynomial = OpFlow.Op("+", polynomial, monomial); } else if (reaction.rate is GeneralFlowRate || reaction.rate is MassActionFlowRate) { Flow monomial = (netStoichiometryI == 0) ? NumberFlow.numberFlowZero : OpFlow.Op("*", new NumberFlow(netStoichiometryI), RateFunction(reaction).Differentiate(variableK.symbol, style)); polynomial = OpFlow.Op("+", polynomial, monomial); } else { throw new Error("Jacobian"); } } // Gui.Log("d " + variableI.Format(style) + "/d" + variableK.Format(style) + " = " + polynomial.Format(style)); jacobian[speciesI, speciesK] = polynomial; } } return(jacobian); }
public Flow[,] Drift() { int speciesNo = sample.Count(); int reactionsNo = reactions.Count(); Flow[,] drift = new Flow[speciesNo, speciesNo]; for (int speciesI = 0; speciesI < speciesNo; speciesI++) // rows { for (int speciesJ = 0; speciesJ < speciesNo; speciesJ++) // columns { drift[speciesI, speciesJ] = NumberFlow.numberFlowZero; for (int reactionR = 0; reactionR < reactionsNo; reactionR++) // reactions { drift[speciesI, speciesJ] = OpFlow.Op("+", drift[speciesI, speciesJ], OpFlow.Op("*", new NumberFlow(stoichio[speciesI, reactionR] * stoichio[speciesJ, reactionR]), RateFunction(reactions[reactionR]))); } } } return(drift); }
public (SpeciesFlow[, ], Flow[, ]) CovarFlow(Style style) { int speciesNo = sample.Count(); SpeciesFlow[,] covar = new SpeciesFlow[speciesNo, speciesNo]; // fill it with fresh covariance variables for (int speciesI = 0; speciesI < speciesNo; speciesI++) // rows { SpeciesValue variableI = sample.stateMap.species[speciesI]; for (int speciesJ = 0; speciesJ < speciesNo; speciesJ++) // columns { SpeciesValue variableJ = sample.stateMap.species[speciesJ]; if (style.exportTarget == ExportTarget.WolframNotebook) { covar[speciesI, speciesJ] = new SpeciesFlow(new Symbol(variableI.Format(style) + "_" + variableJ.Format(style))); } else { covar[speciesI, speciesJ] = (speciesI == speciesJ) ? new SpeciesFlow(new Symbol("var(" + variableI.Format(style) + ")")) : new SpeciesFlow(new Symbol("cov(" + variableI.Format(style) + "," + variableJ.Format(style) + ")")); } } } Flow[,] covarFlow = new Flow[speciesNo, speciesNo]; Flow[,] jacobian = Jacobian(style); Flow[,] drift = Drift(); for (int speciesI = 0; speciesI < speciesNo; speciesI++) // rows { for (int speciesJ = 0; speciesJ < speciesNo; speciesJ++) // columns { covarFlow[speciesI, speciesJ] = NumberFlow.numberFlowZero; for (int speciesK = 0; speciesK < speciesNo; speciesK++) // dot product index { covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], OpFlow.Op("*", jacobian[speciesI, speciesK], covar[speciesK, speciesJ])); covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], OpFlow.Op("*", jacobian[speciesJ, speciesK], covar[speciesI, speciesK])); // jacobian transposed } covarFlow[speciesI, speciesJ] = OpFlow.Op("+", covarFlow[speciesI, speciesJ], drift[speciesI, speciesJ]); } } return(covar, covarFlow); }
public Flow ToFlow(Lst <Equation> eqs, Style style) { // this is a bit redundant because eventually we call Flow.Normalize, but Normalize does not handle pos, etc. Flow result; if (op == "id") { result = Monomial.ToFlow(args[0], eqs, style); } else if (op == "time") { result = Flow.zero; } else if (op == "poly 1/[]") { Flow arg0 = Monomial.ToFlow(args[0], eqs, style); if (arg0 is NumberFlow num) { result = new NumberFlow(1 / num.value); } else { result = OpFlow.Op(Flow.one, "/", arg0); } } else if (op == "poly []^(1/[])") { Flow arg0 = Monomial.ToFlow(args[0], eqs, style); Flow arg1 = Monomial.ToFlow(args[1], eqs, style); if (arg0 is NumberFlow num0 && arg1 is NumberFlow num1) { result = new NumberFlow(Math.Pow(num0.value, 1 / num1.value)); } else { result = OpFlow.Op(arg0, "^", OpFlow.Op(Flow.one, "/", arg1)); } }
// ===== Separate ===== public static (Lst <Monomial> positive, Lst <Monomial> negative) Separate(Lst <Monomial> monomials, Style style) { if (monomials is Cons <Monomial> cons) { (Lst <Monomial> positive, Lst <Monomial> negative) = Separate(cons.tail, style); int decide = Polynomial.DecideNonnegative(cons.head.coefficient, style); if (decide == 1) { return(Monomial.Cons(cons.head, positive), negative); } else if (decide == -1) { return(positive, Monomial.Cons(new Monomial(OpFlow.Op("-", cons.head.coefficient), cons.head.factors, style), negative)); } else { throw new Error("MassActionCompiler: aborted because it cannot determine the sign of this expression: " + cons.head.coefficient.Format(style)); } } else { return(Monomial.nil, Monomial.nil); } }
public Flow ToFlow(Lst <Polynomize.Equation> eqs, Style style) { return(OpFlow.Op(Polynomize.Lookup(this.variable, eqs, style).ToFlow(eqs, style), "^", new NumberFlow(this.power))); }
public Monomial Product(Flow coefficient, Style style) { return(new Monomial(OpFlow.Op(this.coefficient, "*", coefficient), this.factors, style)); }
public Monomial Product(Monomial other, Style style) { return(new Monomial(OpFlow.Op(this.coefficient, "*", other.coefficient), Factor.Product(this.factors, other.factors), style)); }
public Flow ToFlow(Lst <Polynomize.Equation> eqs, Style style) { return(OpFlow.Op(this.coefficient, "*", Factor.ToFlow(this.factors, eqs, style))); }
public Monomial Power(int power, Style style) { return(new Monomial(OpFlow.Op(this.coefficient, "^", new NumberFlow(power)), Factor.Power(this.factors, power), style)); }