Showing posts with label Equal. Show all posts
Showing posts with label Equal. Show all posts

Friday, April 11, 2014

More Complex Predicates: allOddQ, allIdenticalQ, subsetQ

"Mr Wizard Todd", Manfred Plagmann, and Sophia Scheibe have done Mathematica users a nice favor by getting permission from McGraw-Hill to distribute licensed copies of David Wagner' s superb book, Power Programming in Mathematica. (Dropbox link: https://www.dropbox.com/s/j2dsyvptnxjd369/Wagner%20All%20Parts-RC.pdf)

A related post is How to See the Equivalence of Select and Cases.

Here are some nice examples of predicates from Wagner (re - written in my Prefix/Postfix dialect).Test a list to see if all of its entries are odd integers.

allOdd@aList_List:=Length@Select[aList,OddQ]==Length@aList

allOdd@{2,3,5,6}

False

allOdd@{3,5,7,9}

True

This predicate tests a List to see if its parts are identical. Count returns all Parts that are Equal to the First Part.

identicalListPartsQ@aList_List:=Count[aList, First@aList] == Length@aList

identicalListPartsQ@{a,b,c,4}

False

identicalListPartsQ@{a,a,a,a}

True

SameQ vs. Equal  and Testing for Lists

SubsetQ determines if its first argument is a subset of its second argument and returns True or False. Wagner's function did not include a List test and he notes on Equal vs.SameQ : "The use of === rather than == makes SubsetQ return False if either set1 or set2 is not a list. Try it with Equal."

I use the Head test: set1_List, which rejects a non-List argument before evaluation. And more importantly, SameQ should always be used to test non-numerical equivalence. In fact using Equal here can give screwy results in part because of its usage as the mathematical "equals" (=) in Mathematica's syntax for equations.

When using abbreviated operators, we should first determine their Precedence:

Precedence/@{Union,Equal,SameQ}

{300.,290.,290.}

Since Union is slightly stickier than SameQ, the Union will be performed before the SameQ test.

subsetQ[set1_,set2_]:=set1∪set2===set2

subsetQ[{a,b,c},{a,b,d}]

False

subsetQ[{a,b},{a,b,2}]

False

Union Sorts Its Result

Whoops! Wagner's function didn't work. Let's find out why:

subsetQ[{a,b},{a,b,2}]//Trace

{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}==={a,b,2},{{a,b}∪{a,b,2},{2,a,b}},{2,a,b}==={a,b,2},False}

The fact that Union returns a sorted List fouls up the comparison. Let's try a fix with Sort:

Clear@subsetQ;subsetQ[set1_,set2_]:=set1∪set2===Sort@set2

And it works - you see in the last step Sort fixes the order.

subsetQ[{a,b},{a,b,2}]//Trace

{subsetQ[{a,b},{a,b,2}],{a,b}∪{a,b,2}===Sort[{a,b,2}],{{a,b}∪{a,b,2},{2,a,b}},{Sort[{a,b,2}],{2,a,b}},{2,a,b}==={2,a,b},True}

Greater (>) is a "non-Q" predicate so the last statement (lacking a return-suppressing semi-colon), returns True or False.

More on predicates: http://mathematica-guide.blogspot.com/2015/07/how-to-see-equivalence-of-select-and.html

Create Predicates to Test Strings vs Numerics: Test for File Extensions

Elsewhere I tell why predicates are important to use, show how to find all predicates in Mathematica including ones not suffixed with "Q", and create ones of your own to test numerical expressions. Here I cover predicates for testing Strings, and create some tests for file types, as judged by their extensions. Note that FileExtension does not capture the period before the extension.

Equal (==) and SameQ (===) are valid predicates for Strings as well as numerics, and work fine for simple applications.

In[206]:= uncusFileQ@fileName_String := FileExtension@fileName == "unc"

In[207]:= uncusFileQ@"afile.unc"

Out[207]= True

In[208]:= uncusFileQ@"afile.txt"

Out[208]= False

In[209]:= textFileQ@fileName_String := FileExtension@fileName == "txt"

In[215]:= textFileQ@"sampleFile.txt"

Out[215]= True

To test for two alternative file extensions is a little trickier. Since we are testing for String equivalence between String patterns, we use the general String predicate function StringMatchQ and Alternatives (|), not logical Or (||). An example is testing for HTML files, since their extensions come in .htm and .html flavors.

In[210]:= Clear@htmlFileQ;
htmlFileQ@fileName_String := StringMatchQ[FileExtension@fileName, "html" | "htm"]

In[212]:= htmlFileQ@"www.jognog.com/index.html"

Out[212]= True

In[213]:= htmlFileQ@"www.jognog.com/index.htm"

Out[213]= True

In[214]:= htmlFileQ@"www.jognog.com/sitemap.xml"

Out[214]= False


Monday, January 2, 2012

Predicates, Tests and Test Patterns: NumberQ, NumericQ, Equal, SameQ

NumberQ and NumericQ

NumberQ is more restrictive than NumericQ and seems to be True only if the evaluated expression is explicitly a number, while NumericQ tests for a "numeric quantity," which seems to mean that Mathematica tests each component to see if its fully evaluated form is a number. NumberQ probably also contains exceptions that should be considered "numeric," for instance all of the built-in numerical constants. More Predicates are implicit in built-in defined sets, such as Rationals and Reals (see below).

NumberQ@3.14159

True

NumberQ@Pi

False

NumericQ@Pi

True

NumberQ@Sqrt@2

False

Both Predicates will test a compound expression, but only NumericQ will test the fully evaluated form of each component. If any component evaluates False by NumberQ, the whole expression evaluates as False.

NumberQ[Sqrt@2 + 5]

False

NumericQ[Sqrt@2 + 5]

True

NumberQ@Sin@Sqrt@2

False

Since in the end the sine of the square root of 2 evaluates to a Real, NumericQ tests it as True; in effect it's testing 0.987766, while NumberQ cannot see the evaluated form.

Sin@Sqrt@2 // N

0.987766

NumericQ@Sin@Sqrt@2

True

Equal (==) and SameQ (===)

The distinction between these two Predicates can be confusing, but the basic idea is Equal tests for numeric equality while SameQ tests for syntactical equality. There are subtleties; here Mathematica compares Pi using its internal storage form.

N[Pi, 4] == N[Pi, 6]

True

However if we compare explicitly different numbers Equal will return False.

3.141 == 3.14159

False

SameQ will pick up syntactic differences that Equal misses.

Pi === N[Pi, 5]

False

Here is a nice example from a good introduction to Mathematica by Nancy Blachman and Colin Williams of using SameQ to test syntax in a paradigm for testing user input for a correctness (Mathematica, A Practical Introduction, 2nd ed., p 433, syntax modifications mine).

testUser1[question_, correctAnswer_] :=
 Module[{userAnswer = Input@question},
  If[userAnswer === correctAnswer, Print@"Correct!",
   Print["You said ", userAnswer, " but the correct answer is ",
    correctAnswer] ]
  ]


testUser1["What is Newton's second law of motion?", f = ma]

Correct!

It is easy to see how using Equal or StringMatchQ would give different tests for equality ("What is the square root of 2?") or an exact string match ("What is the largest continent?") in user input.

Part 3 will show how to build and use your own user-defined Predicates.