# Find elements of a list matching specific patterns

I have defined several symbolic function f[x],g[x,y],h[x,y,z] etc... And I have a list made of elements which are product of these functions with different arguments; for example,

list = { f[a]f[-a], f[a]g[c,d]h[-a,-c,-d],  f[c]f[-c] ,
f[d]g[a,y]h[-d,-a,-y] , f[b]f[-a] , f[-c]f[c] ,
f[d]g[a,y]h[-d,-a,-z] }


Actually, these functions are just symbolic. They do not return any value. You can think the functions' arguments as tensorial indexes.

I want to find an efficient function checkPattern[list_] which does the following

1) Take the first element f[a]f[-a] and find if there are others elements matching this pattern; so, for example, the third element of list is "equal" to the first one, in the sense that f[a]f[-a]~f[c]f[-c]~f[-c]f[c] irrespectively of the arguments. Note that the elements f[a]f[-a] and f[b]f[-a] are different.

2) Take the second element (which is more complicated) and does the same check as the step 1.

So the result would be

checkPattern[list]
(* {{1,3,6},{2,4},{5},{7}}*)

• Why not represent your products using TensorProduct/TensorContract? For example, both f[-c]f[c] and f[a] f[-a] could be TensorContract[TensorProduct[f, f], {{1,2}}] and f[a]g[c,d][h[-a,-c,-d] could be TensorContract[TensorProduct[f,g,h], {{1, 4}, {2,5}, {3, 6}}]. This eliminates the use of dummy indices. – Carl Woll Apr 2 '18 at 21:43
• I know the TensorProduct function; but this would not allow me to do symbolic computation – apt45 Apr 2 '18 at 21:44
• Why would TensorProduct prevent you from doing symbolic computations? – Carl Woll Apr 2 '18 at 22:08

list = {f[a] f[-a], f[a] g[c, d] h[-a, -c, -d], f[c] f[-c],
f[d] g[a, y] h[-d, -a, -y], f[b] f[-a], f[-c] f[c],
f[d] g[a, y] h[-d, -a, -z]};


Borrowing from here, we can find a list of all distinct patterns as follows:

patterns = Quiet[
SortBy[
DeleteDuplicates[
list /.
p : Alternatives[a | b | c | d | x | y | z] :>
Pattern[p, Blank[]],
InternalComparePatterns[##] == "Identical" &
],
MemberQ[{"Identical" , "Specific"}, InternalComparePatterns[##]] &]
];


Observe that I had to specify which symbols may be used as "indices".

A first approximation to the ultimate result could be

allpos = Map[Flatten@Position[list, #] &, patterns]


{{1, 3, 6}, {1, 3, 5, 6}, {2, 4}, {2, 4, 7}}

This can be cleaned up by utilizing that patterns is already ordered:

Table[Complement[allpos[[i]], Union @@ allpos[[1 ;; i - 1]]], {i, 1, Length[allpos]}]


{{1, 3, 6}, {5}, {2, 4}, {7}}

• Thank you. I did not understand the last passage, when you clean allpos. Is this operation valid for any type of list like list or it is specific for the example I gave? – apt45 Apr 3 '18 at 6:42
• The cleaning just removes duplicated from allpos while preserving the first occurence (since patterns is ordered by "specificallity", the first occurence belongs to the most specific pattern). It is meant to work with all input lists list for which patterns can be set up correctly. I haven't performed any further tests, though. – Henrik Schumacher Apr 3 '18 at 6:51
• Ok thanks. I'll do some tests and let you know :) – apt45 Apr 3 '18 at 6:53