Esempio n. 1
0
 public bool Equals(DiffParams diffParams)
 {
     if (IgnoreWhitespace != diffParams.IgnoreWhitespace)
     {
         return(false);
     }
     if (IgnoreCase != diffParams.IgnoreCase)
     {
         return(false);
     }
     if (IgnoreNumbers != diffParams.IgnoreNumbers)
     {
         return(false);
     }
     if (IgnoreLineEndings != diffParams.IgnoreLineEndings)
     {
         return(false);
     }
     if (IgnoreCharacters != diffParams.IgnoreCharacters)
     {
         return(false);
     }
     return(true);
 }
Esempio n. 2
0
    /**
     * Get gameplay parameter value for desired target difficulty
     * uses PMDeltaLastTheta for PMDelta algorithm
     */
    public DiffParams computeNewDiffParams(double targetDifficulty, bool doNotUpdateLRAccuracy = false)
    {
        DiffParams diffParams = new DiffParams();

        diffParams.LogRegReady     = true;
        diffParams.AlgorithmWanted = Algorithm;
        diffParams.Betas           = null;
        diffParams.LogRegError     = DDALogRegError.OK;

        //Loading data
        List <DDADataManager.Attempt> attempts = DataManager.getAttempts(PlayerId, ChallengeId, LRNbLastAttemptsToConsider);

        //Data translation for LR
        LogisticRegression.DataLR data      = new LogisticRegression.DataLR();
        List <double[]>           indepVars = new List <double[]>();
        List <double>             depVars   = new List <double>();

        foreach (DDADataManager.Attempt attempt in attempts)
        {
            indepVars.Add(attempt.Thetas);
            depVars.Add(attempt.Result);
        }
        data.LoadDataFromList(indepVars, depVars);

        //On met a jour le dernier theta en fonction des datas si on ne l'a pas deja set
        if (indepVars.Count > 0 && !PMInitialized)
        {
            PMLastTheta   = indepVars[indepVars.Count - 1][0];
            PMWonLastTime = depVars[depVars.Count - 1] > 0 ? true : false;
            PMInitialized = true;
        }

        //Check if enough data to update LogReg
        if (attempts.Count < 10)
        {
            Debug.Log("Less than 10 attempts, can not use LogReg prediciton");
            diffParams.LogRegReady = false;
            diffParams.LogRegError = DDALogRegError.NOT_ENOUGH_SAMPLES;
        }
        else
        {
            //Chekcing wins and fails
            double nbFail = 0;
            double nbWin  = 0;
            foreach (DDADataManager.Attempt attempt in attempts)
            {
                if (attempt.Result == 0)
                {
                    nbFail++;
                }
                else
                {
                    nbWin++;
                }
            }

            //If only three fails or three wins
            if (nbFail <= 3 || nbWin <= 3)
            {
                Debug.Log("Less than 4 wins or 4 fails, will not use LogReg");
                diffParams.LogRegReady = false;

                if (nbWin <= 3)
                {
                    diffParams.LogRegError = DDALogRegError.NOT_ENOUGH_WINS;
                }
                if (nbFail <= 3)
                {
                    diffParams.LogRegError = DDALogRegError.NOT_ENOUGH_FAILS;
                }
            }
        }

        if (diffParams.LogRegReady)
        {
            //Debug.Log("Using " + data.DepVar.Length + " lines to update model");

            if (!doNotUpdateLRAccuracy && !LRAccuracyUpToDate)
            {
                //Ten fold cross val
                LRAccuracy = 0;

                for (int i = 0; i < 10; i++)
                {
                    double AccuracyNow = 0;
                    data = data.shuffle();
                    int nk = 10;
                    for (int k = 0; k < nk; k++)
                    {
                        LogisticRegression.DataLR dataTrain;
                        LogisticRegression.DataLR dataTest;
                        data.split(k * (100 / nk), (k + 1) * (100 / nk), out dataTrain, out dataTest);
                        LogReg       = LogisticRegression.ComputeModel(dataTrain);
                        AccuracyNow += LogisticRegression.TestModel(LogReg, dataTest);
                    }
                    AccuracyNow /= nk;
                    LRAccuracy  += AccuracyNow;
                }
                LRAccuracy /= 10;

                LRAccuracyUpToDate = true;

                //Using all data to update model
                LogReg = LogisticRegression.ComputeModel(data);
                diffParams.NbAttemptsUsedToCompute = data.DepVar.Length;
            }
            else
            {
                data   = data.shuffle();
                LogReg = LogisticRegression.ComputeModel(data);
                diffParams.NbAttemptsUsedToCompute = data.DepVar.Length;
            }

            if (LRAccuracy < LRMinimalAccuracy)
            {
                Debug.Log("LogReg accuracy is under " + LRMinimalAccuracy + ", not using LogReg");
                diffParams.LogRegReady = false;
                diffParams.LogRegError = DDALogRegError.ACCURACY_TOO_LOW;
            }

            if (!LogReg.isUsable())
            {
                LRAccuracy             = 0;
                diffParams.LogRegError = DDALogRegError.NEWTON_RAPHSON_ERROR;
            }
            else if (diffParams.LogRegReady)
            {
                //Verifying if LogReg is ok : must be able to work in both ways
                double   errorSum       = 0;
                double   diffTest       = 0.1;
                double[] pars           = new double[1];
                double[] parsForAllDiff = new double[10];
                string   res            = "";
                for (int i = 0; i < 8; i++)
                {
                    pars[0]           = LogReg.InvPredict(diffTest, pars, 0); //on regarde que la première variable.
                    parsForAllDiff[i] = pars[0];
                    res       = "D = " + diffTest + " par = " + pars[0];
                    errorSum += System.Math.Abs(diffTest - LogReg.Predict(pars)); //On passe dans les deux sens on doit avoir pareil
                    res      += " res = " + LogReg.Predict(pars) + "\n";
                    diffTest += 0.1;
                    //Debug.Log(res);
                }

                if (errorSum > 1 || double.IsNaN(errorSum))
                {
                    Debug.Log("Model is not solid, error = " + errorSum);
                    LRAccuracy = 0;
                    if (errorSum > 1)
                    {
                        diffParams.LogRegError = DDALogRegError.SUM_ERROR_TOO_HIGH;
                    }
                    if (double.IsNaN(errorSum))
                    {
                        diffParams.LogRegError = DDALogRegError.SUM_ERROR_IS_NAN;
                    }
                }

                //Verifying if LogReg is ok : sd of diff predictions in all theta range must not be 0
                double mean = 0;
                for (int i = 0; i < 8; i++)
                {
                    mean += parsForAllDiff[i];
                }
                mean /= 8;
                double sd = 0;
                for (int i = 0; i < 8; i++)
                {
                    sd += (parsForAllDiff[i] - mean) * (parsForAllDiff[i] - mean);
                }
                sd = System.Math.Sqrt(sd);

                //Debug.Log("Model parameter estimation sd = " + sd);

                if (sd < 0.05 || double.IsNaN(sd))
                {
                    Debug.Log("Model parameter estimation is always the same : sd=" + sd);
                    LRAccuracy = 0;

                    if (sd < 0.05)
                    {
                        diffParams.LogRegError = DDALogRegError.SD_PRED_TOO_LOW;
                    }
                    if (double.IsNaN(sd))
                    {
                        diffParams.LogRegError = DDALogRegError.SD_PRED_IS_NAN;
                    }
                }
            }
        }

        //Saving params
        diffParams.TargetDiff = targetDifficulty;
        diffParams.LRAccuracy = LRAccuracy;

        //Determining theta

        //If we want pmdelta or we want log reg but it's not available
        if ((Algorithm == DDAAlgorithm.DDA_LOGREG && !diffParams.LogRegReady) ||
            Algorithm == DDAAlgorithm.DDA_PMDELTA)
        {
            double delta = PMWonLastTime ? PMDeltaValue : -PMDeltaValue;
            delta           *= Random.Range(PMDeltaExploMin, PMDeltaExploMax);
            diffParams.Theta = PMLastTheta + delta;
            diffParams.AlgorithmActuallyUsed = DDAAlgorithm.DDA_PMDELTA;

            //If regression is okay, we can tell the difficulty for this theta
            if (diffParams.LogRegReady)
            {
                double[] pars = new double[1];
                pars[0] = diffParams.Theta;
                diffParams.TargetDiff          = 1.0 - LogReg.Predict(pars);
                diffParams.TargetDiffWithExplo = diffParams.TargetDiff;
            }
            else //Otherwise we just can tell we aim for 0.5
            {
                diffParams.TargetDiffWithExplo = 0.5;
                diffParams.TargetDiff          = 0.5;
            }
        }

        //if we want log reg and it's available
        if (Algorithm == DDAAlgorithm.DDA_LOGREG && diffParams.LogRegReady)
        {
            diffParams.TargetDiffWithExplo = targetDifficulty + Random.Range(-LRExplo, LRExplo);
            diffParams.TargetDiffWithExplo = System.Math.Min(1.0, System.Math.Max(0, diffParams.TargetDiffWithExplo));
            diffParams.Theta = LogReg.InvPredict(1.0 - diffParams.TargetDiffWithExplo);
            diffParams.AlgorithmActuallyUsed = DDAAlgorithm.DDA_LOGREG;
        }

        //if we want random log reg and it's available
        if (Algorithm == DDAAlgorithm.DDA_RANDOM_LOGREG && diffParams.LogRegReady)
        {
            diffParams.TargetDiff          = Random.Range(0.0f, 1.0f);
            diffParams.TargetDiffWithExplo = diffParams.TargetDiff; //Pas d'explo on est en random
            diffParams.Theta = LogReg.InvPredict(1.0 - diffParams.TargetDiffWithExplo);
            diffParams.AlgorithmActuallyUsed = DDAAlgorithm.DDA_RANDOM_LOGREG;
        }

        //If we want random
        if (Algorithm == DDAAlgorithm.DDA_RANDOM_THETA || (Algorithm == DDAAlgorithm.DDA_RANDOM_LOGREG && !diffParams.LogRegReady))
        {
            diffParams.Theta = Random.Range(0.0f, 1.0f);
            diffParams.AlgorithmActuallyUsed = DDAAlgorithm.DDA_RANDOM_THETA;

            //If regression is okay, we can tell the difficulty for this theta
            if (diffParams.LogRegReady)
            {
                double[] pars = new double[1];
                pars[0] = diffParams.Theta;
                diffParams.TargetDiff          = 1.0 - LogReg.Predict(pars);
                diffParams.TargetDiffWithExplo = diffParams.TargetDiff;
            }
            else //Otherwise, we don't know, let's put a negative value
            {
                diffParams.TargetDiffWithExplo = -1;
                diffParams.TargetDiff          = -1;
            }
        }

        //Save betas if we have some
        if (LogReg != null && LogReg.Betas != null && LogReg.Betas.Length > 0)
        {
            diffParams.Betas = new double[LogReg.Betas.Length];
            for (int i = 0; i < LogReg.Betas.Length; i++)
            {
                diffParams.Betas[i] = LogReg.Betas[i];
            }
        }

        //Clamp 01 double. Super inportant pour éviter les infinis
        diffParams.Theta = diffParams.Theta > 1.0 ? 1.0 : diffParams.Theta;
        diffParams.Theta = diffParams.Theta < 0.0 ? 0.0 : diffParams.Theta;

        return(diffParams);
    }
