コード例 #1
0
ファイル: Radical.cs プロジェクト: erjicles/Radicals
        public int CompareTo(Radical other)
        {
            var result = (Sign * Rational.Abs(RaisedToIndexPower))
                         .CompareTo(other.Sign * Rational.Abs(other.RaisedToIndexPower));

            return(result);
        }
コード例 #2
0
ファイル: RationalTest.cs プロジェクト: gisdevelope/aegis
        public void RationalAbsTest()
        {
            Rational.Abs(new Rational(1, 2)).ShouldBe(new Rational(1, 2));
            Rational.Abs(new Rational(-1, 2)).ShouldBe(new Rational(1, 2));

            Rational.Abs(Rational.NegativeInfinity).ShouldBe(Rational.PositiveInfinity);
            Rational.Abs(Rational.PositiveInfinity).ShouldBe(Rational.PositiveInfinity);
            Rational.Abs(Rational.NaN).ShouldBe(Rational.NaN);
        }
コード例 #3
0
        public void AbsoluteNaN()
        {
            // arrange
            var input = Rational.NaN;

            // action
            var result = Rational.Abs(input);

            // assert
            Assert.Equal(Rational.NaN, result);
        }
コード例 #4
0
        public void Absolute5()
        {
            // arrange
            var p = new Rational(0, 10);

            // action
            var q = -p;

            // assert
            Assert.Equal(p, Rational.Abs(q));
        }
コード例 #5
0
        public void Absolute4()
        {
            // arrange
            var p = new Rational(-1, -2);

            // action
            var q = -p;

            // assert
            Assert.Equal((Rational)1 / 2, Rational.Abs(q));
        }
コード例 #6
0
        private Rational StarDiscrepency(List <Rational> s)
        {
            s.Sort();
            Rational d = 0;

            for (int i = 1; i < s.Count; i++)
            {
                d = Rational.Max(d, Rational.Abs(i / (Rational)s.Count - s[i]));
            }

            return(d);
        }
コード例 #7
0
        public bool IsXeqYRow(int rowIndex)
        {
            var row = matrix[rowIndex];

            if (row.NonDefaultElementsCount != 2)
            {
                return(false);
            }

            var k1    = default(Rational);
            var k2    = default(Rational);
            var k1Set = false;
            var k2Set = false;

            foreach (var pair in row.GetElements())
            {
                if (pair.Key == row.Length - 1)
                {
                    // To make the code more robust
                    if (pair.Value != 0)
                    {
                        return(false);
                    }
                }

                if (pair.Value.IsMinValue || Rational.Abs(pair.Value) != 1)
                {
                    return(false);
                }
                if (!k1Set)
                {
                    k1    = pair.Value;
                    k1Set = true;
                    continue;
                }

                if (!k2Set)
                {
                    k2    = pair.Value;
                    k2Set = true;
                    break;
                }
            }

            return((k1 * k2) == -1);
        }
コード例 #8
0
 public ComplexPart Abs()
 {
     return(ComplexPart.Create(_value.Abs()));
 }
