Showing posts with label MatchQ. Show all posts
Showing posts with label MatchQ. Show all posts

Thursday, February 4, 2016

Wolfram Language Attribute: OneIdentity

Attributes modify the behavior of entire classes of functions. Some Attributes cause functions to have well-known mathematical properties such as commutativity, associativity, or idempotency, notably for valid pattern-matching. Others control the way the Wolfram Language evaluates or does not evaluate a function's arguments, which if you study that you will see is at the very core of Wolfram Language operation.

Listable is a valuable functional language Attribute since it incorporates Thread into a function so it automatically maps over a List and instead of taking a List apart, we apply a function to it as a gestalt.

NumericFunction is an Attribute of all Wolfram Language mathematical functions and is True when all of their arguments are numerical. I suspect it is integral to the interaction of many functions with the underlying knowledge base of Mathematica and therefore to many functions' valid behavior (e.g. Piecewise – always define piecewise mathematical functions with Piecewise).

Attribute: OneIdentity


OneIdentity is the mathematical property of idempotency, which dictates that applying a function any number of times to its argument (i.e. Nest) returns the argument unchanged. Examples are adding zero to any number, or multiplying any number by one, or raising any number to 1st or 0th power (except 0 - someone explain that inconsistency to me!).

0^0

During evaluation of In[549]:= Power::indet: Indeterminate expression 0^0 encountered. >>

Out[549]= Indeterminate

The Doc Center says that OneIdentity is necessary for pattern-matching to work with the default of Times, Plus, and Power, which is a period. I.e., x_+ y_. => x + 0, x_ * y_. => x * 1, and x_^y_. => x^1.

MatchQ[x, Times[n_. , x_]]

True

You can see that OneIdentity removes nested Heads. It says to the evaluator, 'If the given pattern x_ matches any of these patterns, return True.'

