Making tables and update calculated values
A few customizations for the IntervalSlider
and InputField
controls:
ClearAll[thumb, intSlider, inpField]
thumb = Graphics[{#, Text[Style["▲", #, 16], Offset[{0, -20}, {0, 0}]],
Text[Style[#2, 12], Offset[{0, -35}, {0, 0}]]}, ImageSize -> 20] &;
intSlider[Dynamic[{x_, y_}], range_, opts___ : OptionsPattern[]] :=
IntervalSlider[Dynamic[{x, y}], range, Method -> "Stop",
Appearance -> {"ThumbAppearance" -> {thumb[Red, Dynamic[x]], None,
thumb[Blue, Dynamic[y]]}}, ImageSize -> {400, 50}, opts]
inpField = InputField[#, Appearance -> "Frameless", FieldSize -> 5,
Alignment -> Center] &;
Given a list of input functions, we only need the functions Interval
and MinMax
to find the extrema of the input expressions:
ClearAll[functions, minMax]
functions = {# + #2 &, -# &, # + 2 #2 &, -#2 &, #- #2&, #2 - #&, 1/(2 # - #2) &};
minMax[f_][x_, y_] := MinMax@f[Interval@x, Interval@y]
The IntervalSlider
s and InputField
s are used to specify the input.
DynamicModule[{a = {20, 50}, b = {35, 75}}, Dynamic @
Grid[{{Grid[{{Labeled[intSlider[Dynamic@{a[[1]], a[[2]]}, {0, 100, 1}],
Style["a", 16], Left], SpanFromLeft, SpanFromLeft, SpanFromLeft},
{Labeled[intSlider[Dynamic@{b[[1]], b[[2]]}, {0, 100, 1}],
Style["b", 16], Left], SpanFromLeft, SpanFromLeft, SpanFromLeft}},
Dividers -> All, ItemSize -> 10]},
{Grid[{{"a", SpanFromLeft, "b", SpanFromLeft} /. s_String :>
Item[s, Background -> LightGray],
Item[#, Background -> LightBlue] & /@ {"min", "max", "min", "max"},
Item[#, Background -> LightYellow] & /@
{inpField[Dynamic[a[[1]]]], inpField[Dynamic[a[[2]]]],
inpField[Dynamic[b[[1]]]], inpField[Dynamic[b[[2]]]]}},
Frame -> {All, All}, ColumnsEqual -> True, ItemSize -> 10, Alignment -> Center]},
{Dynamic@ Grid[{{"expr", SpanFromLeft, "min (expr)", "max (expr)"} /.
s_String :> Item[s, Background -> LightMagenta],
## & @@ Table[{foo["a", "b"], SpanFromLeft, ##& @@ minMax[foo][a, b]},
{foo, functions}]},
Dividers -> All, ColumnsEqual -> True, ItemSize -> 10, Alignment -> Center]}}]]
Note: You can also define functions
as
functions = Function[{x, y}, #] & /@
{x + y, -x, x + 2 y, -y, x - y, y - x, 1/(2 x - y)}
Update: Dealing with cases where some input expression are lists, as in,for example,
expList = {x + y, 2 x, {x + y, 2 x}, -x, x + 2 y, -y, x - y, y - x, 1/(2 x - y)}
We need to modify minMax
to handle lists:
ClearAll[minMax, functions]
minMax[f_][x_, y_] := MinMax@f[Interval@x, Interval@y]
minMax[f_List][x_, y_] := MinMax@Transpose[minMax[#][x, y] & /@ f]
Second, we need to transform the input list to a list of functions:
functions = Block[{bar},
Map[bar, expList, 1] /. bar[l_List] :> bar /@ l /. bar -> (Function[{x, y}, #] &)]
Finally, we need to change the first argument of Table
in the last grid to handle lists in the functions
list properly.
With these changes (removing the second grid with input fields):
DynamicModule[{a = {20, 50}, b = {35, 75}},
Dynamic@Grid[{{Grid[{{Labeled[intSlider[Dynamic@{a[[1]], a[[2]]}, {0, 100, 1}],
Style["a", 16], Left], SpanFromLeft, SpanFromLeft, SpanFromLeft},
{Labeled[intSlider[Dynamic@{b[[1]], b[[2]]}, {0, 100, 1}],
Style["b", 16], Left], SpanFromLeft, SpanFromLeft, SpanFromLeft}},
Dividers -> All, ItemSize -> 10]},
{Dynamic@ Grid[{{"expr", SpanFromLeft, "min (expr)", "max (expr)"} /.
s_String :> Item[s, Background -> LightMagenta],
## & @@ Table[{If[Head[foo] === List, Through@foo["a", "b"], foo["a", "b"]],
SpanFromLeft, ## & @@ minMax[foo][a, b]},
{foo, functions}]},
Dividers -> All, ColumnsEqual -> True, ItemSize -> 10, Alignment -> Center]}}]]
One way is to use Minimize
and Maximize
with constraint.
Need to make sure min is smaller than max, else you'll get unexpected results.
Manipulate[
Module[{a, b},
Quiet@Grid[{
{"expression", "Min", "Max"},
{"a+b",
First@Minimize[{a + b, minA < a < maxA && minB < b < maxB}, {a, b}],
First@Maximize[{a + b, minA < a < maxA && minB < b < maxB}, {a, b}]},
{"-a", First@Minimize[{-a, minA < a < maxA}, a],
First@Maximize[{-a, minA < a < maxA}, a]},
{"a+2 b", First@Minimize[{a + 2 b, minA < a < maxA && minB < b < maxB}, {a, b}],
First@Maximize[{a + b, minA < a < maxA && minB < b < maxB}, {a,b}]},
{"-b", First@Minimize[{-b, minB < b < maxB}, b],
First@Maximize[{-b, minB < b < maxB}, b]}
}, Frame -> All
]
],
{{minA, 1, "Min of a"}, 0, 10, 1, Appearance -> "Labeled"},
{{maxA, 3, "Max of a"}, 0, 10, 1, Appearance -> "Labeled"},
{{minB, 2, "Min of b"}, 0, 10, 1, Appearance -> "Labeled"},
{{maxB, 6, "Max of b"}, 0, 10, 1, Appearance -> "Labeled"},
TrackedSymbols :> {minA, minB, maxA, maxB}
]