コード例 #9
0
ファイル: BigMath.cs プロジェクト: tupunco/deveel-math
        public static BigDecimal PowRound(BigDecimal x, Rational q)
        {
            /** Special cases: x^1=x and x^0 = 1
                */
            if (q.CompareTo(BigInteger.One) == 0)
                return x;
            if (q.Sign == 0)
                return BigDecimal.One;
            if (q.IsInteger) {
                /* We are sure that the denominator is positive here, because normalize() has been
                        * called during constrution etc.
                        */
                return PowRound(x, q.Numerator);
            }
            /* Refuse to operate on the general negative basis. The integer q have already been handled above.
                        */
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("Cannot power negative " + x);
            if (q.IsIntegerFraction) {
                /* Newton method with first estimate in double precision.
                                * The disadvantage of this first line here is that the result must fit in the
                                * standard range of double precision numbers exponents.
                                */
                double estim = System.Math.Pow(x.ToDouble(), q.ToDouble());
                var res = new BigDecimal(estim);

                /* The error in x^q is q*x^(q-1)*Delta(x).
                                * The relative error is q*Delta(x)/x, q times the relative error of x.
                                */
                var reserr = new BigDecimal(0.5*q.Abs().ToDouble()
                                            *x.Ulp().Divide(x.Abs(), MathContext.Decimal64).ToDouble());

                /* The main point in branching the cases above is that this conversion
                                * will succeed for numerator and denominator of q.
                                */
                int qa = q.Numerator.ToInt32();
                int qb = q.Denominator.ToInt32();

                /* Newton iterations. */
                BigDecimal xpowa = PowRound(x, qa);
                for (;;) {
                    /* numerator and denominator of the Newton term.  The major
                                        * disadvantage of this implementation is that the updates of the powers
                                        * of the new estimate are done in full precision calling BigDecimal.pow(),
                                        * which becomes slow if the denominator of q is large.
                                        */
                    BigDecimal nu = res.Pow(qb).Subtract(xpowa);
                    BigDecimal de = MultiplyRound(res.Pow(qb - 1), q.Denominator);

                    /* estimated correction */
                    BigDecimal eps = nu.Divide(de, MathContext.Decimal64);

                    BigDecimal err = res.Multiply(reserr, MathContext.Decimal64);
                    int precDiv = 2 + ErrorToPrecision(eps, err);
                    if (precDiv <= 0) {
                        /* The case when the precision is already reached and any precision
                                                * will do. */
                        eps = nu.Divide(de, MathContext.Decimal32);
                    } else {
                        eps = nu.Divide(de, new MathContext(precDiv));
                    }

                    res = SubtractRound(res, eps);
                    /* reached final precision if the relative error fell below reserr,
                                        * |eps/res| < reserr
                                        */
                    if (eps.Divide(res, MathContext.Decimal64).Abs().CompareTo(reserr) < 0) {
                        /* delete the bits of extra precision kept in this
                                                * working copy.
                                                */
                        return res.Round(new MathContext(ErrorToPrecision(reserr.ToDouble())));
                    }
                }
            }
            /* The error in x^q is q*x^(q-1)*Delta(x) + Delta(q)*x^q*log(x).
                                * The relative error is q/x*Delta(x) + Delta(q)*log(x). Convert q to a floating point
                                * number such that its relative error becomes negligible: Delta(q)/q << Delta(x)/x/log(x) .
                                */
            int precq = 3 + ErrorToPrecision((x.Ulp().Divide(x, MathContext.Decimal64)).ToDouble()
                                             /System.Math.Log(x.ToDouble()));

            /* Perform the actual calculation as exponentiation of two floating point numbers.
                                */
            return Pow(x, q.ToBigDecimal(new MathContext(precq)));
        }
