public void testDecrement()
 {
     MixedRadixNumber mrn = new MixedRadixNumber(5, new int[] { 3, 2 });
     int i = 0;
     while (mrn.decrement())
     {
         i++;
     }
     Assert.AreEqual(i, mrn.getMaxAllowedValue());
 }
 public void testCurrentNumberalValue()
 {
     MixedRadixNumber mrn;
     //
     mrn = new MixedRadixNumber(0, new int[] { 3, 3, 2, 2 });
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(35, new int[] { 3, 3, 2, 2 });
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(1, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(1, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(25, new int[] { 3, 3, 2, 2 });
     Assert.AreEqual(1, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(1, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(17, new int[] { 3, 3, 2, 2 });
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(1, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(8, new int[] { 3, 3, 2, 2 });
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(0, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(359, new int[] { 3, 4, 5, 6 });
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(3, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(4, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(5, mrn.getCurrentNumeralValue(3));
     //
     mrn = new MixedRadixNumber(359, new int[] { 6, 5, 4, 3 });
     Assert.AreEqual(5, mrn.getCurrentNumeralValue(0));
     Assert.AreEqual(4, mrn.getCurrentNumeralValue(1));
     Assert.AreEqual(3, mrn.getCurrentNumeralValue(2));
     Assert.AreEqual(2, mrn.getCurrentNumeralValue(3));
 }
        public ProbabilityTable(double[] vals, params RandomVariable[] vars)
        {
            if (null == vals)
            {
                throw new ArgumentException("Values must be specified");
            }
            if (vals.Length != ProbUtil.expectedSizeOfProbabilityTable(vars))
            {
                throw new ArgumentException("ProbabilityTable of Length "
                                            + values.Length + " is not the correct size, should be "
                                            + ProbUtil.expectedSizeOfProbabilityTable(vars)
                                            + " in order to represent all possible combinations.");
            }
            if (null != vars)
            {
                foreach (RandomVariable rv in vars)
                {
                    // Track index information relevant to each variable.
                    randomVarInfo.Add(rv, new RVInfo(rv));
                }
            }

            values = new double[vals.Length];
            Array.Copy(vals, 0, values, 0, vals.Length);

            radices = createRadixs(randomVarInfo);

            if (radices.Length > 0)
            {
                queryMRN = new MixedRadixNumber(0, radices);
            }
        }
        public ProbabilityTable divideBy(ProbabilityTable divisor)
        {
            if (!randomVarInfo.keySet().containsAll(divisor.randomVarInfo.keySet()))
            {
                throw new IllegalArgumentException(
                    "Divisor must be a subset of the dividend.");
            }

            ProbabilityTable quotient = new ProbabilityTable(new List<RandomVariable>(randomVarInfo.Keys));

            if (1 == divisor.getValues().Length)
            {
                double d = divisor.getValues()[0];
                for (int i = 0; i < quotient.getValues().Length; i++)
                {
                    if (0 == d)
                    {
                        quotient.getValues()[i] = 0;
                    }
                    else
                    {
                        quotient.getValues()[i] = getValues()[i]/d;
                    }
                }
            }
            else
            {
                Set<RandomVariable> dividendDivisorDiff = SetOps
                    .difference(new List<RVInfo>(randomVarInfo.keySet()),
                                new List<RVInfo>(randomVarInfo.keySet()));
                Map<RandomVariable, RVInfo> tdiff = null;
                MixedRadixNumber tdMRN = null;
                if (dividendDivisorDiff.size() > 0)
                {
                    tdiff = new LinkedHashMap<RandomVariable, RVInfo>();
                    foreach (RandomVariable rv in dividendDivisorDiff)
                    {
                        tdiff.put(rv, new RVInfo(rv));
                    }
                    tdMRN = new MixedRadixNumber(0, createRadixs(tdiff));
                }
                Map<RandomVariable, RVInfo> diff = tdiff;
                MixedRadixNumber dMRN = tdMRN;
                int[] qRVs = new int[quotient.radices.Length];
                MixedRadixNumber qMRN = new MixedRadixNumber(0,
                                                             quotient.radices);
                //ProbabilityTable.Iterator divisorIterator = new ProbabilityTable.Iterator() {
                //    public void iterate(Map<RandomVariable, Object> possibleWorld,
                //            double probability) {
                //        foreach (RandomVariable rv in possibleWorld.keySet()) {
                //            RVInfo rvInfo = quotient.randomVarInfo.get(rv);
                //            qRVs[rvInfo.getRadixIdx()] = rvInfo
                //                    .getIdxForDomain(possibleWorld.get(rv));
                //        }
                //        if (null != diff) {
                //            // Start from 0 off the diff
                //            dMRN.setCurrentValueFor(new int[diff.size()]);
                //            do {
                //                for (RandomVariable rv : diff.keySet()) {
                //                    RVInfo drvInfo = diff.get(rv);
                //                    RVInfo qrvInfo = quotient.randomVarInfo.get(rv);
                //                    qRVs[qrvInfo.getRadixIdx()] = dMRN
                //                            .getCurrentNumeralValue(drvInfo
                //                                    .getRadixIdx());
                //                }
                //                updateQuotient(probability);
                //            } while (dMRN.increment());
                //        } else {
                //            updateQuotient(probability);
                //        }
                //    }

                //    //
                //
                //private void updateQuotient(double probability) {
                //    int offset = (int) qMRN.getCurrentValueFor(qRVs);
                //    if (0 == probability) {
                //        quotient.getValues()[offset] = 0;
                //    } else {
                //        quotient.getValues()[offset] += getValues()[offset]
                //                / probability;
                //    }
                //}
                ////// 	};

                //	divisor.iterateOverTable(divisorIterator);
                // TODO
            }

            return quotient;
        }
        /**
         * Iterate over all possible values assignments for the Random Variables
         * comprising this ProbabilityTable that are not in the fixed set of values.
         * This allows you to iterate over a subset of possible combinations.
         * 
         * @param pti
         *            the ProbabilityTable Iterator to iterate
         * @param fixedValues
         *            Fixed values for a subset of the Random Variables comprising
         *            this Probability Table.
         */

        public void iterateOverTable(Factor.Iterator pti,
                                     params AssignmentProposition[] fixedValues)
        {
            Map<RandomVariable, Object> possibleWorld = new LinkedHashMap<RandomVariable, Object>();
            MixedRadixNumber tableMRN = new MixedRadixNumber(0, radices);
            int[] tableRadixValues = new int[radices.Length];

            // Assert that the Random Variables for the fixed values
            // are part of this probability table and assign
            // all the fixed values to the possible world.
            foreach (AssignmentProposition ap in fixedValues)
            {
                if (!randomVarInfo.ContainsKey(ap.getTermVariable()))
                {
                    throw new ArgumentException("Assignment proposition ["
                                                + ap + "] does not belong to this probability table.");
                }
                possibleWorld.Add(ap.getTermVariable(), ap.getValue());
                RVInfo fixedRVI = randomVarInfo.get(ap.getTermVariable());
                tableRadixValues[fixedRVI.getRadixIdx()] = fixedRVI
                    .getIdxForDomain(ap.getValue());
            }
            // If have assignments for all the random variables
            // in this probability table
            if (fixedValues.Length == randomVarInfo.Count)
            {
                // Then only 1 iteration call is required.
                pti.iterate(possibleWorld, getValue(fixedValues));
            }
            else
            {
                // Else iterate over the non-fixed values
                List<RandomVariable> freeVariables = SetOps.difference(
                    new List<RandomVariable>(randomVarInfo.Keys), new List<RandomVariable>(possibleWorld.Keys));
                Map<RandomVariable, RVInfo> freeVarInfo = new LinkedHashMap<RandomVariable, RVInfo>();
                // Remove the fixed Variables
                foreach (RandomVariable fv in freeVariables)
                {
                    freeVarInfo.put(fv, new RVInfo(fv));
                }
                int[] freeRadixValues = createRadixs(freeVarInfo);
                MixedRadixNumber freeMRN = new MixedRadixNumber(0, freeRadixValues);
                Object fval = null;
                // Iterate through all combinations of the free variables
                do
                {
                    // Put the current assignments for the free variables
                    // into the possible world and update
                    // the current index in the table MRN
                    foreach (RVInfo freeRVI in freeVarInfo.values())
                    {
                        fval = freeRVI.getDomainValueAt(freeMRN
                                                            .getCurrentNumeralValue(freeRVI.getRadixIdx()));
                        possibleWorld.put(freeRVI.getVariable(), fval);

                        tableRadixValues[randomVarInfo.get(freeRVI.getVariable())
                                             .getRadixIdx()] = freeRVI.getIdxForDomain(fval);
                    }
                    pti.iterate(possibleWorld, values[(int) tableMRN
                                                                .getCurrentValueFor(tableRadixValues)]);

                } while (freeMRN.increment());
            }
        }
        // END-Factor
        //

        /**
         * Iterate over all the possible value assignments for the Random Variables
         * comprising this ProbabilityTable.
         * 
         * @param pti
         *            the ProbabilityTable Iterator to iterate.
         */

        public void iterateOverTable(Factor.Iterator pti)
        {
            Map<RandomVariable, Object> possibleWorld = new LinkedHashMap<RandomVariable, Object>();
            MixedRadixNumber mrn = new MixedRadixNumber(0, radices);
            do
            {
                foreach (RVInfo rvInfo in randomVarInfo.Values)
                {
                    possibleWorld.put(rvInfo.getVariable(), rvInfo
                                                                .getDomainValueAt(mrn.getCurrentNumeralValue(rvInfo
                                                                                                                 .
                                                                                                                 getRadixIdx
                                                                                                                 ())));
                }
                pti.iterate(possibleWorld, values[mrn.intValue()]);

            } while (mrn.increment());
        }