public static XElement getTwoWordsInstructorFeedback(XElement regex, XElement xAlphabet, XElement first, XElement second) { string firstString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(first.ToString()))).Value.Trim(); string secondString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(second.ToString()))).Value.Trim(); HashSet <char> alphabet = parseAlphabet(xAlphabet); CharSetSolver solver = new CharSetSolver(BitWidth.BV64); var dfaPair = DFAUtilities.parseRegexFromXML(regex, xAlphabet, solver); var dfa = dfaPair.Second.Determinize(solver).Minimize(solver); firstString = firstString.decodeEpsilon(); secondString = secondString.decodeEpsilon(); int firstState = DFAUtilities.GetStateAfterString(dfa.InitialState, firstString, dfa, solver); int secondState = DFAUtilities.GetStateAfterString(dfa.InitialState, secondString, dfa, solver); bool areEquivalent = (firstState == secondState); if (areEquivalent) { var suffixDfa = Automaton <BDD> .Create(firstState, dfa.GetFinalStates(), dfa.GetMoves()); var suffixRegex = solver.ConvertToRegex(suffixDfa); suffixRegex = regexToTraditional(suffixRegex); return(XElement.Parse(String.Format("<div><feedback> The words '{0}' and '{1}' are equivalent. The language of suffixes is '{2}'</feedback></div>", firstString, secondString, suffixRegex))); } else { var shortestDiff = DFAUtilities.GetDifferentiatingWord(firstState, secondState, dfa, alphabet, solver).Second; return(XElement.Parse(String.Format("<div><feedback> The words '{0}' and '{1}' are NOT equivalent. The shortest differentiating word is '{2}'</feedback></div>", firstString, secondString, shortestDiff))); } }
public static bool compareNfaToRegex(XElement regex, XElement alphabet, XElement attemptNfa) { CharSetSolver solver = new CharSetSolver(BitWidth.BV64); var dfaCorrectPair = DFAUtilities.parseRegexFromXML(regex, alphabet, solver); var attempt = DFAUtilities.parseBlockFromXML(attemptNfa, alphabet, solver); var same = dfaCorrectPair.Second.IsEquivalentWith(attempt.Second, solver); return(same); }
public static XElement getShortestFeedback(XElement regex, XElement xAlphabet, XElement representative, XElement attemptShortest, XElement maxGrade) { int maxG = int.Parse(maxGrade.Value); CharSetSolver solver = new CharSetSolver(BitWidth.BV64); var dfaPair = DFAUtilities.parseRegexFromXML(regex, xAlphabet, solver); var dfa = dfaPair.Second.Minimize(solver); string representativeString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(representative.ToString()))).Value.Trim(); representativeString = representativeString.decodeEpsilon(); string attemptShortestString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(attemptShortest.ToString()))).Value.Trim(); attemptShortestString = attemptShortestString.decodeEpsilon(); int representativeState = DFAUtilities.GetStateAfterString(dfa.InitialState, representativeString, dfa, solver); int attemptShortestState = DFAUtilities.GetStateAfterString(dfa.InitialState, attemptShortestString, dfa, solver); xAlphabet = XElement.Parse(DFAUtilities.RemoveAllNamespaces(xAlphabet.ToString())); HashSet <char> alphabet = parseAlphabet(xAlphabet); string correctShortest = DFAUtilities.GetRepresentative(representativeState, dfa, alphabet, solver); if (correctShortest.Equals(attemptShortestString)) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>Correct!</feedback></div>", maxG))); } else if (attemptShortestState == representativeState) { if (representativeString.Equals(attemptShortestString)) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>Please provide a different word than the given one</feedback></div>", 0))); } else if (attemptShortestString.Length > correctShortest.Length) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>The word '{1}' is in the same equivalence class as '{2}' but there exists a shorter one</feedback></div>", (int)(maxG * 2 / 3), attemptShortestString.emptyToEpsilon(), representativeString.emptyToEpsilon()))); } else { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>The word '{1}' is in the same equivalence class as '{2}' but there exists a <strong>lexicographically smaller</strong> one</feedback></div>", (int)(maxG * 4 / 5), attemptShortestString.emptyToEpsilon(), representativeString.emptyToEpsilon()))); } } else { string feedString = "Incorrect!";//"The Correct Answer is '" + correctShortest + "'"; return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>{1}</feedback></div>", 0, feedString))); } }
public static XElement getWordsFeedback(XElement regex, XElement xAlphabet, XElement representative, XElement wordsIn, XElement maxGrade) { //read inputs int maxG = int.Parse(maxGrade.Value); List <string> wordsInList = new List <String>(); HashSet <string> usedWords = new HashSet <string>(); foreach (var wordElement in wordsIn.Elements()) { string w = wordElement.Value; if (w.Length > 75) { w = w.Substring(0, 75); //limit word length } w = w.decodeEpsilon(); wordsInList.Add(w); } HashSet <char> alphabet = parseAlphabet(xAlphabet); string alphabetString = alphabetToString(alphabet); CharSetSolver solver = new CharSetSolver(BitWidth.BV64); var dfaPair = DFAUtilities.parseRegexFromXML(regex, xAlphabet, solver); var dfa = dfaPair.Second.Minimize(solver); string representativeString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(representative.ToString()))).Value.Trim(); representativeString = representativeString.decodeEpsilon(); int representativeState = DFAUtilities.GetStateAfterString(dfa.InitialState, representativeString, dfa, solver); string feedString = "<ul>"; int correct = 0; int total = wordsInList.Count; usedWords.Add(representativeString); foreach (string s in wordsInList) { //TODO: Check string only contains valid characters if (usedWords.Contains(s)) { if (s.Equals(representativeString)) { feedString += String.Format("<li> The word '{0}' was provided by the instructor </li>", s.emptyToEpsilon()); } else { feedString += String.Format("<li> The word '{0}' was already used </li>", s.emptyToEpsilon()); } continue; } bool overValidAlphabet = true; foreach (char c in s) { if (!alphabet.Contains(c)) { overValidAlphabet = false; } } if (!overValidAlphabet) { feedString += String.Format("<li> The word '{0}' is not over the alphabet {1} </li>", s.emptyToEpsilon(), alphabetString); continue; } usedWords.Add(s); int wordState = DFAUtilities.GetStateAfterString(dfa.InitialState, s, dfa, solver); if (wordState == representativeState) { correct++; } else { feedString += String.Format("<li> The word '{0}' is not in the same equivalence class as '{1}' </li>", s.emptyToEpsilon(), representativeString.emptyToEpsilon()); } } feedString += "</ul>"; var grade = 1.0 * int.Parse(maxGrade.Value) * correct / total; if (grade == maxG) { feedString = "Correct!"; } return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>{1}</feedback></div>", (int)(Math.Ceiling(grade)), feedString))); }
public static XElement getSameFeedback(XElement regex, XElement xAlphabet, XElement first, XElement second, XElement notEquivalent, XElement reason, XElement maxGrade) { string firstString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(first.ToString()))).Value.Trim().decodeEpsilon(); string secondString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(second.ToString()))).Value.Trim().decodeEpsilon(); string reasonString = (XElement.Parse(DFAUtilities.RemoveAllNamespaces(reason.ToString()))).Value.Trim(); bool areEquivalentAttempt = int.Parse(notEquivalent.Value) == 1 ? false : true; int maxG = int.Parse(maxGrade.Value); HashSet <char> alphabet = parseAlphabet(xAlphabet); CharSetSolver solver = new CharSetSolver(BitWidth.BV64); var dfaPair = DFAUtilities.parseRegexFromXML(regex, xAlphabet, solver); var dfa = dfaPair.Second.Minimize(solver); int firstState = DFAUtilities.GetStateAfterString(dfa.InitialState, firstString, dfa, solver); int secondState = DFAUtilities.GetStateAfterString(dfa.InitialState, secondString, dfa, solver); bool areEquivalent = (firstState == secondState); if (areEquivalent != areEquivalentAttempt) { return(XElement.Parse(string.Format("<div><grade>0</grade><feedback>Wrong equivalency assesment!</feedback></div>"))); } else if (areEquivalent) { try { var suffixDfa = Automaton <BDD> .Create(firstState, dfa.GetFinalStates(), dfa.GetMoves()); var reasonDfaPair = DFAUtilities.parseRegexFromXML(reason, xAlphabet, solver); var dfaGradingFeedback = DFAGrading.GetGrade(suffixDfa, reasonDfaPair.Second, alphabet, solver, 1500, maxG, FeedbackLevel.Minimal, false, false, true); var feedString = "<div>"; foreach (var feed in dfaGradingFeedback.Second) { feedString += string.Format("{0}<br />", feed); } feedString += "</div>"; if (maxG == dfaGradingFeedback.First) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>Correct!</feedback></div>", maxG))); } else { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>{1}</feedback></div>", Math.Max((int)(maxG / 3), dfaGradingFeedback.First), feedString))); } } catch (PDLException pdlex) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>Parsing Error: {1}</feedback></div>", (int)(maxG / 3), pdlex.Message))); } } else { // Finding a shortest differentiating word var shortestDiff = DFAUtilities.GetDifferentiatingWord(firstState, secondState, dfa, alphabet, solver).Second; reasonString = reasonString.decodeEpsilon(); int endFirst = DFAUtilities.GetStateAfterString(firstState, reasonString, dfa, solver); int endSecond = DFAUtilities.GetStateAfterString(secondState, reasonString, dfa, solver); bool c1 = dfa.GetFinalStates().Contains(endFirst); bool c2 = dfa.GetFinalStates().Contains(endSecond); if (c1 ^ c2) { return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>Correct!</feedback></div>", maxG))); } else { string feedString = string.Format("The words '{0}' and '{2}' are both {1} by the language", (firstString + reasonString).emptyToEpsilon(), c1 ? "accepted" : "not accepted", (secondString + reasonString).emptyToEpsilon()); return(XElement.Parse(string.Format("<div><grade>{0}</grade><feedback>{1}</feedback></div>", (int)(maxG / 3), feedString))); } } }