コード例 #10
0
        /// <summary>
        /// Итерация метода ветвей и границ
        /// </summary>
        /// <param name="additionalRestrictions">Дополнительные ограничения, вводимые при ветвлении</param>
        private void Iterate(List <DataRow> additionalRestrictions)
        {
            DataTable dt = (dataGridView1.DataSource as DataTable).Copy();

            dt.Columns.RemoveAt(0);
            Dictionary <int, int> rSign   = new Dictionary <int, int>();
            StringBuilder         @string = new StringBuilder();

            foreach (var r in additionalRestrictions)
            {
                var x = dt.NewRow();
                x.ItemArray = r.ItemArray.Clone() as object[];
                for (int j = 0; j < r.ItemArray.Length; j++)
                {
                    if (!(x[j] is DBNull))
                    {
                        int sgn = Math.Sign(((Rational)x[j]).ToDouble());
                        if (sgn != 0 && j < x.ItemArray.Length - 1)
                        {
                            rSign.Add(dt.Rows.Count, sgn);
                            @string.AppendFormat(" x{0}{1}{2}", j + 1,
                                                 sgn > 0 ? '≤' : '≥',
                                                 Rational.Abs((Rational)x[x.ItemArray.Length - 1]));
                        }
                        x[j] = Rational.Abs((Rational)x[j]);
                    }
                }
                dt.Rows.Add(x);
            }

            int xcnt = dt.Columns.Count - 1;
            int scnt = dt.Rows.Count - 1;

            Rational[,] matrix = new Rational[xcnt + scnt + 2, scnt + 2];
            for (int j = 0; j < matrix.GetLength(0); j++) //Столбцы
            {
                matrix[j, 0] = j;
            }
            for (int i = 1; i < matrix.GetLength(1); i++) //Строки
            {
                matrix[0, i] = i == 1 ? 0 : i + xcnt - 1;
                for (int j = 1; j < matrix.GetLength(0); j++) //Столбцы
                {
                    if (j < dt.Columns.Count)                 //Заполним для всех Х
                    {
                        object txx = dt.Rows[i - 1][j - 1];
                        matrix[j, i] = txx is DBNull ? 0 : (Rational)txx;
                    }
                    else if (matrix[0, i] == matrix[j, 0]) //Для всех S единички по диагонали
                    {
                        matrix[j, i] = rSign.ContainsKey(i) ? rSign[i] : 1;
                    }
                    else if (j == matrix.GetLength(0) - 1)
                    {
                        object txx = dt.Rows[i - 1][dt.Columns.Count - 1];
                        matrix[j, i] = txx is DBNull ? 0 : (Rational)txx;
                    }
                    else
                    {
                        matrix[j, i] = 0;
                    }
                }
            }
            //PrintMatrix(matrix);
            textBox1.AppendText(string.Format("\r\nРешение{0}:{1}", @string.ToString(), Environment.NewLine));
            Simplex(matrix, checkBox1.Checked);
            Rational[] result = new Rational[xcnt];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = 0;
            }
            for (int i = 2; i < matrix.GetLength(1); i++)
            {
                if (matrix[0, i] <= xcnt)
                {
                    result[matrix[0, i].Numerator - 1] = matrix[matrix.GetLength(0) - 1, i];
                }
            }
            int rIdx = -1;

            for (int i = 0; i < result.Length; i++)
            {
                textBox1.AppendText(string.Format("x{0}={1}{2}", i + 1, result[i].ToMixedString(),
                                                  i != result.Length - 1 ? "; " : "  "));
                if (rIdx < 0 && result[i].Denominator > 1) //Дробный корень
                {
                    rIdx = i;
                }
            }
            textBox1.AppendText(string.Format("z(max)= {2}   {0} решение{1}", rIdx < 0 && matrix[matrix.GetLength(0) - 1, 1].Denominator == 1
                ? "Целое" : "Дробное", Environment.NewLine,
                                              matrix[matrix.GetLength(0) - 1, 1].ToMixedString()));
            if (rIdx < 0)
            {
                if (matrix[matrix.GetLength(0) - 1, 1].Denominator != 1)
                {
                    textBox1.AppendText("Нет решения" + Environment.NewLine);
                    return;
                }
                for (int i = 2; i < dataGridView1.RowCount; i++)
                {
                    Rational check = 0;
                    for (int j = 1; j < dataGridView1.Columns.Count - 1; j++)
                    {
                        check += (result[j - 1] * (Rational)(dataGridView1[j, i].Value is DBNull ?
                                                             Rational.Zero : dataGridView1[j, i].Value));
                    }
                    if (check > (Rational)dataGridView1[dataGridView1.ColumnCount - 1, i].Value)
                    {
                        textBox1.AppendText("Ограничения не выполнены" + Environment.NewLine);
                        return;
                    }
                }
                if (checkBox1.Checked == false)
                {
                    if (matrix[matrix.GetLength(0) - 1, 1] > record[record.Length - 1])
                    {
                        for (int i = 0; i < record.Length - 1; i++)
                        {
                            record[i] = result[i];
                        }
                        record[record.Length - 1] = matrix[matrix.GetLength(0) - 1, 1];
                    }
                }
                else
                {
                    if (matrix[matrix.GetLength(0) - 1, 1] < record[record.Length - 1] || record[record.Length - 1] == 0)
                    {
                        for (int i = 0; i < record.Length - 1; i++)
                        {
                            record[i] = result[i];
                        }
                        record[record.Length - 1] = matrix[matrix.GetLength(0) - 1, 1];
                    }
                }
            }
            if (rIdx >= 0 && xcnt > additionalRestrictions.Count)
            {
                foreach (var a in additionalRestrictions)
                {
                    if (!(a[rIdx] is DBNull) && Rational.Abs((Rational)a[rIdx]) == 1)
                    {
                        return; //Уже есть ограничение для этого Х
                    }
                }
                additionalRestrictions.Add(dt.NewRow());
                additionalRestrictions[additionalRestrictions.Count - 1][rIdx] = Rational.One;
                additionalRestrictions[additionalRestrictions.Count - 1][dt.Columns.Count - 1] =
                    (Rational)Math.Floor(result[rIdx].ToDouble());
                Iterate(additionalRestrictions);
                additionalRestrictions[additionalRestrictions.Count - 1][rIdx] = -Rational.One;
                additionalRestrictions[additionalRestrictions.Count - 1][dt.Columns.Count - 1] =
                    -(Rational)Math.Ceiling(result[rIdx].ToDouble());
                Iterate(additionalRestrictions);
                additionalRestrictions.RemoveAt(additionalRestrictions.Count - 1);
            }
        }
