@doenet/doenetml 0.6.0-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +3 -0
- package/LICENSE +661 -0
- package/README.md +146 -0
- package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
- package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
- package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
- package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
- package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
- package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
- package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
- package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
- package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
- package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
- package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
- package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
- package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
- package/cypress/e2e/assignNames/collections.cy.js +9247 -0
- package/cypress/e2e/assignNames/selects.cy.js +105 -0
- package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
- package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
- package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
- package/cypress/e2e/chemistry/atom.cy.js +201 -0
- package/cypress/e2e/chemistry/ion.cy.js +608 -0
- package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
- package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
- package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
- package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
- package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
- package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
- package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
- package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
- package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
- package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
- package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
- package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
- package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
- package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
- package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
- package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
- package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
- package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
- package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
- package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
- package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
- package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
- package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
- package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
- package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
- package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
- package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
- package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
- package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
- package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
- package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
- package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
- package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
- package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
- package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
- package/cypress/e2e/tagSpecific/document.cy.js +234 -0
- package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
- package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
- package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
- package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
- package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
- package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
- package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
- package/cypress/e2e/tagSpecific/group.cy.js +683 -0
- package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
- package/cypress/e2e/tagSpecific/image.cy.js +770 -0
- package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
- package/cypress/e2e/tagSpecific/label.cy.js +800 -0
- package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
- package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
- package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
- package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
- package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
- package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
- package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
- package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
- package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
- package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
- package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
- package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
- package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
- package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
- package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
- package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
- package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
- package/cypress/e2e/tagSpecific/p.cy.js +72 -0
- package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
- package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
- package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
- package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
- package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
- package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
- package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
- package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
- package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
- package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
- package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
- package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
- package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
- package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
- package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
- package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
- package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
- package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
- package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
- package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
- package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
- package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
- package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
- package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
- package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
- package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
- package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
- package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
- package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
- package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
- package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
- package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
- package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
- package/cypress/e2e/tagSpecific/text.cy.js +975 -0
- package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
- package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
- package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
- package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
- package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
- package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
- package/cypress/e2e/tagSpecific/video.cy.js +612 -0
- package/cypress/e2e/tagSpecific/when.cy.js +202 -0
- package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
- package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.js +32 -0
- package/cypress/support/e2e.js +31 -0
- package/cypress.config.js +18 -0
- package/docs/codeSnippet.jsx +11 -0
- package/docs/index.html +133 -0
- package/docs/index.jsx +138 -0
- package/docs/prism.css +3 -0
- package/index.html +14 -0
- package/index.js +21 -0
- package/media/answer_example.png +0 -0
- package/media/graph_example.png +0 -0
- package/media/graph_markup_example.png +0 -0
- package/package.json +83 -0
- package/public/favicon.ico +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/Core/ComponentTypes.js +426 -0
- package/src/Core/Core.js +11852 -0
- package/src/Core/CoreWorker.js +127 -0
- package/src/Core/Dependencies.js +8226 -0
- package/src/Core/Numerics.js +473 -0
- package/src/Core/ParameterStack.js +36 -0
- package/src/Core/ReadOnlyProxyHandler.js +41 -0
- package/src/Core/StateProxyHandler.js +88 -0
- package/src/Core/components/Aliases.js +67 -0
- package/src/Core/components/Angle.js +758 -0
- package/src/Core/components/AnimateFromSequence.js +922 -0
- package/src/Core/components/Answer.js +2087 -0
- package/src/Core/components/AsList.js +83 -0
- package/src/Core/components/AttractTo.js +245 -0
- package/src/Core/components/AttractToAngles.js +262 -0
- package/src/Core/components/AttractToConstraint.js +104 -0
- package/src/Core/components/AttractToGrid.js +315 -0
- package/src/Core/components/Award.js +906 -0
- package/src/Core/components/BestFitLine.js +318 -0
- package/src/Core/components/BezierControls.js +719 -0
- package/src/Core/components/BlockQuote.js +35 -0
- package/src/Core/components/Boolean.js +500 -0
- package/src/Core/components/BooleanInput.js +330 -0
- package/src/Core/components/BooleanList.js +396 -0
- package/src/Core/components/BooleanOperators.js +35 -0
- package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
- package/src/Core/components/CallAction.js +261 -0
- package/src/Core/components/Caption.js +73 -0
- package/src/Core/components/Case.js +56 -0
- package/src/Core/components/Cell.js +439 -0
- package/src/Core/components/CellBlock.js +64 -0
- package/src/Core/components/Chart.js +795 -0
- package/src/Core/components/Choice.js +266 -0
- package/src/Core/components/ChoiceInput.js +1407 -0
- package/src/Core/components/Circle.js +2884 -0
- package/src/Core/components/CodeEditor.js +647 -0
- package/src/Core/components/CodeViewer.js +294 -0
- package/src/Core/components/CollaborateGroupSetup.js +46 -0
- package/src/Core/components/CollaborateGroups.js +119 -0
- package/src/Core/components/Collect.js +850 -0
- package/src/Core/components/Column.js +608 -0
- package/src/Core/components/ConditionalContent.js +468 -0
- package/src/Core/components/ConsiderAsResponses.js +49 -0
- package/src/Core/components/ConstrainTo.js +161 -0
- package/src/Core/components/ConstrainToAngles.js +244 -0
- package/src/Core/components/ConstrainToGraph.js +142 -0
- package/src/Core/components/ConstrainToGrid.js +175 -0
- package/src/Core/components/ConstraintUnion.js +119 -0
- package/src/Core/components/Constraints.js +497 -0
- package/src/Core/components/ContentBrowser.js +441 -0
- package/src/Core/components/ContentPicker.js +263 -0
- package/src/Core/components/ControlVectors.js +25 -0
- package/src/Core/components/Coords.js +63 -0
- package/src/Core/components/Copy.js +3412 -0
- package/src/Core/components/Curve.js +4130 -0
- package/src/Core/components/CustomAttribute.js +175 -0
- package/src/Core/components/DataFrame.js +357 -0
- package/src/Core/components/DiscreteSimulationResultList.js +342 -0
- package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
- package/src/Core/components/Divisions.js +55 -0
- package/src/Core/components/Document.js +888 -0
- package/src/Core/components/Embed.js +65 -0
- package/src/Core/components/Endpoint.js +62 -0
- package/src/Core/components/Evaluate.js +321 -0
- package/src/Core/components/Extract.js +656 -0
- package/src/Core/components/Extrema.js +556 -0
- package/src/Core/components/Feedback.js +200 -0
- package/src/Core/components/FeedbackDefinitions.js +97 -0
- package/src/Core/components/Figure.js +148 -0
- package/src/Core/components/Footnote.js +73 -0
- package/src/Core/components/Function.js +5344 -0
- package/src/Core/components/FunctionIterates.js +306 -0
- package/src/Core/components/FunctionOperators.js +702 -0
- package/src/Core/components/Graph.js +1679 -0
- package/src/Core/components/Group.js +7 -0
- package/src/Core/components/HasSameFactoring.js +407 -0
- package/src/Core/components/Hint.js +241 -0
- package/src/Core/components/Image.js +524 -0
- package/src/Core/components/Indexing.js +79 -0
- package/src/Core/components/IntComma.js +64 -0
- package/src/Core/components/Integer.js +81 -0
- package/src/Core/components/Intersection.js +328 -0
- package/src/Core/components/Interval.js +29 -0
- package/src/Core/components/Label.js +492 -0
- package/src/Core/components/Latex.js +104 -0
- package/src/Core/components/Legend.js +329 -0
- package/src/Core/components/Line.js +2040 -0
- package/src/Core/components/LineSegment.js +882 -0
- package/src/Core/components/Lists.js +180 -0
- package/src/Core/components/Lorem.js +249 -0
- package/src/Core/components/MMeMen.js +377 -0
- package/src/Core/components/Map.js +873 -0
- package/src/Core/components/Markers.js +101 -0
- package/src/Core/components/MatchesPattern.js +339 -0
- package/src/Core/components/Math.js +2552 -0
- package/src/Core/components/MathInput.js +948 -0
- package/src/Core/components/MathList.js +828 -0
- package/src/Core/components/MathOperators.js +1286 -0
- package/src/Core/components/Matrix.js +497 -0
- package/src/Core/components/MatrixInput.js +3157 -0
- package/src/Core/components/MdMdnMrow.js +394 -0
- package/src/Core/components/Module.js +16 -0
- package/src/Core/components/Number.js +1031 -0
- package/src/Core/components/NumberList.js +550 -0
- package/src/Core/components/Option.js +24 -0
- package/src/Core/components/P.js +71 -0
- package/src/Core/components/Paginator.js +338 -0
- package/src/Core/components/Panel.js +126 -0
- package/src/Core/components/Parabola.js +1561 -0
- package/src/Core/components/ParagraphMarkup.js +59 -0
- package/src/Core/components/Pegboard.js +43 -0
- package/src/Core/components/PeriodicSet.js +291 -0
- package/src/Core/components/PiecewiseFunction.js +832 -0
- package/src/Core/components/Pluralize.js +198 -0
- package/src/Core/components/Point.js +1295 -0
- package/src/Core/components/Polygon.js +408 -0
- package/src/Core/components/Polyline.js +841 -0
- package/src/Core/components/RandomizedTextList.js +225 -0
- package/src/Core/components/Ray.js +1737 -0
- package/src/Core/components/Rectangle.js +1535 -0
- package/src/Core/components/Ref.js +350 -0
- package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
- package/src/Core/components/RegionHalfPlane.js +107 -0
- package/src/Core/components/RegularPolygon.js +2118 -0
- package/src/Core/components/RenderDoenetML.js +181 -0
- package/src/Core/components/Row.js +780 -0
- package/src/Core/components/SampleRandomNumbers.js +653 -0
- package/src/Core/components/Sectioning.js +303 -0
- package/src/Core/components/Select.js +947 -0
- package/src/Core/components/SelectFromSequence.js +1242 -0
- package/src/Core/components/SelectRandomNumbers.js +225 -0
- package/src/Core/components/Sequence.js +444 -0
- package/src/Core/components/Setup.js +53 -0
- package/src/Core/components/Shuffle.js +470 -0
- package/src/Core/components/SideBySide.js +2130 -0
- package/src/Core/components/SingleCharacterComponents.js +41 -0
- package/src/Core/components/Slider.js +819 -0
- package/src/Core/components/SolutionContainer.js +67 -0
- package/src/Core/components/Solutions.js +334 -0
- package/src/Core/components/SolveEquations.js +568 -0
- package/src/Core/components/Sort.js +398 -0
- package/src/Core/components/Sources.js +108 -0
- package/src/Core/components/Split.js +205 -0
- package/src/Core/components/Spreadsheet.js +1507 -0
- package/src/Core/components/StyleDefinitions.js +111 -0
- package/src/Core/components/SubsetOfReals.js +348 -0
- package/src/Core/components/SubsetOfRealsInput.js +1474 -0
- package/src/Core/components/Substitute.js +496 -0
- package/src/Core/components/SummaryStatistics.js +652 -0
- package/src/Core/components/Table.js +145 -0
- package/src/Core/components/Tabular.js +384 -0
- package/src/Core/components/Template.js +360 -0
- package/src/Core/components/Text.js +341 -0
- package/src/Core/components/TextInput.js +566 -0
- package/src/Core/components/TextList.js +442 -0
- package/src/Core/components/TextListFromString.js +137 -0
- package/src/Core/components/TextOperatorsOfMath.js +21 -0
- package/src/Core/components/Triangle.js +280 -0
- package/src/Core/components/TriggerSet.js +189 -0
- package/src/Core/components/TupleList.js +43 -0
- package/src/Core/components/UpdateValue.js +435 -0
- package/src/Core/components/VariantControl.js +36 -0
- package/src/Core/components/Vector.js +2478 -0
- package/src/Core/components/Verbatim.js +125 -0
- package/src/Core/components/Video.js +673 -0
- package/src/Core/components/When.js +198 -0
- package/src/Core/components/abstract/AngleListComponent.js +140 -0
- package/src/Core/components/abstract/BaseComponent.js +1496 -0
- package/src/Core/components/abstract/BlockComponent.js +5 -0
- package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
- package/src/Core/components/abstract/ComponentSize.js +789 -0
- package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
- package/src/Core/components/abstract/CompositeComponent.js +142 -0
- package/src/Core/components/abstract/ConstraintComponent.js +19 -0
- package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
- package/src/Core/components/abstract/GraphicalComponent.js +56 -0
- package/src/Core/components/abstract/InlineComponent.js +5 -0
- package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
- package/src/Core/components/abstract/Input.js +192 -0
- package/src/Core/components/abstract/IntervalListComponent.js +218 -0
- package/src/Core/components/abstract/LineListComponent.js +114 -0
- package/src/Core/components/abstract/MathBaseOperator.js +631 -0
- package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
- package/src/Core/components/abstract/PointListComponent.js +238 -0
- package/src/Core/components/abstract/SectioningComponent.js +1262 -0
- package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
- package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
- package/src/Core/components/abstract/TextOrInline.js +66 -0
- package/src/Core/components/abstract/VariableName.js +31 -0
- package/src/Core/components/abstract/VariableNameList.js +83 -0
- package/src/Core/components/abstract/VectorListComponent.js +235 -0
- package/src/Core/components/chemistry/Atom.js +910 -0
- package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
- package/src/Core/components/chemistry/Ion.js +684 -0
- package/src/Core/components/chemistry/IonicCompound.js +189 -0
- package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
- package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
- package/src/Core/components/chemistry/index.js +6 -0
- package/src/Core/components/commonsugar/breakstrings.js +627 -0
- package/src/Core/components/commonsugar/lists.js +177 -0
- package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
- package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
- package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
- package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
- package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
- package/src/Core/components/dynamicalSystems/index.js +5 -0
- package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
- package/src/Core/utils/array.js +30 -0
- package/src/Core/utils/booleanLogic.js +965 -0
- package/src/Core/utils/checkEquality.js +818 -0
- package/src/Core/utils/cid.js +29 -0
- package/src/Core/utils/componentInfoObjects.js +100 -0
- package/src/Core/utils/constraints.js +23 -0
- package/src/Core/utils/copy.js +572 -0
- package/src/Core/utils/deepFunctions.js +173 -0
- package/src/Core/utils/descendants.js +252 -0
- package/src/Core/utils/enumeration.js +234 -0
- package/src/Core/utils/feedback.js +84 -0
- package/src/Core/utils/function.js +1343 -0
- package/src/Core/utils/graphical.js +196 -0
- package/src/Core/utils/label.js +396 -0
- package/src/Core/utils/math.js +1056 -0
- package/src/Core/utils/naming.js +45 -0
- package/src/Core/utils/periodicSetEquality.js +403 -0
- package/src/Core/utils/randomNumbers.js +70 -0
- package/src/Core/utils/retrieveMedia.js +98 -0
- package/src/Core/utils/retrieveTextFile.js +140 -0
- package/src/Core/utils/returnAllPossibleVariants.js +73 -0
- package/src/Core/utils/rounding.js +316 -0
- package/src/Core/utils/sequence.js +754 -0
- package/src/Core/utils/serializedStateProcessing.js +4049 -0
- package/src/Core/utils/size.js +22 -0
- package/src/Core/utils/stateVariables.js +138 -0
- package/src/Core/utils/style.js +535 -0
- package/src/Core/utils/subset-of-reals.js +796 -0
- package/src/Core/utils/table.js +41 -0
- package/src/Core/utils/text.js +16 -0
- package/src/Core/utils/triggering.js +167 -0
- package/src/Core/utils/variants.js +477 -0
- package/src/DoenetML.css +308 -0
- package/src/DoenetML.jsx +201 -0
- package/src/Parser/doenet.grammar +90 -0
- package/src/Parser/doenet.js +33 -0
- package/src/Parser/doenet.terms.js +20 -0
- package/src/Parser/parser.js +266 -0
- package/src/Parser/tokens.js +129 -0
- package/src/Tools/CodeMirror.jsx +440 -0
- package/src/Tools/DarkmodeController.jsx +21 -0
- package/src/Tools/Footers/MathInputSelector.jsx +34 -0
- package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
- package/src/Tools/cypressTest/CypressTest.jsx +341 -0
- package/src/Tools/cypressTest/index.html +102 -0
- package/src/Tools/cypressTest/index.jsx +40 -0
- package/src/Viewer/ActivityViewer.jsx +1461 -0
- package/src/Viewer/PageViewer.jsx +1329 -0
- package/src/Viewer/renderers/alert.jsx +17 -0
- package/src/Viewer/renderers/angle.jsx +209 -0
- package/src/Viewer/renderers/answer.jsx +206 -0
- package/src/Viewer/renderers/asList.jsx +25 -0
- package/src/Viewer/renderers/blockQuote.jsx +41 -0
- package/src/Viewer/renderers/boolean.jsx +17 -0
- package/src/Viewer/renderers/booleanInput.css +105 -0
- package/src/Viewer/renderers/booleanInput.jsx +636 -0
- package/src/Viewer/renderers/button.jsx +369 -0
- package/src/Viewer/renderers/c.jsx +17 -0
- package/src/Viewer/renderers/callAction.jsx +18 -0
- package/src/Viewer/renderers/cell.jsx +59 -0
- package/src/Viewer/renderers/chart.jsx +83 -0
- package/src/Viewer/renderers/choiceInput.css +223 -0
- package/src/Viewer/renderers/choiceInput.jsx +535 -0
- package/src/Viewer/renderers/circle.jsx +990 -0
- package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
- package/src/Viewer/renderers/codeEditor.jsx +248 -0
- package/src/Viewer/renderers/codeViewer.jsx +105 -0
- package/src/Viewer/renderers/containerBlock.jsx +41 -0
- package/src/Viewer/renderers/containerInline.jsx +17 -0
- package/src/Viewer/renderers/contentBrowser.jsx +159 -0
- package/src/Viewer/renderers/contentPicker.jsx +160 -0
- package/src/Viewer/renderers/curve.jsx +1072 -0
- package/src/Viewer/renderers/ellipsis.jsx +17 -0
- package/src/Viewer/renderers/em.jsx +17 -0
- package/src/Viewer/renderers/embed.jsx +110 -0
- package/src/Viewer/renderers/feedback.jsx +74 -0
- package/src/Viewer/renderers/figure.jsx +131 -0
- package/src/Viewer/renderers/footnote.jsx +52 -0
- package/src/Viewer/renderers/graph.jsx +925 -0
- package/src/Viewer/renderers/hint.jsx +142 -0
- package/src/Viewer/renderers/image.jsx +581 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
- package/src/Viewer/renderers/label.jsx +470 -0
- package/src/Viewer/renderers/legend.jsx +306 -0
- package/src/Viewer/renderers/line.jsx +511 -0
- package/src/Viewer/renderers/lineSegment.jsx +754 -0
- package/src/Viewer/renderers/list.jsx +111 -0
- package/src/Viewer/renderers/lq.jsx +12 -0
- package/src/Viewer/renderers/lsq.jsx +12 -0
- package/src/Viewer/renderers/math.jsx +582 -0
- package/src/Viewer/renderers/mathInput.css +10 -0
- package/src/Viewer/renderers/mathInput.jsx +425 -0
- package/src/Viewer/renderers/mathInputog.jsx +534 -0
- package/src/Viewer/renderers/mathList.jsx +39 -0
- package/src/Viewer/renderers/matrixInput.jsx +317 -0
- package/src/Viewer/renderers/mdash.jsx +12 -0
- package/src/Viewer/renderers/nbsp.jsx +12 -0
- package/src/Viewer/renderers/ndash.jsx +12 -0
- package/src/Viewer/renderers/number.jsx +454 -0
- package/src/Viewer/renderers/numberList.jsx +35 -0
- package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
- package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
- package/src/Viewer/renderers/p.jsx +38 -0
- package/src/Viewer/renderers/paginatorControls.jsx +41 -0
- package/src/Viewer/renderers/pegboard.jsx +239 -0
- package/src/Viewer/renderers/point.jsx +649 -0
- package/src/Viewer/renderers/polygon.jsx +612 -0
- package/src/Viewer/renderers/polyline.jsx +608 -0
- package/src/Viewer/renderers/pre.jsx +34 -0
- package/src/Viewer/renderers/q.jsx +17 -0
- package/src/Viewer/renderers/ray.jsx +410 -0
- package/src/Viewer/renderers/ref.jsx +149 -0
- package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
- package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
- package/src/Viewer/renderers/row.jsx +31 -0
- package/src/Viewer/renderers/rq.jsx +12 -0
- package/src/Viewer/renderers/rsq.jsx +12 -0
- package/src/Viewer/renderers/section.jsx +427 -0
- package/src/Viewer/renderers/sideBySide.jsx +80 -0
- package/src/Viewer/renderers/slider.jsx +800 -0
- package/src/Viewer/renderers/solution.jsx +134 -0
- package/src/Viewer/renderers/spreadsheet.jsx +83 -0
- package/src/Viewer/renderers/sq.jsx +17 -0
- package/src/Viewer/renderers/styles/global.css +14 -0
- package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
- package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
- package/src/Viewer/renderers/table.jsx +78 -0
- package/src/Viewer/renderers/tabular.jsx +58 -0
- package/src/Viewer/renderers/tag.jsx +26 -0
- package/src/Viewer/renderers/text.jsx +439 -0
- package/src/Viewer/renderers/textInput.jsx +774 -0
- package/src/Viewer/renderers/textList.jsx +30 -0
- package/src/Viewer/renderers/triggerSet.jsx +52 -0
- package/src/Viewer/renderers/updateValue.jsx +30 -0
- package/src/Viewer/renderers/utils/css.js +13 -0
- package/src/Viewer/renderers/utils/graph.js +159 -0
- package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
- package/src/Viewer/renderers/vector.jsx +678 -0
- package/src/Viewer/renderers/video.jsx +494 -0
- package/src/Viewer/useDoenetRenderer.jsx +128 -0
- package/src/main.jsx +16 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/test/testCode.doenet +26 -0
- package/src/test/testViewer.jsx +158 -0
- package/src/uiComponents/ActionButton.jsx +157 -0
- package/src/uiComponents/ActionButtonGroup.jsx +93 -0
- package/src/uiComponents/Button.jsx +160 -0
- package/src/uiComponents/ButtonGroup.jsx +56 -0
- package/src/uiComponents/ToggleButton.jsx +194 -0
- package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
- package/src/utils/activityUtils.js +713 -0
- package/src/utils/array.js +17 -0
- package/src/utils/cid.js +34 -0
- package/src/utils/componentInfoObjects.js +89 -0
- package/src/utils/deepFunctions.js +165 -0
- package/src/utils/enumeration.js +226 -0
- package/src/utils/math.js +624 -0
- package/src/utils/naming.js +44 -0
- package/src/utils/retrieveTextFile.js +156 -0
- package/src/utils/returnAllPossibleVariants.js +81 -0
- package/src/utils/sequence.js +715 -0
- package/src/utils/serialize.js +29 -0
- package/src/utils/serializedStateProcessing.js +2587 -0
- package/src/utils/subset-of-reals.js +783 -0
- package/src/utils/url.js +19 -0
- package/vite.config.js +14 -0
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
import me from "math-expressions";
|
|
2
|
+
import { deepCompare } from "./deepFunctions";
|
|
3
|
+
import { normalizeMathExpression, vectorOperators } from "./math";
|
|
4
|
+
import periodicSetEquality from "./periodicSetEquality";
|
|
5
|
+
|
|
6
|
+
const nonTupleVectorOperators = ["vector", "altvector"];
|
|
7
|
+
|
|
8
|
+
export default function checkEquality({
|
|
9
|
+
object1,
|
|
10
|
+
object2,
|
|
11
|
+
isUnordered = false,
|
|
12
|
+
partialMatches = false,
|
|
13
|
+
matchByExactPositions = false,
|
|
14
|
+
symbolicEquality = false,
|
|
15
|
+
simplify = "none",
|
|
16
|
+
expand = false,
|
|
17
|
+
allowedErrorInNumbers = 0,
|
|
18
|
+
includeErrorInNumberExponents = false,
|
|
19
|
+
allowedErrorIsAbsolute = false,
|
|
20
|
+
numSignErrorsMatched = 0,
|
|
21
|
+
numPeriodicSetMatchesRequired = 3,
|
|
22
|
+
caseInsensitiveMatch = false,
|
|
23
|
+
matchBlanks = false,
|
|
24
|
+
}) {
|
|
25
|
+
/*
|
|
26
|
+
Equality check
|
|
27
|
+
|
|
28
|
+
Types of equality checks
|
|
29
|
+
- numeric check (if symbolicEquality === false) which samples variables
|
|
30
|
+
in complex plane and will return equal if can find open sets
|
|
31
|
+
from which a number of samples return nearly identical results for both objects
|
|
32
|
+
- symbolic equality: requires identical abstract syntax trees,
|
|
33
|
+
possibly after simplification and expand normalizations
|
|
34
|
+
- deep equality for any non math-expression objects
|
|
35
|
+
|
|
36
|
+
Special logic for container elements:
|
|
37
|
+
- math-expression tuples, lists, arrays, vectors, intervals, sets, matrices
|
|
38
|
+
- Javascript arrays
|
|
39
|
+
|
|
40
|
+
- For math-expressions
|
|
41
|
+
* will convert tuples to vectors, open intervals
|
|
42
|
+
* will convert arrays to closed intervals
|
|
43
|
+
* will convert singletons to vectors, sets, tuples, lists, arrays
|
|
44
|
+
|
|
45
|
+
- If isUnordered is set, then check if elements match
|
|
46
|
+
regardless of order.
|
|
47
|
+
- If partialMatches is set, then check if just some elements
|
|
48
|
+
match and return the fraction that match. For ordered objects,
|
|
49
|
+
the matching elements must be in the same order.
|
|
50
|
+
|
|
51
|
+
Return object with
|
|
52
|
+
- fraction_equal: number between 0 and 1
|
|
53
|
+
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
let haveMathExpressions = false;
|
|
57
|
+
|
|
58
|
+
// first check if objects can be converted into the same type of objects
|
|
59
|
+
|
|
60
|
+
if (object1 instanceof me.class) {
|
|
61
|
+
haveMathExpressions = true;
|
|
62
|
+
if (!(object2 instanceof me.class)) {
|
|
63
|
+
// see if convert object2 to a math expression
|
|
64
|
+
if (typeof object2 === "number" || typeof object2 === "string") {
|
|
65
|
+
object2 = me.fromAst(object2);
|
|
66
|
+
} else {
|
|
67
|
+
// return not equal if only one is math-expression
|
|
68
|
+
return { fraction_equal: 0 };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} else if (object2 instanceof me.class) {
|
|
72
|
+
haveMathExpressions = true;
|
|
73
|
+
// see if convert object1 to a math expression
|
|
74
|
+
if (typeof object1 === "number" || typeof object1 === "string") {
|
|
75
|
+
object1 = me.fromAst(object1);
|
|
76
|
+
} else {
|
|
77
|
+
// return not equal if only one is math-expression
|
|
78
|
+
return { fraction_equal: 0 };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let normalize = function (x, forNumeric = false) {
|
|
83
|
+
if (!(x instanceof me.class)) {
|
|
84
|
+
x = me.fromAst(x);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
x = x.normalize_function_names().normalize_applied_functions();
|
|
88
|
+
|
|
89
|
+
if (caseInsensitiveMatch) {
|
|
90
|
+
x = me.fromAst(setStringsInTreeToLowerCase(x.tree));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let effectiveSimplify = simplify,
|
|
94
|
+
effectiveExpand = expand;
|
|
95
|
+
if (forNumeric) {
|
|
96
|
+
effectiveSimplify = "full";
|
|
97
|
+
effectiveExpand = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (effectiveSimplify === "none") {
|
|
101
|
+
if (allowedErrorInNumbers > 0) {
|
|
102
|
+
// only if allowing rounding, do we replace constants with floats
|
|
103
|
+
x = x.constants_to_floats();
|
|
104
|
+
}
|
|
105
|
+
} else if (effectiveSimplify === "numberspreserveorder") {
|
|
106
|
+
x = x.evaluate_numbers({ max_digits: Infinity, skip_ordering: true });
|
|
107
|
+
} else if (effectiveSimplify === "number") {
|
|
108
|
+
x = x.evaluate_numbers({ max_digits: Infinity });
|
|
109
|
+
} else {
|
|
110
|
+
x = x.evaluate_numbers({
|
|
111
|
+
max_digits: Infinity,
|
|
112
|
+
evaluate_functions: true,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return normalizeMathExpression({
|
|
116
|
+
value: x,
|
|
117
|
+
simplify: effectiveSimplify,
|
|
118
|
+
expand: effectiveExpand,
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
let check_equality;
|
|
123
|
+
if (haveMathExpressions) {
|
|
124
|
+
if (symbolicEquality) {
|
|
125
|
+
check_equality = function (a, b) {
|
|
126
|
+
let expr_a = a;
|
|
127
|
+
let expr_b = b;
|
|
128
|
+
if (!(a instanceof me.class)) {
|
|
129
|
+
expr_a = me.fromAst(a);
|
|
130
|
+
}
|
|
131
|
+
if (!(b instanceof me.class)) {
|
|
132
|
+
expr_b = me.fromAst(b);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (numSignErrorsMatched > 0) {
|
|
136
|
+
// We have to make a deep copy
|
|
137
|
+
// because equalSpecifiedSignErrors does in-place changes of ast
|
|
138
|
+
// (and then undoes them)
|
|
139
|
+
// TODO: is this the best solution?
|
|
140
|
+
expr_b = JSON.parse(JSON.stringify(expr_b), me.reviver);
|
|
141
|
+
|
|
142
|
+
let equalityFunction = function (aa, bb) {
|
|
143
|
+
// temporary fix until equalsViaSyntax returns false for \uff3f
|
|
144
|
+
if (
|
|
145
|
+
aa.variables().includes("\uFF3F") ||
|
|
146
|
+
bb.variables().includes("\uFF3F")
|
|
147
|
+
) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
aa = normalize(aa); // only have to normalize aa as that is the one that gets modified
|
|
151
|
+
return aa.equalsViaSyntax(bb, {
|
|
152
|
+
allowed_error_in_numbers: allowedErrorInNumbers,
|
|
153
|
+
include_error_in_number_exponents: includeErrorInNumberExponents,
|
|
154
|
+
allowed_error_is_absolute: allowedErrorIsAbsolute,
|
|
155
|
+
allow_blanks: matchBlanks,
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
// temporary fix to keep complex numbers from crashing math-expressions
|
|
159
|
+
// TODO: handle complex numbers
|
|
160
|
+
if (expr_a.tree.im || expr_b.tree.im) {
|
|
161
|
+
return { fraction_equal: 0 };
|
|
162
|
+
}
|
|
163
|
+
let equality = me.equalSpecifiedSignErrors(expr_b, expr_a, {
|
|
164
|
+
equalityFunction,
|
|
165
|
+
n_sign_errors: numSignErrorsMatched,
|
|
166
|
+
});
|
|
167
|
+
return { fraction_equal: equality ? 1 : 0 };
|
|
168
|
+
} else {
|
|
169
|
+
// temporary fix until equalsViaSyntax returns false for \uff3f
|
|
170
|
+
if (
|
|
171
|
+
expr_a.variables().includes("\uFF3F") ||
|
|
172
|
+
expr_b.variables().includes("\uFF3F")
|
|
173
|
+
) {
|
|
174
|
+
return { fraction_equal: 0 };
|
|
175
|
+
}
|
|
176
|
+
// temporary fix to keep complex numbers from crashing math-expressions
|
|
177
|
+
// TODO: handle complex numbers
|
|
178
|
+
if (expr_a.tree.im || expr_b.tree.im) {
|
|
179
|
+
return { fraction_equal: 0 };
|
|
180
|
+
}
|
|
181
|
+
let equality = expr_a.equalsViaSyntax(expr_b, {
|
|
182
|
+
allowed_error_in_numbers: allowedErrorInNumbers,
|
|
183
|
+
include_error_in_number_exponents: includeErrorInNumberExponents,
|
|
184
|
+
allowed_error_is_absolute: allowedErrorIsAbsolute,
|
|
185
|
+
allow_blanks: matchBlanks,
|
|
186
|
+
});
|
|
187
|
+
return { fraction_equal: equality ? 1 : 0 };
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
} else {
|
|
191
|
+
check_equality = function (a, b) {
|
|
192
|
+
let expr_a = a;
|
|
193
|
+
let expr_b = b;
|
|
194
|
+
if (!(a instanceof me.class)) {
|
|
195
|
+
expr_a = me.fromAst(a);
|
|
196
|
+
}
|
|
197
|
+
if (!(b instanceof me.class)) {
|
|
198
|
+
expr_b = me.fromAst(b);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (caseInsensitiveMatch) {
|
|
202
|
+
expr_a = me.fromAst(setStringsInTreeToLowerCase(expr_a.tree));
|
|
203
|
+
expr_b = me.fromAst(setStringsInTreeToLowerCase(expr_b.tree));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// let aIsPeriodicSet = Array.isArray(a) && a[0] === "periodic_set";
|
|
207
|
+
// let bIsPeriodicSet = Array.isArray(b) && b[0] === "periodic_set";
|
|
208
|
+
|
|
209
|
+
// console.log(expr_a, expr_b)
|
|
210
|
+
|
|
211
|
+
// if (aIsPeriodicSet || bIsPeriodicSet) {
|
|
212
|
+
// let set1 = expr_a, set2 = expr_b;
|
|
213
|
+
// if (!aIsPeriodicSet) {
|
|
214
|
+
// set1 = expr_b;
|
|
215
|
+
// set2 = expr_a;
|
|
216
|
+
// }
|
|
217
|
+
|
|
218
|
+
// let equality = periodicSetEquality(set1, set2, { match_partial: partialMatches });
|
|
219
|
+
|
|
220
|
+
// if (equality === true) {
|
|
221
|
+
// return { fraction_equal: 1 };
|
|
222
|
+
// } else if (equality === false) {
|
|
223
|
+
// return { fraction_equal: 0 };
|
|
224
|
+
// } else {
|
|
225
|
+
// return { fraction_equal: equality };
|
|
226
|
+
// }
|
|
227
|
+
|
|
228
|
+
// }
|
|
229
|
+
|
|
230
|
+
if (numSignErrorsMatched > 0) {
|
|
231
|
+
// We have to make a deep copy
|
|
232
|
+
// because equalSpecifiedSignErrors does in-place changes of ast
|
|
233
|
+
// (and then undoes them)
|
|
234
|
+
// TODO: is this the best solution?
|
|
235
|
+
expr_b = JSON.parse(JSON.stringify(expr_b), me.reviver);
|
|
236
|
+
let equalityFunction = function (aa, bb) {
|
|
237
|
+
return aa.equals(bb, {
|
|
238
|
+
allowed_error_in_numbers: allowedErrorInNumbers,
|
|
239
|
+
include_error_in_number_exponents: includeErrorInNumberExponents,
|
|
240
|
+
allowed_error_is_absolute: allowedErrorIsAbsolute,
|
|
241
|
+
allow_blanks: matchBlanks,
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
// temporary fix to keep complex numbers from crashing math-expressions
|
|
245
|
+
// TODO: handle complex numbers
|
|
246
|
+
if (expr_a.tree.im || expr_b.tree.im) {
|
|
247
|
+
return { fraction_equal: 0 };
|
|
248
|
+
}
|
|
249
|
+
let equality = me.equalSpecifiedSignErrors(expr_b, expr_a, {
|
|
250
|
+
equalityFunction,
|
|
251
|
+
n_sign_errors: numSignErrorsMatched,
|
|
252
|
+
});
|
|
253
|
+
return { fraction_equal: equality ? 1 : 0 };
|
|
254
|
+
} else {
|
|
255
|
+
// temporary fix to keep complex numbers from crashing math-expressions
|
|
256
|
+
// TODO: handle complex numbers
|
|
257
|
+
if (expr_a.tree.im || expr_b.tree.im) {
|
|
258
|
+
return { fraction_equal: 0 };
|
|
259
|
+
}
|
|
260
|
+
let equality = expr_a.equals(expr_b, {
|
|
261
|
+
allowed_error_in_numbers: allowedErrorInNumbers,
|
|
262
|
+
include_error_in_number_exponents: includeErrorInNumberExponents,
|
|
263
|
+
allowed_error_is_absolute: allowedErrorIsAbsolute,
|
|
264
|
+
allow_blanks: matchBlanks,
|
|
265
|
+
});
|
|
266
|
+
return { fraction_equal: equality ? 1 : 0 };
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
check_equality = (a, b) => {
|
|
272
|
+
if (caseInsensitiveMatch) {
|
|
273
|
+
a = convertStringsToLowerCase(a);
|
|
274
|
+
b = convertStringsToLowerCase(b);
|
|
275
|
+
}
|
|
276
|
+
return { fraction_equal: deepCompare(a, b) ? 1 : 0 };
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let partialMatchesOnRecursion = false;
|
|
281
|
+
let matchByExactPositionsOnRecursion = false;
|
|
282
|
+
|
|
283
|
+
if (haveMathExpressions) {
|
|
284
|
+
// normalize at the beginning so that expand vectors, etc.
|
|
285
|
+
object1 = normalize(object1, !symbolicEquality);
|
|
286
|
+
object2 = normalize(object2, !symbolicEquality);
|
|
287
|
+
|
|
288
|
+
// if can convert same type of math-expression
|
|
289
|
+
// change object1 and object2 to array of asts
|
|
290
|
+
// otherwise return that are unequal
|
|
291
|
+
|
|
292
|
+
let object1_operator = object1.tree[0];
|
|
293
|
+
let object2_operator = object2.tree[0];
|
|
294
|
+
|
|
295
|
+
if (
|
|
296
|
+
object1_operator === "periodic_set" ||
|
|
297
|
+
object2_operator === "periodic_set"
|
|
298
|
+
) {
|
|
299
|
+
let set1 = object1,
|
|
300
|
+
set2 = object2;
|
|
301
|
+
if (object1_operator !== "periodic_set") {
|
|
302
|
+
set1 = object2;
|
|
303
|
+
set2 = object1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
let equality = periodicSetEquality(set1, set2, {
|
|
307
|
+
match_partial: partialMatches,
|
|
308
|
+
min_elements_match: numPeriodicSetMatchesRequired,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
if (equality === true) {
|
|
312
|
+
return { fraction_equal: 1 };
|
|
313
|
+
} else if (equality === false) {
|
|
314
|
+
return { fraction_equal: 0 };
|
|
315
|
+
} else {
|
|
316
|
+
return { fraction_equal: equality };
|
|
317
|
+
}
|
|
318
|
+
} else if (object1_operator === "list") {
|
|
319
|
+
object1 = object1.tree.slice(1);
|
|
320
|
+
if (object2_operator === "list") {
|
|
321
|
+
object2 = object2.tree.slice(1);
|
|
322
|
+
} else {
|
|
323
|
+
// since a single object could be considered
|
|
324
|
+
// a list of length 1
|
|
325
|
+
// make object2 act like a list of the one element
|
|
326
|
+
object2 = [object2.tree];
|
|
327
|
+
}
|
|
328
|
+
} else if (object2_operator === "list") {
|
|
329
|
+
object2 = object2.tree.slice(1);
|
|
330
|
+
// since a single object could be considered
|
|
331
|
+
// a list of length 1
|
|
332
|
+
// make object1 act like a list of the one element
|
|
333
|
+
object1 = [object1.tree];
|
|
334
|
+
} else if (nonTupleVectorOperators.includes(object1_operator)) {
|
|
335
|
+
// change object1 to array of elements
|
|
336
|
+
object1 = object1.tree.slice(1);
|
|
337
|
+
|
|
338
|
+
if (
|
|
339
|
+
object2_operator === "interval" ||
|
|
340
|
+
object2_operator === "matrix" ||
|
|
341
|
+
object2_operator === "array" ||
|
|
342
|
+
object2_operator === "set"
|
|
343
|
+
) {
|
|
344
|
+
return { fraction_equal: 0 };
|
|
345
|
+
} else if (vectorOperators.includes(object2_operator)) {
|
|
346
|
+
// since we can convert tuple to vector
|
|
347
|
+
// change object2 to array of selements
|
|
348
|
+
object2 = object2.tree.slice(1);
|
|
349
|
+
} else {
|
|
350
|
+
// since can convert singleton to a vector of length 1
|
|
351
|
+
// make object2 array of the one element
|
|
352
|
+
object2 = [object2.tree];
|
|
353
|
+
}
|
|
354
|
+
} else if (nonTupleVectorOperators.includes(object2_operator)) {
|
|
355
|
+
// change object2 to array of elements
|
|
356
|
+
object2 = object2.tree.slice(1);
|
|
357
|
+
|
|
358
|
+
if (
|
|
359
|
+
object1_operator === "interval" ||
|
|
360
|
+
object1_operator === "matrix" ||
|
|
361
|
+
object1_operator === "array" ||
|
|
362
|
+
object1_operator === "set"
|
|
363
|
+
) {
|
|
364
|
+
return { fraction_equal: 0 };
|
|
365
|
+
} else if (object1_operator === "tuple") {
|
|
366
|
+
// since can convert tuple to vector
|
|
367
|
+
// change object2 to array of elements
|
|
368
|
+
object1 = object1.tree.slice(1);
|
|
369
|
+
} else {
|
|
370
|
+
// since can convert singleton to a vector of length 1
|
|
371
|
+
// make object1 array of the one element
|
|
372
|
+
object1 = [object1.tree];
|
|
373
|
+
}
|
|
374
|
+
} else if (object1_operator === "interval") {
|
|
375
|
+
matchByExactPositions = true;
|
|
376
|
+
|
|
377
|
+
let closedInfo = object1.tree[2];
|
|
378
|
+
let leftClosed = closedInfo[1];
|
|
379
|
+
let rightClosed = closedInfo[2];
|
|
380
|
+
|
|
381
|
+
// change object to be the array of the interval endpoints
|
|
382
|
+
object1 = object1.tree[1].slice(1);
|
|
383
|
+
|
|
384
|
+
if (object2_operator === "matrix" || object2_operator === "set") {
|
|
385
|
+
return { fraction_equal: 0 };
|
|
386
|
+
} else if (object2_operator === "tuple") {
|
|
387
|
+
let operands = object2.tree.slice(1);
|
|
388
|
+
if (
|
|
389
|
+
operands.length === 2 &&
|
|
390
|
+
leftClosed === false &&
|
|
391
|
+
rightClosed === false
|
|
392
|
+
) {
|
|
393
|
+
// since can convert tuple to open interval
|
|
394
|
+
// and object1 is open interval
|
|
395
|
+
// make object2 be array of endpoints
|
|
396
|
+
object2 = operands;
|
|
397
|
+
} else {
|
|
398
|
+
return { fraction_equal: 0 };
|
|
399
|
+
}
|
|
400
|
+
} else if (object2_operator === "array") {
|
|
401
|
+
let operands = object2.tree.slice(1);
|
|
402
|
+
if (
|
|
403
|
+
operands.length === 2 &&
|
|
404
|
+
leftClosed === true &&
|
|
405
|
+
rightClosed === true
|
|
406
|
+
) {
|
|
407
|
+
// since can convert array to closed interval
|
|
408
|
+
// and object1 is closed interval
|
|
409
|
+
// make object2 be array of endpoints
|
|
410
|
+
object2 = operands;
|
|
411
|
+
} else {
|
|
412
|
+
return { fraction_equal: 0 };
|
|
413
|
+
}
|
|
414
|
+
} else if (object2_operator === "interval") {
|
|
415
|
+
let closedInfo2 = object2.tree[2];
|
|
416
|
+
if (closedInfo2[1] !== leftClosed || closedInfo2[2] !== rightClosed) {
|
|
417
|
+
return { fraction_equal: 0 };
|
|
418
|
+
}
|
|
419
|
+
// convert object2 to array of endpoints
|
|
420
|
+
object2 = object2.tree[1].slice(1);
|
|
421
|
+
} else {
|
|
422
|
+
// can't convert anything else to interval
|
|
423
|
+
return { fraction_equal: 0 };
|
|
424
|
+
}
|
|
425
|
+
} else if (object2_operator === "interval") {
|
|
426
|
+
matchByExactPositions = true;
|
|
427
|
+
|
|
428
|
+
let closedInfo = object2.tree[2];
|
|
429
|
+
let leftClosed = closedInfo[1];
|
|
430
|
+
let rightClosed = closedInfo[2];
|
|
431
|
+
|
|
432
|
+
// change object to be the array of the interval endpoints
|
|
433
|
+
object2 = object2.tree[1].slice(1);
|
|
434
|
+
|
|
435
|
+
if (object1_operator === "matrix" || object1_operator === "set") {
|
|
436
|
+
return { fraction_equal: 0 };
|
|
437
|
+
} else if (object1_operator === "tuple") {
|
|
438
|
+
let operands = object1.tree.slice(1);
|
|
439
|
+
if (
|
|
440
|
+
operands.length === 2 &&
|
|
441
|
+
leftClosed === false &&
|
|
442
|
+
rightClosed === false
|
|
443
|
+
) {
|
|
444
|
+
// since can convert tuple to open interval
|
|
445
|
+
// and object2 is open interval
|
|
446
|
+
// make object1 be array of endpoints
|
|
447
|
+
object1 = operands;
|
|
448
|
+
} else {
|
|
449
|
+
return { fraction_equal: 0 };
|
|
450
|
+
}
|
|
451
|
+
} else if (object1_operator === "array") {
|
|
452
|
+
let operands = object1.tree.slice(1);
|
|
453
|
+
if (
|
|
454
|
+
operands.length === 2 &&
|
|
455
|
+
leftClosed === true &&
|
|
456
|
+
rightClosed === true
|
|
457
|
+
) {
|
|
458
|
+
// since can convert array to closed interval
|
|
459
|
+
// and object2 is closed interval
|
|
460
|
+
// make object1 be array of endpoints
|
|
461
|
+
object1 = operands;
|
|
462
|
+
} else {
|
|
463
|
+
return { fraction_equal: 0 };
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
// can't convert anything else to interval
|
|
467
|
+
return { fraction_equal: 0 };
|
|
468
|
+
}
|
|
469
|
+
} else if (object1_operator === "matrix") {
|
|
470
|
+
if (object2_operator === "matrix") {
|
|
471
|
+
// convert to array of matrix rows
|
|
472
|
+
|
|
473
|
+
object1 = convertMatrixToArrayOfTuples(object1.tree.slice(1));
|
|
474
|
+
object2 = convertMatrixToArrayOfTuples(object2.tree.slice(1));
|
|
475
|
+
|
|
476
|
+
matchByExactPositions = true;
|
|
477
|
+
matchByExactPositionsOnRecursion = true;
|
|
478
|
+
partialMatchesOnRecursion = true;
|
|
479
|
+
} else {
|
|
480
|
+
return { fraction_equal: 0 };
|
|
481
|
+
}
|
|
482
|
+
} else if (object2_operator === "matrix") {
|
|
483
|
+
return { fraction_equal: 0 };
|
|
484
|
+
} else if (object1_operator === "set") {
|
|
485
|
+
let distinctElements = [];
|
|
486
|
+
for (let v of object1.tree.slice(1)) {
|
|
487
|
+
// if v doesn't match any previous elements, add to array
|
|
488
|
+
if (
|
|
489
|
+
!distinctElements.some(
|
|
490
|
+
(x) => check_equality(x, v).fraction_equal === 1,
|
|
491
|
+
)
|
|
492
|
+
) {
|
|
493
|
+
distinctElements.push(v);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
object1 = distinctElements;
|
|
497
|
+
isUnordered = true;
|
|
498
|
+
if (object2_operator === "tuple" || object2_operator === "array") {
|
|
499
|
+
return { fraction_equal: 0 };
|
|
500
|
+
} else if (object2_operator === "set") {
|
|
501
|
+
distinctElements = [];
|
|
502
|
+
for (let v of object2.tree.slice(1)) {
|
|
503
|
+
// if v doesn't match any previous elements, add to array
|
|
504
|
+
if (
|
|
505
|
+
!distinctElements.some(
|
|
506
|
+
(x) => check_equality(x, v).fraction_equal === 1,
|
|
507
|
+
)
|
|
508
|
+
) {
|
|
509
|
+
distinctElements.push(v);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
object2 = distinctElements;
|
|
513
|
+
} else {
|
|
514
|
+
// since can convert singleton to a set of length 1
|
|
515
|
+
// make object2 array of the one element
|
|
516
|
+
object2 = [object2.tree];
|
|
517
|
+
}
|
|
518
|
+
} else if (object2_operator === "set") {
|
|
519
|
+
let distinctElements = [];
|
|
520
|
+
for (let v of object2.tree.slice(1)) {
|
|
521
|
+
// if v doesn't match any previous elements, add to array
|
|
522
|
+
if (
|
|
523
|
+
!distinctElements.some(
|
|
524
|
+
(x) => check_equality(x, v).fraction_equal === 1,
|
|
525
|
+
)
|
|
526
|
+
) {
|
|
527
|
+
distinctElements.push(v);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
object2 = distinctElements;
|
|
531
|
+
isUnordered = true;
|
|
532
|
+
if (object1_operator === "tuple" || object1_operator === "array") {
|
|
533
|
+
return { fraction_equal: 0 };
|
|
534
|
+
} else {
|
|
535
|
+
// since can convert singleton to a set of length 1
|
|
536
|
+
// make object1 array of the one element
|
|
537
|
+
object1 = [object1.tree];
|
|
538
|
+
}
|
|
539
|
+
} else if (object1_operator === "tuple") {
|
|
540
|
+
object1 = object1.tree.slice(1);
|
|
541
|
+
if (object2_operator === "array") {
|
|
542
|
+
return { fraction_equal: 0 };
|
|
543
|
+
} else if (object2_operator === "tuple") {
|
|
544
|
+
object2 = object2.tree.slice(1);
|
|
545
|
+
} else {
|
|
546
|
+
// since can convert singleton to a tuple of length 1
|
|
547
|
+
// make object2 array of the one element
|
|
548
|
+
object2 = [object2.tree];
|
|
549
|
+
}
|
|
550
|
+
} else if (object2_operator === "tuple") {
|
|
551
|
+
object2 = object2.tree.slice(1);
|
|
552
|
+
if (object1_operator === "array") {
|
|
553
|
+
return { fraction_equal: 0 };
|
|
554
|
+
} else {
|
|
555
|
+
// since can convert singleton to a tuple of length 1
|
|
556
|
+
// make object1 array of the one element
|
|
557
|
+
object1 = [object1.tree];
|
|
558
|
+
}
|
|
559
|
+
} else if (object1_operator === "array") {
|
|
560
|
+
object1 = object1.tree.slice(1);
|
|
561
|
+
if (object2_operator === "array") {
|
|
562
|
+
object2 = object2.tree.slice(1);
|
|
563
|
+
} else {
|
|
564
|
+
// since can convert singleton to an array of length 1
|
|
565
|
+
// make object2 array of the one element
|
|
566
|
+
object2 = [object2.tree];
|
|
567
|
+
}
|
|
568
|
+
} else if (object2_operator === "array") {
|
|
569
|
+
object2 = object2.tree.slice(1);
|
|
570
|
+
// since can convert singleton to an array of length 1
|
|
571
|
+
// make object1 array of the one element
|
|
572
|
+
object1 = [object1.tree];
|
|
573
|
+
} else {
|
|
574
|
+
// neither object is a container type, just return usual equality
|
|
575
|
+
return check_equality(object1.tree, object2.tree);
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
// don't have math expression, just see if have an array of objects
|
|
579
|
+
if (Array.isArray(object1)) {
|
|
580
|
+
if (!Array.isArray(object2)) {
|
|
581
|
+
// if object1 is an array of strings with no commas
|
|
582
|
+
// and object2 is a string,
|
|
583
|
+
// split object2 by commas
|
|
584
|
+
if (
|
|
585
|
+
typeof object2 === "string" &&
|
|
586
|
+
object1.every((x) => typeof x === "string" && !x.includes(","))
|
|
587
|
+
) {
|
|
588
|
+
object2 = object2.split(",").map((x) => x.trim());
|
|
589
|
+
} else {
|
|
590
|
+
// otherwise convert object2 to array of one element
|
|
591
|
+
object2 = [object2];
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
} else if (Array.isArray(object2)) {
|
|
595
|
+
// if object2 is an array of strings with no commas
|
|
596
|
+
// and object1 is a string,
|
|
597
|
+
// split object1 by commas
|
|
598
|
+
if (
|
|
599
|
+
typeof object1 === "string" &&
|
|
600
|
+
object2.every((x) => typeof x === "string" && !x.includes(","))
|
|
601
|
+
) {
|
|
602
|
+
object1 = object1.split(",").map((x) => x.trim());
|
|
603
|
+
} else {
|
|
604
|
+
// otherwise convert object1 to array of one element
|
|
605
|
+
object1 = [object1];
|
|
606
|
+
}
|
|
607
|
+
} else {
|
|
608
|
+
// non-array. Just return if same object
|
|
609
|
+
return check_equality(object1, object2);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
let nelts1 = object1.length;
|
|
614
|
+
let nelts2 = object2.length;
|
|
615
|
+
|
|
616
|
+
let results = { fraction_equal: 0 };
|
|
617
|
+
|
|
618
|
+
if (matchByExactPositions) {
|
|
619
|
+
isUnordered = false;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// if isUnordered isn't set, demand exact equality
|
|
623
|
+
if (!isUnordered) {
|
|
624
|
+
// check how many elements match in order from the beginning
|
|
625
|
+
let n_matches = 0;
|
|
626
|
+
|
|
627
|
+
let minN = Math.min(nelts1, nelts2);
|
|
628
|
+
for (let i = 0; i < minN; i++) {
|
|
629
|
+
let sub_results = checkEquality({
|
|
630
|
+
object1: me.fromAst(object1[i]),
|
|
631
|
+
object2: me.fromAst(object2[i]),
|
|
632
|
+
isUnordered: false,
|
|
633
|
+
partialMatches: partialMatchesOnRecursion,
|
|
634
|
+
matchByExactPositions: matchByExactPositionsOnRecursion,
|
|
635
|
+
symbolicEquality,
|
|
636
|
+
simplify,
|
|
637
|
+
expand,
|
|
638
|
+
allowedErrorInNumbers,
|
|
639
|
+
allowedErrorIsAbsolute,
|
|
640
|
+
numSignErrorsMatched,
|
|
641
|
+
numPeriodicSetMatchesRequired,
|
|
642
|
+
caseInsensitiveMatch,
|
|
643
|
+
matchBlanks,
|
|
644
|
+
});
|
|
645
|
+
n_matches += sub_results.fraction_equal;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
//if object lengths are equal and all match, then exact equality
|
|
649
|
+
if (nelts1 === nelts2 && nelts1 === n_matches) {
|
|
650
|
+
results["fraction_equal"] = 1;
|
|
651
|
+
return results;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (!partialMatches) {
|
|
655
|
+
return results; // return failure
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// if match_exact locations, get partial credit only
|
|
659
|
+
// from matching entries in same locations
|
|
660
|
+
if (matchByExactPositions) {
|
|
661
|
+
results["fraction_equal"] = n_matches / Math.max(nelts1, nelts2);
|
|
662
|
+
return results;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// if partial matches, find length of largest common subsequence
|
|
666
|
+
|
|
667
|
+
// C is a matrix where the [i][j] element represents the best
|
|
668
|
+
// score achieved from a subsequence using
|
|
669
|
+
// the first i components of object1 and
|
|
670
|
+
// the first j components of object2
|
|
671
|
+
// In the end C[nelts1][nelts2] will be the total score
|
|
672
|
+
|
|
673
|
+
// 2D array of zeros from https://stackoverflow.com/a/46792350
|
|
674
|
+
let C = Array.from(Array(nelts1 + 1), (_) => Array(nelts2 + 1).fill(0));
|
|
675
|
+
|
|
676
|
+
for (let i = 0; i < nelts1; i++) {
|
|
677
|
+
for (let j = 0; j < nelts2; j++) {
|
|
678
|
+
let sub_results = checkEquality({
|
|
679
|
+
object1: me.fromAst(object1[i]),
|
|
680
|
+
object2: me.fromAst(object2[j]),
|
|
681
|
+
isUnordered: false,
|
|
682
|
+
partialMatches: partialMatchesOnRecursion,
|
|
683
|
+
matchByExactPositions: matchByExactPositionsOnRecursion,
|
|
684
|
+
symbolicEquality,
|
|
685
|
+
simplify,
|
|
686
|
+
expand,
|
|
687
|
+
allowedErrorInNumbers,
|
|
688
|
+
allowedErrorIsAbsolute,
|
|
689
|
+
numSignErrorsMatched,
|
|
690
|
+
numPeriodicSetMatchesRequired,
|
|
691
|
+
caseInsensitiveMatch,
|
|
692
|
+
matchBlanks,
|
|
693
|
+
});
|
|
694
|
+
C[i + 1][j + 1] = Math.max(
|
|
695
|
+
C[i][j] + sub_results.fraction_equal,
|
|
696
|
+
C[i + 1][j],
|
|
697
|
+
C[i][j + 1],
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
let max_matched = C[nelts1][nelts2];
|
|
703
|
+
|
|
704
|
+
results["fraction_equal"] = max_matched / Math.max(nelts1, nelts2);
|
|
705
|
+
|
|
706
|
+
return results;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// if not ordered, check if match with any order
|
|
710
|
+
|
|
711
|
+
// loop through all elements of tuple 1
|
|
712
|
+
// for each element, look for a matching element of tuple 2
|
|
713
|
+
// that has not been used yet.
|
|
714
|
+
let object2_indices_used = new Set();
|
|
715
|
+
let n_matches = 0;
|
|
716
|
+
for (let expr1 of object1) {
|
|
717
|
+
let best_match_ind = -1;
|
|
718
|
+
let best_match = 0;
|
|
719
|
+
|
|
720
|
+
for (let [i, expr2] of object2.entries()) {
|
|
721
|
+
if (object2_indices_used.has(i)) {
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
let sub_results = checkEquality({
|
|
726
|
+
object1: me.fromAst(expr1),
|
|
727
|
+
object2: me.fromAst(expr2),
|
|
728
|
+
isUnordered: false,
|
|
729
|
+
partialMatches: partialMatchesOnRecursion,
|
|
730
|
+
matchByExactPositions: matchByExactPositionsOnRecursion,
|
|
731
|
+
symbolicEquality,
|
|
732
|
+
simplify,
|
|
733
|
+
expand,
|
|
734
|
+
allowedErrorInNumbers,
|
|
735
|
+
allowedErrorIsAbsolute,
|
|
736
|
+
numSignErrorsMatched,
|
|
737
|
+
numPeriodicSetMatchesRequired,
|
|
738
|
+
caseInsensitiveMatch,
|
|
739
|
+
matchBlanks,
|
|
740
|
+
});
|
|
741
|
+
if (sub_results.fraction_equal > best_match) {
|
|
742
|
+
best_match = sub_results.fraction_equal;
|
|
743
|
+
best_match_ind = i;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
if (best_match_ind !== -1) {
|
|
748
|
+
n_matches += best_match;
|
|
749
|
+
object2_indices_used.add(best_match_ind);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (nelts1 === nelts2 && nelts1 === n_matches) {
|
|
754
|
+
results["fraction_equal"] = 1;
|
|
755
|
+
return results;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (!partialMatches) {
|
|
759
|
+
return results;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
results["fraction_equal"] = n_matches / Math.max(nelts1, nelts2);
|
|
763
|
+
|
|
764
|
+
return results;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
function setStringsInTreeToLowerCase(tree) {
|
|
768
|
+
if (typeof tree === "string") {
|
|
769
|
+
return tree.toLowerCase();
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
if (!Array.isArray(tree)) {
|
|
773
|
+
return tree;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
return [tree[0], ...tree.slice(1).map(setStringsInTreeToLowerCase)];
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function convertStringsToLowerCase(x) {
|
|
780
|
+
if (typeof x === "string") {
|
|
781
|
+
return x.toLowerCase();
|
|
782
|
+
}
|
|
783
|
+
if (!Array.isArray(x)) {
|
|
784
|
+
return x;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return x.map(convertStringsToLowerCase);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function convertMatrixToArrayOfTuples(matrixOperands) {
|
|
791
|
+
// remove any entries not within specified size
|
|
792
|
+
// and pad with \uff3f for any missing entries
|
|
793
|
+
|
|
794
|
+
let numRows = matrixOperands[0][1];
|
|
795
|
+
let numColumns = matrixOperands[0][2];
|
|
796
|
+
if (!(Number.isInteger(numRows) && Number.isInteger(numColumns))) {
|
|
797
|
+
return matrixOperands;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
let result = [];
|
|
801
|
+
|
|
802
|
+
for (let rowInd = 0; rowInd < numRows; rowInd++) {
|
|
803
|
+
let row = ["tuple"];
|
|
804
|
+
let rowOperands = matrixOperands[1][rowInd + 1] || [];
|
|
805
|
+
|
|
806
|
+
for (let colInd = 0; colInd < numColumns; colInd++) {
|
|
807
|
+
let val = rowOperands[colInd + 1];
|
|
808
|
+
if (val === undefined || val === null) {
|
|
809
|
+
val = "\uff3f";
|
|
810
|
+
}
|
|
811
|
+
row.push(val);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
result.push(row);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
return result;
|
|
818
|
+
}
|