a+b+c/.x_:>u/;Print@FullForm[Plus[x]//HoldForm]

HoldForm[Plus[Plus[a,b,c]]]
HoldForm[Plus[Plus]]
HoldForm[Plus[a]]
HoldForm[Plus[b]]
HoldForm[Plus[c]]

a+b+c

Here are related posts on Flat and Orderless. This post shows how to reveal all built-in functions with a given Attribute, categorized by the Attribute.

This is an excellent out-of-print book but there is plenty to learn from it. I'd compare it to David Wagner's Power Programming in Mathematica in its insight to how the Wolfram Language works.

Bahder, Thomas B. Mathematica for Scientists and Engineers. Reading, MA: Addison-Wesley. 1994.




Get new posts by email:

Friday, July 10, 2015

How to See the Equivalence of Select and Cases

MatchQ and PatternTest Equate Cases and Select

Select and Cases are essential Mathematica filtering functions. Select filters expressions, usually Lists, with predicates, such as ones that end with Q (evaluate ?*Q to see them) or those that don't, such as Greater, Less, and others that I list here. Cases uses patterns such as testing for a Head (e.g. _Integer) or a more general pattern (e.g. for a 2-element List, {x_,y_}.

Cases and Select are equivalent and a versatile Mathematica programmer knows how to use either one in any circumstance according to the need of the moment. The keys to seeing their equivalence are MatchQ, which translates a pattern into a predicate, and PatternTest (_?test), which translates a predicate into a pattern.

MatchQ[4.1,_Real]

True

MatchQ[{2,2.1},{_Integer,_Real}]

True

Thus you can take any usage of Cases and translate it into Select.

Cases[{a,4,4.2,6,7.5,8},x_Integer/;x>4]

{6,8}

integerGreaterThan4Q@n_:=MatchQ[n,_Integer&&n>4];
Select[{a,4,4.2,6,7.5,8},integerGreaterThan4Q]

{6,8}

And you can take any usage of Select and translate it into Cases.

Select[{1,2,4,7,6,2},EvenQ]

{2,4,6,2}

Cases[{1,2,4,7,6,2},_?EvenQ]

{2,4,6,2}

If we built our own predicate for EvenQ using MatchQ, it works the same way.

Select[{1,2,3,4},MatchQ[#/2,_Integer]&]

{2,4}

However note the need for parentheses around the test, which is often the case with PatternTest - the no parens usage fails.

Cases[{1,2,3,4},_?(MatchQ[#/2,_Integer]&)]

{2,4}

Cases[{1,2,3,4},_?MatchQ[#/2,_Integer]&]

{}

The reason is that Blank and PatternTest both have a higher Precedence ('stickiness') than Function, and so they stick together and PatternTest ends up inside the pure Function instead of using the pure Function as the pattern test. You don't need to worry about that — just as a rule of thumb put parens around any 'homemade' test.

Precedence/@{PatternTest,Blank,Function}

{680.,730.,90.}

The Q Predicates


This is a handy way to use Partition, especially using {} so a final short sublist won't be dropped from a 'ragged' List. The syntax says

Partition[list, sublist length, offset length, start Position, padding]

and here means divide the List into Partitions of length 4, moving the window that same length 4 with each Partition so there is no overlap, start the List at Position 1,  and the empty set {} for padding tells Partition to return the final sublist even if it's shorter than what is specified by the 2nd argument, and don't pad that final short list. Evaluate this code in your Notebook:

Qpredicates=Names@"*Q";
Print@Length@Qpredicates;
Partition[Qpredicates,4,4,1,{}]//TableForm

Here's the same result in a List.

Names@"*Q"

{AcyclicGraphQ,AlgebraicIntegerQ,AlgebraicUnitQ,AntihermitianMatrixQ,AntisymmetricMatrixQ,ArgumentCountQ,ArrayQ,AssociationQ,AtomQ,BinaryImageQ,BipartiteGraphQ,BooleanQ,BoundaryMeshRegionQ,BoundedRegionQ,BusinessDayQ,ColorQ,CompatibleUnitQ,CompleteGraphQ,CompositeQ,ConnectedGraphQ,ConstantRegionQ,ContinuousTimeModelQ,ControllableModelQ,CoprimeQ,DateObjectQ,DaylightQ,DayMatchQ,DeviceOpenQ,DiagonalizableMatrixQ,DigitQ,DirectedGraphQ,DirectoryQ,DiscreteTimeModelQ,DisjointQ,DispatchQ,DistributionParameterQ,DuplicateFreeQ,EdgeCoverQ,EdgeQ,EllipticNomeQ,EmptyGraphQ,EulerianGraphQ,EvenQ,ExactNumberQ,FileExistsQ,firedQ,FreeQ,GeoWithinQ,GraphQ,GroupElementQ,HamiltonianGraphQ,HermitianMatrixQ,HypergeometricPFQ,ImageQ,IndefiniteMatrixQ,IndependentEdgeSetQ,IndependentVertexSetQ,InexactNumberQ,integerGreaterThan4Q,IntegerQ,IntersectingQ,IntervalMemberQ,InverseEllipticNomeQ,IrreduciblePolynomialQ,IsomorphicGraphQ,KEdgeConnectedGraphQ,KeyExistsQ,KeyFreeQ,KeyMemberQ,KnownUnitQ,KVertexConnectedGraphQ,LeapYearQ,LegendreQ,LetterQ,LinkConnectedQ,LinkReadyQ,ListQ,LoopFreeGraphQ,LowerCaseQ,MachineNumberQ,ManagedLibraryExpressionQ,MandelbrotSetMemberQ,MarcumQ,MatchLocalNameQ,MatchQ,MatrixQ,MemberQ,MeshRegionQ,MixedGraphQ,MultigraphQ,NameQ,NegativeDefiniteMatrixQ,NegativeSemidefiniteMatrixQ,NormalMatrixQ,NumberQ,NumericQ,ObservableModelQ,OddQ,OptionQ,OrderedQ,OrthogonalMatrixQ,OutputControllableModelQ,PartitionsQ,PathGraphQ,PermutationCyclesQ,PermutationListQ,PlanarGraphQ,PolynomialQ,PositiveDefiniteMatrixQ,PositiveSemidefiniteMatrixQ,PossibleZeroQ,PrimePowerQ,PrimeQ,ProcessParameterQ,QHypergeometricPFQ,QuadraticIrrationalQ,QuantityQ,RegionQ,RegularlySampledQ,RootOfUnityQ,SameQ,SatisfiableQ,ScheduledTaskActiveQ,SimpleGraphQ,SquareFreeQ,SquareMatrixQ,StringFreeQ,StringMatchQ,StringQ,SubsetQ,SymmetricMatrixQ,SyntaxQ,TautologyQ,TensorQ,TreeGraphQ,TrueQ,UnateQ,UndirectedGraphQ,UnitaryMatrixQ,UnsameQ,UpperCaseQ,URLExistsQ,ValueQ,VectorQ,VertexCoverQ,VertexQ,WeaklyConnectedGraphQ,WeightedGraphQ}


 

Friday, May 29, 2015

String Processing: StringCases and StringMatchQ

I recently got inconsistent results from StringCases and StringMatchQ (and used Pick instead of Cases). When using Cases or Select, you typically debug issues by mapping MatchQ onto the List that you're sifting for patterns. Similarly, StringMatchQ is the tool used to debug StringCases. However - while I don't believe there is any difference between patterns accepted by MatchQ vs. Cases, there is a significant difference between patterns accepted by StringMatchQ vs. StringCases.

StringMatchQ will accept what are called 'abbreviated String metacharacters'. These are the asterisk wildcard "*" for 0 or more characters, the @ wildcard for one or more non-upper case characters ("@@@@" matches any 4-non-upper case character Expression), and double-backslashes for literal characters (e.g. \\* to match an asterisk).

But StringCases will not; it will only accept StringExpression patterns or RegularExpressions. Here is an example. I want to extract all the "VCathode*" values from this datafile header:

data = {"%", "cln1x", "V", "(V)", "@", "VCathode=2.75392", "V", "(V)", "@", "VCathode=2.29025", "V", "(V)", "@", "VCathode=1.86092", "V", "(V)", "@", "VCathode=1.59846", "V", "(V)", "@", "VCathode=1.40122", "V", "(V)", "@", "VCathode=1.28137", "V", "(V)", "@", "VCathode=1.15876", "V", "(V)", "@", "VCathode=1.06451", "V", "(V)", "@", "VCathode=1.0037", "V", "(V)", "@", "VCathode=0.950678", "V", "(V)", "@", "VCathode=0.881652"};

StringCases with an asterisk fails:

In[190]:= StringCases[data,"VCathode*"]
Out[190]= {{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}}

StringMatchQ with an asterisk works:

In[191]:= StringMatchQ[data,"VCathode*"]
Out[191]= {False,False,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True,False,False,False,True}

Here is the solution for StringCases using StringExpressions. I use Flatten to remove nulls ("{}").

In[192]:= StringCases[#,"VCathode"~~___]&/@data//Flatten
Out[192]= {VCathode=2.75392,VCathode=2.29025,VCathode=1.86092,VCathode=1.59846,VCathode=1.40122,VCathode=1.28137,VCathode=1.15876,VCathode=1.06451,VCathode=1.0037,VCathode=0.950678,VCathode=0.881652}

And here is the solution for StringCases using a RegularExpression. Here I use DeleteCases instead of Flatten to remove nulls, but leave sets of List brackets around the returned values.

In[195]:= StringCases[#,RegularExpression["VCathode.*"]]&/@data//DeleteCases[#,{}]&
Out[195]= {{VCathode=2.75392},{VCathode=2.29025},{VCathode=1.86092},{VCathode=1.59846},{VCathode=1.40122},{VCathode=1.28137},{VCathode=1.15876},{VCathode=1.06451},{VCathode=1.0037},{VCathode=0.950678},{VCathode=0.881652}}

Thank you to Xin Xiao from Wolfram Technical Support.



Saturday, March 9, 2013

Introduction to Strings in Mathematica

A format convention in Mathematica is to show quotation marks around strings in input cells, but not in output cells. To show them in output cells, use FullForm.

In[18]:= "I've entered a string by using quotation marks."

Out[18]= I've entered a string by using quotation marks.

In[19]:= Head@%

Out[19]= String

In[20]:= FullForm@%%

Out[20]//FullForm= "I've entered a string by using quotation marks."

In programming languages, "String" is the name for the data type of text expressions. In other words, unlike symbols in a general expression, the symbols in a String, like a, b, c, do not refer to places in memory that store a variable, like a function or value. Symbols in a String do not refer to anything, or you could say they only refer to themselves as "literals", that is, the literal characters or tokens "a", "b", "c". An "a" is just a blank token with nothing behind it; hence the terms "literal" or "token" for a String symbol.

In[21]:= a = 5534.7; a

Out[21]= 5534.7

Trying to use a String as a variable gives an error message.

In[22]:= "a" = "Lookee here."

During evaluation of In[22]:= Set::setraw: Cannot assign to raw object a. >>

Out[22]= "Lookee here."

Consequently, Strings are not evaluated in the usual way that other Expressions are. Wellin et al. in their excellent book suggest that we think of a String as being broken up by Mathematica into a sequence of its characters and then functions are applied to the sequence.

In[8]:= aSentence = "The quick brown fox jumped over the 742 lazy white dogs.";

In[11]:= aSentenceCharacters = aSentence // Characters

Out[11]= {T,h,e, ,q,u,i,c,k, ,b,r,o,w,n, ,f,o,x, ,j,u,m,p,e,d, ,o,v,e,r, ,t,h,e, ,7,4,2, ,l,a,z,y, ,w,h,i,t,e, ,d,o,g,s,.}

Functions, like MatchQ, Cases, Position, etc., that work on non-String expressions do not work on Strings but do work on their sequence of characters.

In[14]:= Position[aSentence, "e"]

Out[14]= {}

So perhaps as Wellin et al suggest, Mathematica first breaks a String into a sequence of characters and applies some of the regular built-in functions as well as some specialized String functions to the sequence.


In[25]:= MatchQ[#, "e"] & /@ aSentenceCharacters

Out[25]= {False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False}

In[24]:= StringMatchQ[aSentenceCharacters, "e"]

Out[24]= {False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False}


In[15]:= Position[aSentenceCharacters, "e"]

Out[15]= {{3}, {25}, {30}, {35}, {50}}

In[16]:= StringPosition[aSentence, "e"]

Out[16]= {{3, 3}, {25, 25}, {30, 30}, {35, 35}, {50, 50}}

The position index is repeated in StringPosition since it shows the beginning and ending positions of the matched String.

In[20]:= StringPosition[aSentence, "lazy"]

Out[20]= {{41, 44}}

When working with Strings, you do not need to enclose a String in List brackets:

In[3]:= aString = {"abcd"}

Out[3]= {abcd}

In[4]:= aString2 = "abcd"

Out[4]= abcd

In[5]:= Head@aString2

Out[5]= String

The String is delimited by invisible quotation marks. As usual FullForm and InputForm reveal the way Mathematica sees the String.

In[6]:= FullForm@aString2

Out[6]="abcd"

In[7]:= InputForm@aString2

Out[7]="abcd"

Next we will look at the variety of String functions in Mathematica.