Esempio n. 3
0
        static public Tuple <List <Tuple <int, int> >, List <string> > GetDiffFixes(TextData src, TextData dest, int lineStartTabStop, bool?ignoreWhitespace, bool?ignoreCase, bool?ignoreNumbers, bool?ignoreLineEndings, string ignoreCharacters)
        {
            var textData   = new TextData[] { src, dest };
            var lineMap    = new Dictionary <int, int> [2];
            var lines      = new List <string> [2];
            var textLines  = new List <string> [2];
            var diffParams = new DiffParams(ignoreWhitespace ?? true, ignoreCase ?? true, ignoreNumbers ?? true, ignoreLineEndings ?? true, ignoreCharacters, lineStartTabStop);

            for (var pass = 0; pass < 2; ++pass)
            {
                lineMap[pass]   = Enumerable.Range(0, textData[pass].NumLines).Indexes(line => textData[pass].diffData?.LineCompare[line] != LCS.MatchType.Gap).Select((index1, index2) => new { index1, index2 }).ToDictionary(obj => obj.index2, obj => obj.index1);
                lines[pass]     = lineMap[pass].Values.Select(line => textData[pass].GetLine(line, true)).ToList();
                textLines[pass] = lines[pass].Select(line => diffParams.FormatLine(line).Item1).ToList();
            }

            var linesLCS = LCS.GetLCS(textLines[0], textLines[1], (str1, str2) => string.IsNullOrWhiteSpace(str1) == string.IsNullOrWhiteSpace(str2));

            var ranges  = new List <Tuple <int, int> >();
            var strs    = new List <string>();
            var curLine = new int[] { -1, -1 };

            diffParams = new DiffParams(ignoreWhitespace ?? false, ignoreCase ?? false, ignoreNumbers ?? false, ignoreLineEndings ?? src.OnlyEnding != null, ignoreCharacters);
            for (var line = 0; line < linesLCS.Count; ++line)
            {
                var mappedCurLine = new int[2];
                for (var pass = 0; pass < 2; ++pass)
                {
                    if (linesLCS[line][pass] != LCS.MatchType.Gap)
                    {
                        ++curLine[pass];
                        mappedCurLine[pass] = lineMap[pass][curLine[pass]];
                    }
                }

                if (linesLCS[line].IsMatch)
                {
                    var colLines = new string[2];
                    var map      = new List <int> [2];
                    for (var pass = 0; pass < 2; ++pass)
                    {
                        var formatDiffLine = diffParams.FormatLine(lines[pass][curLine[pass]]);
                        colLines[pass] = formatDiffLine.Item1;
                        map[pass]      = formatDiffLine.Item2;
                    }

                    if (colLines[0] != colLines[1])
                    {
                        var colsLCS = LCS.GetLCS(colLines[0], colLines[1]);
                        for (var pass = 0; pass < 2; ++pass)
                        {
                            var start = default(int?);
                            var pos   = -1;
                            for (var ctr = 0; ctr <= colsLCS.Count; ++ctr)
                            {
                                if ((ctr == colsLCS.Count) || (colsLCS[ctr][pass] != LCS.MatchType.Gap))
                                {
                                    ++pos;
                                }

                                if ((ctr == colsLCS.Count) || (colsLCS[ctr].IsMatch))
                                {
                                    if (start.HasValue)
                                    {
                                        var lineOffset = textData[pass].GetOffset(mappedCurLine[pass], 0);
                                        var begin      = lineOffset + map[pass][start.Value];
                                        var end        = lineOffset + map[pass][pos];
                                        if (pass == 0)
                                        {
                                            strs.Add(textData[pass].GetString(begin, end - begin));
                                        }
                                        else
                                        {
                                            ranges.Add(Tuple.Create(begin, end));
                                        }
                                        start = null;
                                    }
                                    continue;
                                }

                                start = start ?? pos + (colsLCS[ctr][pass] == LCS.MatchType.Gap ? 1 : 0);
                            }
                        }
                    }
                }

                if ((ignoreLineEndings == null) && (src.OnlyEnding != null) && (linesLCS[line][1] != LCS.MatchType.Gap))
                {
                    var endingStart = dest.endingOffset[mappedCurLine[1]];
                    var endingEnd   = dest.lineOffset[mappedCurLine[1] + 1];
                    if (endingStart == endingEnd)
                    {
                        continue;
                    }

                    if (dest.Data.Substring(endingStart, endingEnd - endingStart) != src.OnlyEnding)
                    {
                        ranges.Add(Tuple.Create(endingStart, endingEnd));
                        strs.Add(src.OnlyEnding);
                    }
                }
            }

            return(Tuple.Create(ranges, strs));
        }