コード例 #11
0
        public void InitializeGrid()
        {
            grid = new Dictionary <Tuple <Rational, Rational>, CBNode>();
            unprocessedNodeList = new List <CBNode>();
            // Create nodes
            for (Rational m1 = -j1; m1 <= j1; m1 += 1)
            {
                for (Rational m2 = -j2; m2 <= j2; m2 += 1)
                {
                    if (Rational.Abs(m1 + m2) <= j &&
                        Rational.Abs(m1) <= j1 &&
                        Rational.Abs(m2) <= j2)
                    {
                        var node = new CBNode(m1, m2);
                        if (grid.ContainsKey(node.GridCoordinate))
                        {
                            throw new Exception("Node already created: m1: " + m1.ToString() + "; m2: " + m2.ToString());
                        }
                        grid.Add(node.GridCoordinate, node);
                        unprocessedNodeList.Add(node);
                    }
                }
            }
            // Populate neighbors
            for (Rational m1 = -j1; m1 <= j1; m1 += 1)
            {
                for (Rational m2 = -j2; m2 <= j2; m2 += 1)
                {
                    var coord = new Tuple <Rational, Rational>(m1, m2);
                    if (grid.ContainsKey(coord))
                    {
                        var node = grid[coord];

                        var c_m1_00 = new Tuple <Rational, Rational>(m1 - 1, m2);
                        var c_00_m1 = new Tuple <Rational, Rational>(m1, m2 - 1);
                        var c_00_p1 = new Tuple <Rational, Rational>(m1, m2 + 1);
                        var c_p1_00 = new Tuple <Rational, Rational>(m1 + 1, m2);
                        var c_p1_m1 = new Tuple <Rational, Rational>(m1 + 1, m2 - 1);
                        var c_p1_p1 = new Tuple <Rational, Rational>(m1 + 1, m2 + 1);
                        var c_m1_m1 = new Tuple <Rational, Rational>(m1 - 1, m2 - 1);
                        var c_m1_p1 = new Tuple <Rational, Rational>(m1 - 1, m2 + 1);

                        if (grid.ContainsKey(c_m1_00))
                        {
                            node.n_m1_00 = grid[c_m1_00];
                        }
                        if (grid.ContainsKey(c_00_m1))
                        {
                            node.n_00_m1 = grid[c_00_m1];
                        }
                        if (grid.ContainsKey(c_00_p1))
                        {
                            node.n_00_p1 = grid[c_00_p1];
                        }
                        if (grid.ContainsKey(c_p1_00))
                        {
                            node.n_p1_00 = grid[c_p1_00];
                        }
                        if (grid.ContainsKey(c_p1_m1))
                        {
                            node.n_p1_m1 = grid[c_p1_m1];
                        }
                        if (grid.ContainsKey(c_p1_p1))
                        {
                            node.n_p1_p1 = grid[c_p1_p1];
                        }
                        if (grid.ContainsKey(c_m1_m1))
                        {
                            node.n_m1_m1 = grid[c_m1_m1];
                        }
                        if (grid.ContainsKey(c_m1_p1))
                        {
                            node.n_m1_p1 = grid[c_m1_p1];
                        }
                    }
                }
            }
            // Set the seed node
            // Looking for a node that only has one non-null neighbor as part of a triangle
            // Start by trying the maximal m
            for (Rational m1 = j1; m1 >= -j1; m1 -= 1)
            {
                for (Rational m2 = j2; m2 >= -j2; m2 -= 1)
                {
                    var coord = new Tuple <Rational, Rational>(m1, m2);
                    if (grid.ContainsKey(coord))
                    {
                        var node = grid[coord];
                        if ((node.n_m1_00 != null &&
                             node.n_00_m1 == null) ||
                            (node.n_m1_00 == null &&
                             node.n_00_m1 != null) ||
                            (node.n_p1_00 != null &&
                             node.n_00_p1 == null) ||
                            (node.n_p1_00 == null &&
                             node.n_00_p1 != null) ||
                            (node.n_p1_00 != null &&
                             node.n_p1_m1 == null) ||
                            (node.n_p1_00 == null &&
                             node.n_p1_m1 != null) ||
                            (node.n_00_p1 != null &&
                             node.n_m1_p1 == null) ||
                            (node.n_00_p1 == null &&
                             node.n_m1_p1 != null) ||
                            (node.n_00_m1 != null &&
                             node.n_p1_m1 == null) ||
                            (node.n_00_m1 == null &&
                             node.n_p1_m1 != null) ||
                            (node.n_m1_00 != null &&
                             node.n_m1_p1 == null) ||
                            (node.n_m1_00 == null &&
                             node.n_m1_p1 != null))
                        {
                            node.rawCoefficient = 1;
                            node.IsSet          = true;
                            node.IsSeedNode     = true;
                            seedNode            = node;
                            break;
                        }
                    }
                }
                if (seedNode != null)
                {
                    break;
                }
            }
        }
