|
118 | 118 | would parse as an assignment gets parsed instead as an equation, and also carries out |
119 | 119 | other standard string replacements*) |
120 | 120 |
|
121 | | -StandardizeString[str_String]:=StringReplace[ |
122 | | - FixedPoint[StringReplace["==="->"=="],StringReplace[str,"="->"=="]], |
123 | | - "**"->"^"] |
| 121 | +Options[StandardizeString] = {PlusMinusSplit->True}; |
124 | 122 |
|
125 | | -StandardizeString[str_String]:=StringReplace[ |
| 123 | +StandardizeString[str_String,OptionsPattern[]]:=Module[{output},output=StringReplace[ |
126 | 124 | FixedPoint[StringReplace["==="->"=="],StringReplace[str,"="->"=="]], |
127 | | - "**"->"^"] |
| 125 | + {"**"->"^","plus_minus"->"\[PlusMinus]","minus_plus"->"\[MinusPlus]"}]; |
| 126 | +If[OptionValue[PlusMinusSplit]&&StringContainsQ[output,{"\[PlusMinus]","\[MinusPlus]"}],output="{"<>StringReplace[output,{"\[PlusMinus]"->"+","\[MinusPlus]"->"-"}]<>", "<>StringReplace[output,{"\[PlusMinus]"->"-","\[MinusPlus]"->"+"}]<>"}"];output] |
128 | 127 |
|
129 | 128 | (*StandardizeExpression: a function that performs a number of standard replacements |
130 | 129 | at the Expression stage, namely: |
|
148 | 147 | output |
149 | 148 | ] |
150 | 149 |
|
| 150 | +(* FullStandardizeString *) |
| 151 | + |
| 152 | +Options[FullStandardizeString] = {SuppressIndependentVariable -> True}; |
| 153 | + |
| 154 | +FullStandardizeString[str_,OptionsPattern[]] := Module[{output,suppress}, |
| 155 | + output=StandardizeString[str,PlusMinusSplit->True]; |
| 156 | + output = ToExpression[output,TraditionalForm]; |
| 157 | + output=StandardizeExpression[output,SuppressIndependentVariable->OptionValue[SuppressIndependentVariable]]; |
| 158 | + ToString[output,InputForm]] |
| 159 | + |
151 | 160 | (*StructureMatchQ: a function that checks whether a user's response \ |
152 | 161 | has the same structure as a given answer template, given a set of \ |
153 | 162 | named variables.*) |
|
187 | 196 |
|
188 | 197 | Options[StructureMatchQ] = {Atomic -> False}; |
189 | 198 |
|
190 | | -StructureMatchQ[answerTemplate_String,response_String,namedVariables_List] := |
| 199 | +StructureMatchQ[answerTemplate_String,response_String,namedVariables_List,multipleAnswersInterpretation_String] := |
191 | 200 | Module[{response2,answerTemplate2}, |
192 | 201 | response2=MapAll[CanonicComplex,ReplaceAll[ToExpression[response],inertFunctionRules]]; |
193 | 202 | answerTemplate2=ReplaceAll[ToExpression[answerTemplate],inertFunctionRules]; |
194 | | - MatchQ[response2,Patternize[answerTemplate2,namedVariables]]] |
| 203 | + StructureMatchQ[answerTemplate2,response2,namedVariables,multipleAnswersInterpretation]] |
| 204 | + |
| 205 | +StructureMatchQ[answerTemplate_,response_,namedVariables_List,multipleAnswersInterpretation_String] := |
| 206 | + MatchQ[response,Patternize[answerTemplate,namedVariables]] |
| 207 | + |
| 208 | +StructureMatchQ[answerTemplate_List,response_List,namedVariables_List,"match_all"]:=Apply[And,Apply[Or,Apply[StructureMatchQ[#1,#2,namedVariables,"match_all"]&,Outer[List,answerTemplate,response],{2}],{1}]] |
| 209 | + |
| 210 | +StructureMatchQ[answerTemplate_List,response_,namedVariables_List,"match_all"]:=False |
| 211 | + |
| 212 | +StructureMatchQ[answerTemplate_List,response_List,namedVariables_List,"match_any"]:=Apply[And,Apply[Or,Apply[StructureMatchQ[#1,#2,namedVariables,"match_all"]&,Outer[List,answerTemplate,response],{2}],{1}]] |
| 213 | + |
| 214 | +StructureMatchQ[answerTemplate_List,response_,namedVariables_List,"match_any"]:=Apply[Or,Map[StructureMatchQ[#1,response,namedVariables,"match_any"]&,answerTemplate]] |
| 215 | + |
| 216 | +StructureMatchQ[answerTemplate_List,response_List,namedVariables_List,"match_order"]:=Apply[And,Apply[Or,Apply[StructureMatchQ[#1,#2,namedVariables,"match_all"]&,Outer[List,answerTemplate,response],{2}],{1}]] |
195 | 217 |
|
196 | | -equalQStructure[answer_String, response_String, params_Association] := Module[{namedVariables,correctQ,expr,suppress}, |
| 218 | +StructureMatchQ[answerTemplate_List,response_,namedVariables_List,"match_order"]:=Apply[And,Apply[StructureMatchQ[#1,#2,namedVariables,"match_order"]&,Transpose[{answerTemplate,response}],{1}]] |
| 219 | + |
| 220 | +equalQStructure[answer_String, response_String, params_Association] := Module[{namedVariables,correctQ,standardizedAnswer,standardizedResponse,suppress,multipleAnswersInterpretation}, |
197 | 221 | Print["Evaluating Structure"]; |
198 | 222 | suppress = Lookup[params,"suppress_independent_variable",True]; |
199 | 223 | namedVariables = ToExpression[Lookup[params,"named_variables",{}],TraditionalForm]; |
200 | | - expr = StandardizeExpression[ToExpression[StandardizeString[answer],TraditionalForm],SuppressIndependentVariable->suppress]; |
201 | | - correctQ = StructureMatchQ[ |
202 | | - ToString[expr,InputForm], |
203 | | - response, |
204 | | - namedVariables]; |
| 224 | + standardizedAnswer = FullStandardizeString[answer,SuppressIndependentVariable->suppress]; |
| 225 | + standardizedResponse= FullStandardizeString[response,SuppressIndependentVariable->suppress]; |
| 226 | + multipleAnswersInterpretation=Lookup[params,"multiple_answers_interpretation","match_all"]; |
| 227 | + correctQ = StructureMatchQ[standardizedAnswer,standardizedResponse,namedVariables,multipleAnswersInterpretation]; |
205 | 228 |
|
206 | 229 | <| |
207 | 230 | "error" -> Null, |
|
226 | 249 | exp -> Exp, log -> Log, ln -> Log, sqrt -> Sqrt, |
227 | 250 | pi -> Pi, e -> E, i -> I}; |
228 | 251 |
|
229 | | -SemanticMatchQ[answer_,response_] := TrueQ[Simplify[(response-answer)/.activeFunctionRules] == 0] || |
| 252 | +SemanticMatchQ[answer_,response_,multipleAnswersInterpretation_String] := TrueQ[Simplify[(response-answer)/.activeFunctionRules] == 0] || |
230 | 253 | TrueQ[FullSimplify[(response-answer)/.activeFunctionRules] == 0] |
231 | 254 |
|
232 | | -SemanticMatchQ[answer_Equal, response_Equal] := |
233 | | - SemanticMatchQ[answer[[1]]-answer[[2]], response[[1]]-response[[2]]]|| |
234 | | - SemanticMatchQ[answer[[1]]-answer[[2]], response[[2]]-response[[1]]]|| |
235 | | - SemanticMatchQ[Denominator[Cancel[(answer[[1]]-answer[[2]])/(response[[1]]-response[[2]])]],1]|| |
236 | | - SemanticMatchQ[Denominator[Cancel[(response[[1]]-response[[2]])/(answer[[1]]-answer[[2]])]],1] |
| 255 | +SemanticMatchQ[answer_List,response_List,"match_all"]:=Apply[And,Apply[Or,Apply[SemanticMatchQ[#1,#2,"match_all"]&,Outer[List,answer,response],{2}],{1}]]; |
| 256 | + |
| 257 | +SemanticMatchQ[answer_List,response_,"match_all"]:=False; |
| 258 | + |
| 259 | +SemanticMatchQ[answer_List,response_List,"match_any"]:=Apply[And,Apply[Or,Apply[SemanticMatchQ[#1,#2,"match_any"]&,Outer[List,answer,response],{2}],{1}]]; |
| 260 | + |
| 261 | +SemanticMatchQ[answer_List,response_,"match_any"]:=Apply[Or,Map[SemanticMatchQ[#1,response,"match_any"]&,answer]]; |
| 262 | + |
| 263 | +SemanticMatchQ[answer_List,response_List,"match_order"]:=Apply[And,Apply[SemanticMatchQ[#1,#2,"match_order"]&,Transpose[{answer,response}],{1}]]; |
237 | 264 |
|
238 | | -SemanticMatchQ[answer_Equal, response_] := False |
| 265 | +SemanticMatchQ[answer_List,response_,"match_order"]:=False; |
239 | 266 |
|
240 | | -SemanticMatchQ[answer_, response_Equal] := False |
| 267 | +SemanticMatchQ[answer_Equal, response_Equal,multipleAnswersInterpretation_String] := |
| 268 | + SemanticMatchQ[answer[[1]]-answer[[2]], response[[1]]-response[[2]],multipleAnswersInterpretation]|| |
| 269 | + SemanticMatchQ[answer[[1]]-answer[[2]], response[[2]]-response[[1]],multipleAnswersInterpretation]|| |
| 270 | + SemanticMatchQ[Denominator[Cancel[(answer[[1]]-answer[[2]])/(response[[1]]-response[[2]])]],1,multipleAnswersInterpretation]|| |
| 271 | + SemanticMatchQ[Denominator[Cancel[(response[[1]]-response[[2]])/(answer[[1]]-answer[[2]])]],1,multipleAnswersInterpretation] |
241 | 272 |
|
242 | | -SemanticMatchQ[answer_String,response_String] := |
| 273 | +SemanticMatchQ[answer_Equal, response_,multipleAnswersInterpretation_String] := False |
| 274 | + |
| 275 | +SemanticMatchQ[answer_, response_Equal,multipleAnswersInterpretation_String] := False |
| 276 | + |
| 277 | +SemanticMatchQ[answer_String,response_String,multipleAnswersInterpretation_String] := |
243 | 278 | SemanticMatchQ[ |
244 | 279 | ToExpression[answer], |
245 | | - ToExpression[response] |
| 280 | + ToExpression[response], |
| 281 | +multipleAnswersInterpretation |
246 | 282 | ] |
247 | 283 |
|
248 | | -SemanticAndStructureMatchQ[answer_String,response_String,answerTemplate_String,namedVariables_List] := |
249 | | - TrueQ[SemanticMatchQ[answer,response]&&StructureMatchQ[answerTemplate,response,namedVariables]] |
| 284 | +SemanticAndStructureMatchQ[answer_String,response_String,answerTemplate_String,namedVariables_List,multipleAnswersInterpretation_String] := |
| 285 | + TrueQ[SemanticMatchQ[answer,response,multipleAnswersInterpretation]&&StructureMatchQ[answerTemplate,response,namedVariables,multipleAnswersInterpretation]] |
250 | 286 |
|
251 | | -equalQSemantic[answer_String, response_String, params_Association] := Module[{correctQ, expr,suppress}, |
| 287 | +equalQSemantic[answer_String, response_String, params_Association] := Module[{correctQ, standardizedAnswer,standardizedResponse,suppress,multipleAnswersInterpretation}, |
252 | 288 | Print["Evaluating Semantic"]; |
253 | 289 | suppress = Lookup[params,"suppress_independent_variable",True]; |
254 | | - expr = StandardizeExpression[ToExpression[StandardizeString[answer],TraditionalForm],SuppressIndependentVariable->suppress]; |
255 | | - correctQ = SemanticMatchQ[ |
256 | | - ToString[expr,InputForm], |
257 | | - response]; |
| 290 | + standardizedAnswer = FullStandardizeString[answer,SuppressIndependentVariable->suppress]; |
| 291 | + standardizedResponse = FullStandardizeString[response,SuppressIndependentVariable->suppress]; |
| 292 | + multipleAnswersInterpretation=Lookup[params,"multiple_answers_interpretation","match_all"]; |
| 293 | + correctQ = SemanticMatchQ[standardizedAnswer,standardizedResponse,multipleAnswersInterpretation]; |
258 | 294 |
|
259 | 295 | <| |
260 | 296 | "error" -> Null, |
|
263 | 299 | ] |
264 | 300 |
|
265 | 301 | equalQSemanticAndStructure[answer_String, response_String, params_Association] := Module[{ |
266 | | - namedVariables,answerTemplate,correctQ,answerExpr,suppress}, |
| 302 | + namedVariables,standardizedAnswer,standardizedResponse,answerTemplate,standardizedAnswerTemplate,correctQ,suppress,multipleAnswersInterpretation}, |
267 | 303 | Print["Evaluating SemanticAndStructure"]; |
268 | 304 | namedVariables = ToExpression[Lookup[params,"named_variables",{}],TraditionalForm]; |
269 | | - answerTemplate = Lookup[params,"answer_template",{}]; |
| 305 | + answerTemplate = Lookup[params,"answer_template",Automatic]; |
270 | 306 | suppress = Lookup[params,"suppress_independent_variable",True]; |
271 | | - answerExpr = StandardizeExpression[ToExpression[StandardizeString[answer],TraditionalForm],SuppressIndependentVariable->suppress]; |
272 | | - correctQ = SemanticAndStructureMatchQ[ |
273 | | - ToString[answerExpr,InputForm], |
274 | | - response, |
275 | | - answerTemplate, |
276 | | - namedVariables |
277 | | - ]; |
| 307 | + standardizedAnswer= FullStandardizeString[answer,SuppressIndependentVariable->suppress]; |
| 308 | + standardizedResponse= FullStandardizeString[response,SuppressIndependentVariable->suppress]; |
| 309 | + multipleAnswersInterpretation=Lookup[params,"multiple_answers_interpretation","match_all"]; |
| 310 | + standardizedAnswerTemplate=If[TrueQ[answerTemplate==Automatic], |
| 311 | + standardizedAnswer, |
| 312 | + FullStandardizeString[answerTemplate,SuppressIndependentVariable->suppress]]; |
| 313 | + correctQ = SemanticAndStructureMatchQ[standardizedAnswer,standardizedResponse,standardizedAnswerTemplate,namedVariables,multipleAnswersInterpretation]; |
278 | 314 |
|
279 | 315 | <| |
280 | 316 | "error" -> Null, |
|
295 | 331 |
|
296 | 332 | (* IN PARTICULAR, THE COMPARISON OF THE LENGTHS OF THE SYMBOL LISTS IS VERY HAMFISTED *) |
297 | 333 |
|
298 | | -StrictStructureMatchQ[answerTemplate_String,response_String,namedVariables_List] := |
299 | | - StructureMatchQ[answerTemplate,response,namedVariables]&& |
| 334 | +StrictStructureMatchQ[answerTemplate_String,response_String,namedVariables_List,multipleAnswersInterpretation_String] := |
| 335 | + StructureMatchQ[answerTemplate,response,namedVariables,multipleAnswersInterpretation]&& |
300 | 336 | TrueQ[ |
301 | 337 | (Length[Union[UnnamedSymbols[ToExpression[response],namedVariables]]]== |
302 | 338 | Length[Union[UnnamedSymbols[ToExpression[StandardizeString[answerTemplate],TraditionalForm],namedVariables]]])] |
303 | 339 |
|
304 | 340 | (* SemanticAndStrictStructureMatchQ: a function that combines a strict structure comparison with a test of |
305 | 341 | mathematical equivalence *) |
306 | 342 |
|
307 | | -SemanticAndStrictStructureMatchQ[answer_String,response_String,answerTemplate_String,namedVariables_List] := |
308 | | - TrueQ[SemanticMatchQ[answer,response]&&StrictStructureMatchQ[answerTemplate,response,namedVariables]] |
| 343 | +SemanticAndStrictStructureMatchQ[answer_String,response_String,answerTemplate_String,namedVariables_List,multipleAnswersInterpretation_String] := |
| 344 | + TrueQ[SemanticMatchQ[answer,response,multipleAnswersInterpretation]&&StrictStructureMatchQ[answerTemplate,response,namedVariables,multipleAnswersInterpretation]] |
309 | 345 |
|
310 | | -equalQStrictStructure[answer_String, response_String, params_Association] := Module[{namedVariables,correctQ,expr,suppress}, |
311 | | - Print["Evaluating Structure"]; |
| 346 | +equalQStrictStructure[answer_String, response_String, params_Association] := Module[{namedVariables,correctQ,suppress,standardizedAnswer,standardizedResponse,multipleAnswersInterpretation}, |
| 347 | + Print["Evaluating Strict Structure"]; |
312 | 348 | namedVariables = ToExpression[Lookup[params,"named_variables",{}],TraditionalForm]; |
313 | 349 | suppress = Lookup[params,"suppress_independent_variable",True]; |
314 | | - expr = StandardizeExpression[ToExpression[StandardizeString[answer],TraditionalForm],SuppressIndependentVariable->suppress]; |
315 | | - correctQ = StrictStructureMatchQ[ |
316 | | - ToString[expr,InputForm], |
317 | | - response, |
318 | | - namedVariables]; |
| 350 | + standardizedAnswer = FullStandardizeString[answer,SuppressIndependentVariable->suppress]; |
| 351 | + standardizedResponse= FullStandardizeString[response,SuppressIndependentVariable->suppress]; |
| 352 | + multipleAnswersInterpretation=Lookup[params,"multiple_answers_interpretation","match_all"]; |
| 353 | + correctQ = StrictStructureMatchQ[standardizedAnswer,standardizedResponse,namedVariables,multipleAnswersInterpretation]; |
319 | 354 |
|
320 | 355 | <| |
321 | 356 | "error" -> Null, |
|
324 | 359 | ] |
325 | 360 |
|
326 | 361 | equalQSemanticAndStrictStructure[answer_String, response_String, params_Association] := Module[{ |
327 | | - namedVariables,answerTemplate,correctQ,expr,suppress}, |
328 | | - Print["Evaluating SemanticAndStructure"]; |
| 362 | + namedVariables,answerTemplate,correctQ,suppress,standardizedAnswer,standardizedResponse,standardizedAnswerTemplate,multipleAnswersInterpretation}, |
| 363 | + Print["Evaluating SemanticAndStrictStructure"]; |
329 | 364 | namedVariables = ToExpression[Lookup[params,"named_variables",{}],TraditionalForm]; |
330 | | - answerTemplate = Lookup[params,"answer_template",{}]; |
| 365 | + answerTemplate = Lookup[params,"answer_template",Automatic]; |
331 | 366 | suppress = Lookup[params,"suppress_independent_variable",True]; |
332 | | - expr = StandardizeExpression[ToExpression[StandardizeString[answer],TraditionalForm],SuppressIndependentVariable->suppress]; |
333 | | - correctQ = SemanticAndStrictStructureMatchQ[ |
334 | | - ToString[expr,InputForm], |
335 | | - response, |
336 | | - answerTemplate, |
337 | | - namedVariables |
338 | | - ]; |
| 367 | + standardizedAnswer= FullStandardizeString[answer,SuppressIndependentVariable->suppress]; |
| 368 | + standardizedResponse= FullStandardizeString[response,SuppressIndependentVariable->suppress]; |
| 369 | + standardizedAnswerTemplate=If[TrueQ[answerTemplate==Automatic], |
| 370 | + standardizedAnswer, |
| 371 | + FullStandardizeString[answerTemplate,SuppressIndependentVariable->suppress]]; |
| 372 | + multipleAnswersInterpretation=Lookup[params,"multiple_answers_interpretation","match_all"]; |
| 373 | + correctQ = SemanticAndStrictStructureMatchQ[standardizedAnswer,standardizedAnswer,standardizedAnswerTemplate,namedVariables,multipleAnswersInterpretation]; |
339 | 374 |
|
340 | 375 | <| |
341 | 376 | "error" -> Null, |
|
0 commit comments