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); }
/** * 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); }
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)); }
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; } } } } }
public DiffData(string data, DiffParams diffParams) { Data = data; DiffParams = diffParams; }