Esempio n. 4
0
        public static void CalculateDiff(TextData textData0, TextData textData1, bool ignoreWhitespace, bool ignoreCase, bool ignoreNumbers, bool ignoreLineEndings, string ignoreCharacters)
        {
            var diffParams = new DiffParams(ignoreWhitespace, ignoreCase, ignoreNumbers, ignoreLineEndings, ignoreCharacters);

            if ((textData0.diffData != null) && (textData1.diffData != null) && (textData0.diffData.Data == textData0.Data) && (textData1.diffData.Data == textData1.Data) && (textData0.diffData.DiffParams.Equals(diffParams)) && (textData1.diffData.DiffParams.Equals(diffParams)))
            {
                return;
            }

            var textData = new TextData[] { textData0, textData1 };
            var lines    = new List <string> [2];
            var map      = new List <List <int> > [2];

            for (var pass = 0; pass < 2; ++pass)
            {
                textData[pass].ClearDiff();
                textData[pass].diffData = new DiffData(textData[pass].Data, diffParams);
                var formatDiffLine = Enumerable.Range(0, textData[pass].NumLines).Select(line => diffParams.FormatLine(textData[pass].GetLine(line, true))).ToList();
                lines[pass] = formatDiffLine.Select(val => val.Item1).ToList();
                map[pass]   = formatDiffLine.Select(val => val.Item2).ToList();
            }

            var linesLCS = LCS.GetLCS(lines[0], lines[1], (str1, str2) => (string.IsNullOrWhiteSpace(str1) == string.IsNullOrWhiteSpace(str2)));

            for (var pass = 0; pass < 2; ++pass)
            {
                textData[pass].diffData.LineCompare = linesLCS.Select(val => val[pass]).ToList();
                for (var ctr = 0; ctr < linesLCS.Count; ++ctr)
                {
                    if (linesLCS[ctr][pass] == LCS.MatchType.Gap)
                    {
                        textData[pass].lineOffset.Insert(ctr, textData[pass].lineOffset[ctr]);
                        textData[pass].endingOffset.Insert(ctr, textData[pass].lineOffset[ctr]);
                    }
                }

                textData[pass].diffData.LineMap = new Dictionary <int, int>();
                var pos = -1;
                for (var line = 0; line < linesLCS.Count; ++line)
                {
                    if (linesLCS[line][pass] != LCS.MatchType.Gap)
                    {
                        ++pos;
                    }
                    textData[pass].diffData.LineMap[line] = pos;
                }
                textData[pass].diffData.LineRevMap = textData[pass].diffData.LineMap.GroupBy(pair => pair.Value).ToDictionary(group => group.Key, group => group.Min(pair => pair.Key));
                textData[pass].diffData.ColCompare = new List <Tuple <int, int> > [linesLCS.Count];
            }

            var curLine = new int[] { -1, -1 };

            for (var line = 0; line < textData0.diffData.ColCompare.Length; ++line)
            {
                for (var pass = 0; pass < 2; ++pass)
                {
                    ++curLine[pass];
                }

                if (linesLCS[line].IsMatch)
                {
                    continue;
                }

                var skip = false;
                for (var pass = 0; pass < 2; ++pass)
                {
                    if (linesLCS[line][pass] == LCS.MatchType.Gap)
                    {
                        --curLine[pass];
                        textData[1 - pass].diffData.ColCompare[line] = new List <Tuple <int, int> > {
                            Tuple.Create(0, int.MaxValue)
                        };
                        skip = true;
                    }
                }
                if (skip)
                {
                    continue;
                }

                var colsLCS = LCS.GetLCS(lines[0][curLine[0]], lines[1][curLine[1]], (ch1, ch2) => (char.IsLetterOrDigit(ch1) && char.IsLetterOrDigit(ch2)) || (char.IsWhiteSpace(ch1) && char.IsWhiteSpace(ch2)));

                for (var pass = 0; pass < 2; ++pass)
                {
                    var start = default(int?);
                    var pos   = -1;
                    textData[pass].diffData.ColCompare[line] = new List <Tuple <int, int> >();
                    for (var ctr = 0; ctr <= colsLCS.Count; ++ctr)
                    {
                        if ((ctr == colsLCS.Count) || (colsLCS[ctr][pass] != LCS.MatchType.Gap))
                        {
                            ++pos;
                        }

                        if ((ctr == colsLCS.Count) || (colsLCS[ctr].IsMatch))
                        {
                            if (start.HasValue)
                            {
                                textData[pass].diffData.ColCompare[line].Add(Tuple.Create(map[pass][curLine[pass]][start.Value], map[pass][curLine[pass]][pos]));
                            }
                            start = null;
                            continue;
                        }

                        if (colsLCS[ctr][pass] == LCS.MatchType.Mismatch)
                        {
                            start = start ?? pos;
                        }
                    }
                }
            }
        }
Esempio n. 5
0
 public DiffData(string data, DiffParams diffParams)
 {
     Data       = data;
     DiffParams = diffParams;
 }