Sorting out list elements that are nonlinear in a certain function - Mathematica Stack Exchange most recent 30 from mathematica.stackexchange.com 2019-09-20T17:21:05Z https://mathematica.stackexchange.com/feeds/question/180288 https://creativecommons.org/licenses/by-sa/4.0/rdf https://mathematica.stackexchange.com/q/180288 1 Sorting out list elements that are nonlinear in a certain function Display Name https://mathematica.stackexchange.com/users/40650 2018-08-20T09:07:00Z 2018-08-20T11:59:14Z <p>I have the following (long) list (exemplary I will show you only a few elements of it):</p> <pre><code> list={a[om1,om2,om3,om4,om5,om6]*F[om1] F[om2] F[om4] F[om5] F[om6],b[om1,om2,om3,om4,om5,om6]*F[om1] F[om2], c[om1,om2,om3,om4,om5,om6]*F[om2],d[om1, om2, om3, om4,om5,om6]} </code></pre> <p>I want to keep only those elements that are linear in the function <code>F[_]</code> (i.e. the result in the example should be <code>{c[om1,om2,om3,om4,om5,om6]*F[om2]}</code>). So far I did this with <code>Select</code>, sth like</p> <pre><code>Select[list, MemberQ[#, F[_]] &amp;&amp; FreeQ[#, F[_] __F] &amp;] </code></pre> <p>For a very large list, however, this becomes too slow (can I invoke Assumptions with <code>Select</code>?). Is there another way, to do the same task in a faster way? I was thinking of <code>Series</code> but it doesn't seem to be applicable to expansions in functions.</p> https://mathematica.stackexchange.com/questions/180288/-/180290#180290 3 Answer by Fraccalo for Sorting out list elements that are nonlinear in a certain function Fraccalo https://mathematica.stackexchange.com/users/40354 2018-08-20T09:22:56Z 2018-08-20T09:29:41Z <p>Replace MemberQ and FreeQ with Count as follows:</p> <pre><code>list2 = Join @@ ConstantArray[list, 10000]; RepeatedTiming[A=Select[list2, MemberQ[#, F[_]] &amp;&amp; FreeQ[#, F[_] __F] &amp;]][] RepeatedTiming[B = Select[list2, Count[#, F[_]] == 1 &amp;]][] A == B </code></pre> <blockquote> <p>0.302</p> <p>0.063</p> <p>True</p> </blockquote> <p>Speed up: 5x (better than nothing :) )</p> https://mathematica.stackexchange.com/questions/180288/-/180292#180292 1 Answer by Alexei Boulbitch for Sorting out list elements that are nonlinear in a certain function Alexei Boulbitch https://mathematica.stackexchange.com/users/788 2018-08-20T09:31:28Z 2018-08-20T09:45:31Z <p>Provided each term always has a coefficient (like a[om1,...], c[om1,...] etc.) and may (or may not) have one or several <code>F</code> factors, try this:</p> <pre><code>Select[list, Length[#] == 2 &amp;] (* {c[om1, om2, om3, om4, om5, om6] F[om2]} *) </code></pre> <p>Edit: taking into account your comment try also this:</p> <pre><code>count[expr_] := Count[expr, _F, Infinity] Select[list, count[#] == 1 &amp;] (* {c[om1, om2, om3, om4, om5, om6] F[om2]} *) </code></pre> <p>Have fun!</p> https://mathematica.stackexchange.com/questions/180288/-/180302#180302 2 Answer by Anton.Sakovich for Sorting out list elements that are nonlinear in a certain function Anton.Sakovich https://mathematica.stackexchange.com/users/59438 2018-08-20T11:59:14Z 2018-08-20T11:59:14Z <p>The question of efficient lookup of terms linear relative expression satisfying a given pattern depends strongly on whether coefficients <code>c[om1,...]</code> themselves can somehow depend on this expression.</p> <p>If coefficients <code>a</code>, <code>b</code>, <code>c</code>, etc can themselves depend on <code>F</code>, then none of the above solutions can be reliable. For example, the expression <code>Sin[F[om1]]</code> contains exactly one expression matching <code>_F</code> at the first level, so both approaches of Fraccalo and Alexei Boulbitch will return it.</p> <pre><code>Select[{Sin[F[om1]]}, Count[#, F[_]] == 1 &amp;] (*Returns {Sin[F[om1]]}*) ClearAll[count]; count[expr_] := Count[expr, _F, Infinity]; Select[{Sin[F[om1]]}, count[#] == 1 &amp;] (*Returns {Sin[F[om1]]}*) </code></pre> <p>In this, the most general case, the only option I see is to use <code>FreeQ</code>:</p> <pre><code>list={a[om1,om2,om3,om4,om5,om6]*F[om1] F[om2] F[om4] F[om5] F[om6],b[om1,om2,om3,om4,om5,om6]*F[om1] F[om2],c[om1,om2,om3,om4,om5,om6]*F[om2],d[om1,om2,om3,om4,om5,om6]}; list2=Join@@ConstantArray[list,10000]; RepeatedTiming[ general=Cases[ list2, (a_/;(FreeQ[a,_F]))*_F ] ]//First (*0.298*) </code></pre> <p>However, if coefficients themselves cannot depend on <code>F</code> and we just need to figure out how many times <code>F[...]</code> is repeated, then Fraccalo approach is a good option.</p> <pre><code>RepeatedTiming[ select = Select[list2, Count[#, F[_]] == 1 &amp;] ] // First (*0.054*) </code></pre> <p>But we can improve the result a little bit by exploiting the fact that in this case we are not interested in how many there are <code>F[...]</code> expressions in the terms, what <code>Count</code> computes. We only need to know, whether there is exactly one expression of the form or not. For this reason, we can try the following:</p> <pre><code>RepeatedTiming[ pattern = Cases[list2, Repeated[Except[_F], {1}]*_F] ] // First (*0.0280*) general === select === pattern (*True*) </code></pre> <p>Note, that <code>Except[_F]*_F</code> will not work here because <code>Times</code> is <code>Flat</code>.</p>