コード例 #12
0
ファイル: Radical.cs プロジェクト: erjicles/Radicals
        /// <summary>
        /// S = simplest form, R = all under the radical
        /// </summary>
        /// <param name="format"></param>
        /// <param name="formatProvider"></param>
        /// <returns></returns>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (Coefficient.IsZero)
            {
                return("0");
            }
            if (Radicand.IsZero)
            {
                return("0");
            }
            if (format == null)
            {
                format = "S";
            }

            if (IsZero)
            {
                return(0.ToString());
            }
            if (IsOne)
            {
                return(1.ToString());
            }

            var result = new StringBuilder();

            // Simplest form
            if ("S".Equals(format))
            {
                // Handle coefficient
                // TODO: Pass format through
                if (Coefficient.Denominator.IsOne)
                {
                    if (!Coefficient.Numerator.IsOne ||
                        (Coefficient.Numerator.IsOne && Radicand.IsOne))
                    {
                        if (Sign < 0)
                        {
                            result.Append("(" + Coefficient.Numerator.ToString() + ")");
                        }
                        else
                        {
                            result.Append(Coefficient.Numerator.ToString());
                        }
                    }
                }
                else
                {
                    result.Append("(" + Coefficient.ToString() + ")");
                }

                // Handle radicand
                if (Index > 1 && Radicand > 1)
                {
                    if (result.Length > 0)
                    {
                        result.Append("*");
                    }
                    if (Index == 2)
                    {
                        result.Append("Sqrt");
                    }
                    else
                    {
                        result.Append("Nth-Root[index:" + Index.ToString() + "]");
                    }
                    result.Append("(" + Radicand.ToString() + ")");
                }
            }
            else if ("R".Equals(format))
            {
                if (Index == 1)
                {
                    if (Coefficient.Denominator.IsOne)
                    {
                        if (!Coefficient.Numerator.IsOne ||
                            (Coefficient.Numerator.IsOne && Radicand.IsOne))
                        {
                            result.Append(Coefficient.Numerator.ToString());
                        }
                    }
                    else
                    {
                        result.Append("(" + Coefficient.ToString() + ")");
                    }
                }
                else
                {
                    if (Sign < 0)
                    {
                        result.Append("-");
                    }
                    // Get the rational for all under the radical
                    if (Index == 2)
                    {
                        result.Append("Sqrt");
                    }
                    else
                    {
                        result.Append("Nth-Root[index:" + Index.ToString() + "]");
                    }
                    var radicand = RaisedToIndexPower;
                    if (radicand.Denominator.IsOne)
                    {
                        result.Append("(" + BigInteger.Abs(radicand.Numerator).ToString() + ")");
                    }
                    else
                    {
                        result.Append("(" + Rational.Abs(radicand.CanonicalForm).ToString() + ")");
                    }
                }
            }

            return(result.ToString());
        }
