Function Repository Resource:

GenerateOrderingConditions

Source Notebook

Generate the conditions under which a list of symbolic expressions has a particular ordering or set of orderings with respect to an operation

Contributed by: Seth J. Chandler

ResourceFunction["GenerateOrderingConditions"][op,exprs,vars]

computes the conditions under which, for a given ordering operator op, each possible ordering of the symbolic expressions in exprs would occur, assuming that vars is the list of variables in exprs.

ResourceFunction["GenerateOrderingConditions"][op,exprs,vars,dom]

assumes that the values of vars are confined to the domain dom.

Details and Options

By default, the function produces an Association in which each key is an ordering of the symbolic expressions exprs and the values are the conditions under which that ordering would exist.
The op argument is likely to be a function such as Greater, Less or other function with arity of 2 or more that yields True or False when its arguments are real values.
The arguments of the function after the initial op argument are precisely the same as those available for Reduce, though additional options are supported.
If the list contains duplicate expressions and the operator is Greater, Less or others where ties are prohibited, all values produced by the function will be False.
ResourceFunction["GenerateOrderingConditions"] has the same options as Reduce, with the following additions:
"AdditionalConstraints"{}constraints on permissible values of the variables
"KeyFunction"Identitya function to map over the keys of the output Association
"Pattern"_specification of which orderings of the expressions will be considered
"PatternInterpreter"(Function[explist,Function[pat,pat]])how to interpret the value of the "Pattern" option

Examples

Basic Examples (1) 

Order three symbolic expressions involving the variables a and b:

In[1]:=
explist = {a + b, a - b, a*b};
In[2]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}]
Out[2]=

Scope (2) 

The expressions can contain constants:

In[3]:=
ResourceFunction[
 "GenerateOrderingConditions"][Greater, {3 ( a + b), 2, a b}, {a, b}]
Out[3]=

Restrict the domain of permissible solutions:

In[4]:=
ResourceFunction[
 "GenerateOrderingConditions"][Greater, {3 ( a + b), 2, a b}, {a, b}, Integers]
Out[4]=

Options (10) 

Pattern (2) 

Determine the conditions under which ab will lie in the middle of the two other values:

In[5]:=
explist = {a + b, a - b, a*b};
In[6]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "Pattern" -> {_, a - b, _}]
Out[6]=

Determine the conditions under which the ordering of a four-element list with respect to an operation will have its fourth member first and its second member third:

In[7]:=
Module[{augmentedexplist = Append[explist, a^3 - b^2], pat},
 pat = Normal@
   SparseArray[{1 -> augmentedexplist[[4]], 3 -> augmentedexplist[[2]]}, 4, _];
 ResourceFunction["GenerateOrderingConditions"][Less, augmentedexplist, {a, b}, "Pattern" -> pat]]
Out[7]=

PatternInterpreter (2) 

By setting the "PatternRepresentation" option, you can change the interpretation of the value of the "Pattern" option. For a value f taken by this option, and a value explist of the expressions to be sorted, the value of the "Pattern" option pat is interpreted as f[explist][pat]. Interpret the value of the "Pattern" option as indices into the list of expressions:

In[8]:=
f = (Function[explist, Function[pat, explist[[pat]]]]);
In[9]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "Pattern" -> {1, 3, 2}, "PatternInterpreter" -> f]
Out[9]=

Use integer indices to represent a desired ordering but also permit blank patterns where one does not care about the exact ordering:

In[10]:=
f2 = (Function[explist, Function[pat, Map[p |-> Switch[p, _Integer, explist[[p]], _, p]][pat]]]);
In[11]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "Pattern" -> {1, _, _}, "PatternInterpreter" -> f2]
Out[11]=

KeyFunction (2) 

Represent the keys not as the expressions themselves but by indices into the original expression list:

In[12]:=
explist = {a + b, a - b, a*b}
Out[12]=
In[13]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "KeyFunction" -> "Indexed"]
Out[13]=

