/// <summary>
        /// The prediction method which can be called from SQL Server
        /// </summary>
        /// <param name="inputCase"></param>
        /// <param name="predictionResult"></param>
        protected override void Predict(MiningCase inputCase, PredictionResult predictionResult)
        {
            //the input values and predictec label
            double[] values;
            uint     label         = 0;
            int      attributeSize = 0;

            //convert and scale the input
            getValues(inputCase, out values, out label, out attributeSize);
            Instance instance = new Instance(1, (int)label, values, getLabels());

            //obtain the votes
            int[] votes = getVotes(instance);
            label = 0;
            for (uint i = 1; i < votes.Length; i++)
            {
                if (votes[i] > votes[label])
                {
                    label = i;
                }
            }

            //construct the output
            AttributeStatistics attStats = new AttributeStatistics();

            attStats.Attribute = getTargetAttribute();
            StateStatistics stateStat = new StateStatistics();
            StateValue      stateVal  = new StateValue();

            stateVal.SetIndex(label);

            stateStat.Value = AttributeSet.TokenizeAttributeValue(attStats.Attribute, AttributeSet.UntokenizeAttributeValue(attStats.Attribute, stateVal));
            attStats.StateStatistics.Add(stateStat);
            predictionResult.AddPrediction(attStats);
        }
 /// <summary>
 /// Support drill-through functionality for the viewer
 /// </summary>
 /// <param name="nodeFlags"></param>
 /// <param name="caseID"></param>
 /// <param name="inputCase"></param>
 /// <param name="maxNodes"></param>
 /// <returns></returns>
 protected override string[] GetNodeIDsForCase(
     DrillThroughNodeFlags nodeFlags,
     long caseID, MiningCase inputCase,
     ulong maxNodes)
 {
     return(new string[] { "" });
 }
        /// <summary>
        /// Convert the input case to continuous space. This consists of 2 steps:
        /// 1. Convert all discrete columns to continuous input space
        /// 2. Scale the input columns to lie between 0 and 1
        /// </summary>
        /// <param name="inputCase">An input example</param>
        /// <param name="doubleValues">the output in continous n-dimensional space</param>
        /// <param name="label">the label of the example</param>
        /// <param name="attributeSize">the size of the n-dimensional space</param>
        public void getValues(MiningCase inputCase, out double[] doubleValues, out uint label, out int attributeSize)
        {
            //save the input example in a dictionary
            SortedDictionary <uint, double> dict = new SortedDictionary <uint, double>();
            bool bContinue = inputCase.MoveFirst();

            while (bContinue)
            {
                if (inputCase.Value.IsDouble)
                {
                    dict.Add(inputCase.Attribute, inputCase.DoubleValue);
                }
                else
                {
                    dict.Add(inputCase.Attribute, inputCase.Value.Index);
                }
                bContinue = inputCase.MoveNext();
            }

            //the linked list will save all the values
            LinkedList <double> values = new LinkedList <double>();

            label         = 0;
            attributeSize = 0;

            //loop through the dictionary and scale the input and store it in the linked list
            SortedDictionary <uint, double> .Enumerator enumerator = dict.GetEnumerator();
            while (enumerator.MoveNext())
            {
                uint   attribute = enumerator.Current.Key;
                double value     = enumerator.Current.Value;
                if (!isNominal(attribute))
                {
                    //scaling
                    double max = MarginalStats.GetAttributeStats(attribute).Max;
                    double min = MarginalStats.GetAttributeStats(attribute).Min;
                    value = (value - min) / (max - min);
                    if (Double.IsNaN(value) || Double.IsInfinity(value))
                    {
                        value = 0;
                        attributeSize++;
                    }
                    values.AddLast(value);
                }
                else
                {
                    if (isTarget(attribute))
                    {
                        label = (uint)value;
                    }
                    else
                    {
                        for (uint i = 0; i < AttributeSet.GetAttributeStateCount(attribute); i++)
                        {
                            if (i == (uint)value)
                            {
                                values.AddLast(1);
                            }
                            else
                            {
                                values.AddLast(0);
                            }
                            attributeSize++;
                        }
                    }
                }
            }
            this.attributeSize = attributeSize;
            doubleValues       = new double[values.Count];
            values.CopyTo(doubleValues, 0);
        }