コード例 #13
0
        // j1
        // j2
        // m1
        // m2
        // j
        // m
        // m1 + m2 = m +- 1
        // abs(m1) <= j1
        // abs(m2) <= j2
        // -j <= m1 + m2 <= j
        // sqrt[(j -+ m)(j +- m + 1)]<m1, m2; j, m +- 1>
        //      = sqrt[(j1 -+ m1 + 1)(j1 +- m1)]<m1 -+ 1, m2; j, m>
        //      + sqrt[(j2 -+ m2 + 1)(j2 +- m2)]<m1, m2 -+ 1; j, m>

        // Fix j1, j2, j

        // J+:
        // sqrt[(j - m)(j + m + 1)]<m1, m2; j, m + 1>
        //      = sqrt[(j1 - m1 + 1)(j1 + m1)]<m1 - 1, m2; j, m>
        //      + sqrt[(j2 - m2 + 1)(j2 + m2)]<m1, m2 - 1; j, m>
        //  ; m1 + m2 = m + 1

        // J-:
        // sqrt[(j + m)(j - m + 1)]<m1, m2; j, m - 1>
        //      = sqrt[(j1 + m1 + 1)(j1 - m1)]<m1 + 1, m2; j, m>
        //      + sqrt[(j2 + m2 + 1)(j2 - m2)]<m1, m2 + 1; j, m>
        //  ; m1 + m2 = m - 1

        // J+:
        // <m1, m2; j, m + 1> = {sqrt[(j1 - m1 + 1)(j1 + m1)]<m1 - 1, m2; j, m> + sqrt[(j2 - m2 + 1)(j2 + m2)]<m1, m2 - 1; j, m>} / sqrt[(j - m)(j + m + 1)]
        // <m1 - 1, m2; j, m> = {sqrt[(j - m)(j + m + 1)]<m1, m2; j, m + 1> - sqrt[(j2 - m2 + 1)(j2 + m2)]<m1, m2 - 1; j, m>} / sqrt[(j1 - m1 + 1)(j1 + m1)]
        // <m1, m2 - 1; j, m> = {sqrt[(j - m)(j + m + 1)]<m1, m2; j, m + 1> - sqrt[(j1 - m1 + 1)(j1 + m1)]<m1 - 1, m2; j, m>} / sqrt[(j2 - m2 + 1)(j2 + m2)]

        // J-:
        // <m1, m2; j, m - 1> = {sqrt[(j1 + m1 + 1)(j1 - m1)]<m1 + 1, m2; j, m> + sqrt[(j2 + m2 + 1)(j2 - m2)]<m1, m2 + 1; j, m>} / sqrt[(j + m)(j - m + 1)]
        // <m1 + 1, m2; j, m> = {sqrt[(j + m)(j - m + 1)]<m1, m2; j, m - 1> - sqrt[(j2 + m2 + 1)(j2 - m2)]<m1, m2 + 1; j, m>} / sqrt[(j1 + m1 + 1)(j1 - m1)]
        // <m1, m2 + 1; j, m> = {sqrt[(j + m)(j - m + 1)]<m1, m2; j, m - 1> - sqrt[(j1 + m1 + 1)(j1 - m1)]<m1 + 1, m2; j, m>} / sqrt[(j2 + m2 + 1)(j2 - m2)]

        static void Main(string[] args)
        {
            bool continueProgram = true;

            while (continueProgram)
            {
                bool isValidInput = false;

                Rational j1 = 0;
                Rational j2 = 0;
                Rational j  = 0;
                Rational m1 = 0;
                Rational m2 = 0;
                Rational m  = 0;

                while (!isValidInput)
                {
                    Console.Write("j1: ");
                    j1 = Rational.Parse(Console.ReadLine());
                    Console.Write("j2: ");
                    j2 = Rational.Parse(Console.ReadLine());
                    Console.Write("m: ");
                    m = Rational.Parse(Console.ReadLine());
                    Console.Write("j: ");
                    j = Rational.Parse(Console.ReadLine());
                    Console.Write("m1: ");
                    m1 = Rational.Parse(Console.ReadLine());
                    Console.Write("m2: ");
                    m2 = Rational.Parse(Console.ReadLine());

                    if (Rational.Abs(j1 - j2) > j ||
                        j > j1 + j2)
                    {
                        Console.WriteLine("Parameters violate |j1 - j2| <= j <= j1 + j2");
                    }
                    else if (m1 + m2 != m)
                    {
                        Console.WriteLine("Parameters violate m1 + m2 = m");
                    }
                    else if (Rational.Abs(m1) > j1)
                    {
                        Console.WriteLine("Parameters violate |m1| <= j1");
                    }
                    else if (Rational.Abs(m2) > j2)
                    {
                        Console.WriteLine("Parameters violate |m2| <= j2");
                    }
                    else if (Rational.Abs(m1 + m2) > j)
                    {
                        Console.WriteLine("Parameters violate -j <= m1 + m2 <= j");
                    }
                    else if (j1.Denominator != m1.Denominator)
                    {
                        Console.WriteLine("Parameters violate j1 and m1 must both simultaneously be integers or half integers");
                    }
                    else if (j2.Denominator != m2.Denominator)
                    {
                        Console.WriteLine("Parameters violate j2 and m2 must both simultaneously be integers or half integers");
                    }
                    else
                    {
                        isValidInput = true;
                    }
                }

                // Run the scenario
                CBScenario scenario = new CBScenario(j1: j1, j2: j2, j: j, m: m);
                scenario.InitializeGrid();
                if (scenario.seedNode == null)
                {
                    Console.Write("-----SEED NODE NOT SET-----");
                }
                scenario.CalculateRawCoefficients();
                scenario.NormalizeCoefficients();
                //Utilities.DrawGrid(scenario);

                var node = scenario.grid[new Tuple <Rational, Rational>(m1, m2)];
                Console.WriteLine("Requested coefficient: " + node.ToString());

                Console.WriteLine("Run another scenario? (y/n)");
                var input = Console.ReadLine();
                if ("y".Equals(input, StringComparison.InvariantCultureIgnoreCase) ||
                    "yes".Equals(input, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                else
                {
                    continueProgram = false;
                }
            }
        }