Any arbitrary expression can be used as a "KeyFunction":

In[14]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "KeyFunction" -> Apply[Less]]
Out[14]=

The default value for "KeyFunction" is Identity:

In[15]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, Integers, "KeyFunction" -> Identity] === ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b},
   Integers]
Out[15]=

One can combine the "KeyFunction" option with the "Pattern" and "PatternInterpretation" functions:

In[16]:=
f2 = (Function[explist, Function[pat, Map[p |-> Switch[p, _Integer, explist[[p]], _, p]][pat]]])
Out[16]=
In[17]:=
ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "KeyFunction" -> "Indexed", "Pattern" -> {2, _, _}, "PatternInterpreter" -> f2]
Out[17]=

AdditionalConstraint (4) 

Place additional constraints on the expressions to be sorted:

In[18]:=
explist = {a + b, a - b, a*b}
Out[18]=
In[19]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}, "AdditionalConstraints" -> And[a > 1, b < a]]
Out[19]=
In[20]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}, "AdditionalConstraints" -> a > 2]
Out[20]=

The additional constraints can be geometric:

In[21]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}, "AdditionalConstraints" -> {a, b} \[Element] Circle[]]
Out[21]=

The additional constraints can result from the computation of an ImplicitRegion:

In[22]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}, "AdditionalConstraints" -> {a, b} \[Element] ImplicitRegion[a + 2 b >= 1 && a b == 7, {a, b}]]
Out[22]=

The additional constraints can result from the computation of a ParametricRegion:

In[23]:=
ResourceFunction[
 "GenerateOrderingConditions"][GreaterEqual, explist, {a, b}, "AdditionalConstraints" -> {a, b} \[Element] ParametricRegion[{Sin[t], Cos[2 t]}, t]]
Out[23]=

All the options for Reduce are also supported, including user-specified generated parameters and display of full cubic and quartic expressions instead of root objects. The GeneratedParameters option works:

In[24]:=
ResourceFunction[
 "GenerateOrderingConditions"][Greater, {Cos[x], Sin[2 y]}, {x, y}, Reals, GeneratedParameters -> (Subscript[k, #] &)]
Out[24]=

The Quartics option works (as does Cubics):

In[25]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/42523335-5c0d-4640-bab4-968223ed028d"]
Out[25]=

The WorkingPrecision option can be used:

In[26]:=
ResourceFunction[
 "GenerateOrderingConditions"][Less, {x^77 + 3 x - 11, E, y^5 - x^2 y + 21}, {x, y}, Integers, "AdditionalConstraints" -> {x > 0, y > 0}, WorkingPrecision -> 10]
Out[26]=

Applications (2) 

Show conditions under which a-b will have the smallest value among {a+b,ab,ab}, but also requiring a+b<3:

In[27]:=
explist = {a + b, a - b, a b};
In[28]:=
RegionPlot[
 Evaluate[Or @@ Values@ResourceFunction["GenerateOrderingConditions"][Less, explist, {a, b}, "Pattern" -> {a - b, ___}, "AdditionalConstraints" -> a + b < 3]], {a, -3, 3}, {b, -3, 3}, FrameLabel -> {"a", "b"}]
Out[28]=

In a three-party race, the first candidate has 20 votes, the second candidate has 25 votes, and the third candidate has 27 votes. It is estimated, however, that only 70% of the votes have been counted. Compute the conditions under which candidate 1 will end up with the most votes:

In[29]:=
f2 = (Function[explist, Function[pat, Map[p |-> Switch[p, _Integer, explist[[p]], _, p]][pat]]]);
In[30]:=
candidate1Region = Module[{votes = {20, 25, 27}, counted = 7/10},
  Or @@ Values@
    With[{uncounted = Total[votes]/counted - counted}, Quiet@ResourceFunction["GenerateOrderingConditions"][Greater, votes + uncounted*{c1, c2, 1 - (c1 + c2)}, {c1, c2}, "AdditionalConstraints" -> {Total[{c1, c2, 1 - (c1 + c2)}] == 1, 0 <= c1 <= 1, 0 <= c2 <= 1}, "Pattern" -> {1, _, _}, "PatternInterpreter" -> f2, "KeyFunction" -> "Indexed"]]
  ]
Out[30]=

Plot the corresponding region:

In[31]:=
RegionPlot[candidate1Region, {c1, 0, 1}, {c2, 0, 1}, FrameLabel -> {"fraction of remaining votes for candidate 1", "fraction of remaining votes for candidate 2"}, PlotLabel -> "Path to Victory for Candidate 1"]
Out[31]=

Do the same computation but assume that to avoid a runoff election, candidate 1 must get more than 50% of the total votes:

In[32]:=
candidate1Majority = Module[{votes = {20, 25, 27}, counted = 7/10},
  Or @@ Values@
    With[{uncounted = Total[votes]/counted - counted}, Quiet@ResourceFunction["GenerateOrderingConditions"][Greater, votes + uncounted*{c1, c2, 1 - (c1 + c2)}, {c1, c2}, "AdditionalConstraints" -> {Total[{c1, c2, 1 - (c1 + c2)}] == 1, 0 <= c1 <= 1, 0 <= c2 <= 1, votes[[1]] + uncounted*c1 > 0.5*Total[votes + uncounted*{c1, c2, 1 - (c1 + c2)}]}, "Pattern" -> {1, _, _}, "PatternInterpreter" -> f2, "KeyFunction" -> "Indexed"]]
  ]
Out[32]=

Plot the resulting region:

In[33]:=
RegionPlot[candidate1Majority, {c1, 0, 1}, {c2, 0, 1}, FrameLabel -> {"fraction of remaining votes for candidate 1", "fraction of remaining votes for candidate 2"}, PlotLabel -> "Path to Victory with No Runoff for Candidate 1"]
Out[33]=

Possible Issues (3) 

The "Modulus" option cannot be used if the op argument generates an inequality:

In[34]:=
ResourceFunction[
 "GenerateOrderingConditions"][{x^3 - 2 x + 1, x^2 - 2}, {x}, Modulus -> 5]
Out[34]=

As the length of the expression list grows or the length of the vars argument grows, the time needed to do the computations can grow significantly:

In[35]:=
Timing[ResourceFunction["GenerateOrderingConditions"][
  Less, {a x^2 + b x + c, 3 x^3 + 2 x^2 - 5 x , 9}, {a, b, c, x}]]
Out[35]=

If Reduce cannot determine the order of the expressions, the computation can take a long time:

In[36]:=
TimeConstrained[
 ResourceFunction["GenerateOrderingConditions"][
  Less, {m x + b, Sin[x]}, {m, b, x}, Reals], 10]
Out[36]=

Neat Examples (3) 

Under the original Article II of the United States Constitution and prior to the enactment of the Twelfth Amendment, the presidential candidate with the most votes in the electoral college would become the President of the United States and the candidate with the second-most votes would become the Vice President, even if the President and Vice President had serious disagreements. Suppose the electoral college votes of four candidates subject to that voting system depend on two parameters, x and y. Compute the conditions for each ordering of the four candidates:

In[37]:=
votes = {Clip[33 + x + y, {0, 138}], Clip[26 + x - y, {0, 138}], Clip[40 - x + 2 y, {0, 138}], 138 - Clip[26 + x - y, {0, 138}] - Clip[33 + x + y, {0, 138}] - Clip[40 - x + 2 y, {0, 138}]};
In[38]:=
(votingOrder = ResourceFunction["GenerateOrderingConditions"][GreaterEqual, votes, {x, y}, Reals, "KeyFunction" -> "Indexed"]) // ResourceFunction[
ResourceObject[<|"Name" -> "Terse", "ShortName" -> "Terse", "UUID" -> "6809487c-44ed-4a55-a610-ab706ebb8661", "ResourceType" -> "Function", "Version" -> "1.0.0", "Description" -> "An operator form of Short", "RepositoryLocation" -> URL[
      "https://www.wolframcloud.com/objects/resourcesystem/api/1.0"], "SymbolName" -> "FunctionRepository`$369a78f89aa2413eb5b19a962ce89cd7`Terse", "FunctionLocation" -> CloudObject[
      "https://www.wolframcloud.com/obj/c1820918-b759-4685-b9b8-c971a81216b5"]|>, ResourceSystemBase -> Automatic]][5]
Out[38]=

Plot the regions of x and y for which each candidate becomes President and Vice President:

In[39]:=
regions[n_][generatedConditions_] := Query[KeyTake[Range[Length[generatedConditions]]]/*Values, Values/*Apply[Or]][ResourceFunction[
ResourceObject[<|"Name" -> "KeyGroupBy", "ShortName" -> "KeyGroupBy", "UUID" -> "10d8ffd6-2783-4d26-949b-9636792e92ff", "ResourceType" -> "Function", "Version" -> "1.0.0", "Description" -> "Apply a function to keys of an association and group results by modified keys", "RepositoryLocation" -> URL[
       "https://www.wolframcloud.com/objects/resourcesystem/api/1.0"],
       "SymbolName" -> "FunctionRepository`$9b1c24130d3e49889d3705320461ccb4`KeyGroupBy", "FunctionLocation" -> CloudObject[
       "https://www.wolframcloud.com/obj/ef7b080c-c161-4427-8844-33b7cac307c1"]|>, ResourceSystemBase -> Automatic]][
   generatedConditions, #[[n]] &]]
In[40]:=
Block[{legend},
 legend = Legended[#, SwatchLegend[(ColorData[1][#1] &) /@ Range[4], Range[4]]] &; Row@MapThread[{pos, label} |-> With[{plotOperator = (
ResourceFunction[
ResourceObject[<|"Name" -> "MapSlice", "ShortName" -> "MapSlice", "UUID" -> "f3da3843-eca4-49a1-a10f-ae495c5a085e", "ResourceType" -> "Function", "Version" -> "1.0.0", "Description" -> "Provide the part specifications to a mapped function as a sequence of arguments after the first one", "RepositoryLocation" -> URL[
             "https://www.wolframcloud.com/objects/resourcesystem/api/1.0"], "SymbolName" -> "FunctionRepository`$fc34d7cb86b4477286abcf1aeedb1cac`MapSlice", "FunctionLocation" -> CloudObject[
             "https://www.wolframcloud.com/obj/2edb34b0-5ba9-472e-9991-7a8746a6c7a5"]|>, ResourceSystemBase -> Automatic]])[{candidate, index} |-> RegionPlot[candidate, {x, -20, 20}, {y, -20, 20}, PlotLabel -> label, Sequence[
          MaxRecursion -> 5, ImageSize -> 350], PlotStyle -> ColorData[1][index]]]},
     Apply[Show][plotOperator[regions[pos][votingOrder]]] // legend], {Range[2], {"President", "Vice-President"}}]
 ]
Out[40]=

Compute the probability that each candidate will become President and Vice President, assuming that x and y are drawn from a multivariate normal distribution:

In[41]:=
With[{xyDist = MultinormalDistribution[{7, -1}, {{8, 3}, {3, 6}}]}, AssociationMap[
  pos |-> With[{reg = regions[pos /. {"President" -> 1, "Vice President" -> 2}][
       votingOrder]}, AssociationMap[
     candidateIndex |-> NProbability[
       reg[[candidateIndex]], {x, y} \[Distributed] xyDist, Method -> "MonteCarlo"], Range[4]]
    ], {"President", "Vice President"}]
 ]
Out[41]=

Publisher

Seth J. Chandler

Version History

  • 2.0.0 – 09 November 2020
  • 1.0.0 – 23 October 2020

Related Resources

License Information