コード例 #1
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 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));
     }
 }
コード例 #2
0
        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);
        }
コード例 #3
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 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);
     }
 }
コード例 #4
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 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));
     }
 }
コード例 #5
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 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);
     }
 }
コード例 #6
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 public Flow ToFlow()
 {
     if (power == 0)
     {
         return(new NumberFlow(1.0));
     }
     if (power == 1)
     {
         return(variable);
     }
     return(OpFlow.Op(variable, "^", new NumberFlow(power)));
 }
コード例 #7
0
        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);
        }
コード例 #8
0
 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));
         }
     }
 }
コード例 #9
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
        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);
        }
コード例 #10
0
 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);
 }
コード例 #11
0
        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);
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        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);
        }
コード例 #14
0
            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));
                    }
                }
コード例 #15
0
        // ===== 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);
            }
        }
コード例 #16
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 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)));
 }
コード例 #17
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 public Monomial Product(Flow coefficient, Style style)
 {
     return(new Monomial(OpFlow.Op(this.coefficient, "*", coefficient), this.factors, style));
 }
コード例 #18
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 public Monomial Product(Monomial other, Style style)
 {
     return(new Monomial(OpFlow.Op(this.coefficient, "*", other.coefficient), Factor.Product(this.factors, other.factors), style));
 }
コード例 #19
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 public Flow ToFlow(Lst <Polynomize.Equation> eqs, Style style)
 {
     return(OpFlow.Op(this.coefficient, "*", Factor.ToFlow(this.factors, eqs, style)));
 }
コード例 #20
0
ファイル: Polynomial.cs プロジェクト: luca-cardelli/KaemikaXM
 public Monomial Power(int power, Style style)
 {
     return(new Monomial(OpFlow.Op(this.coefficient, "^", new NumberFlow(power)), Factor.Power(this.factors, power), style));
 }