({{}})

({{, ({{Lezione 6}, {Interattività e dinamicità}, {Crescenzio Gallo - Università di Foggia
crescenzio.gallo@unifg.it}})}})

Note:

Il materiale visualizzato durante questo seminario è disponibile per il download all'indirizzo http://www.crescenziogallo.it/unifg/seminario-mathematica-2014/

Il materiale utilizzato è tratto dai webinar pubblicati da Adalta e prodotti dal dott. Roberto Cavaliere (Mathematica Technical Sales Manager, r.cavaliere@adalta.it)

12-26 Giugno 2014

Agenda

Come nasce il concetto di computazione dinamica e interattiva

I principali controller

Tutto si può rendere dinamico: esempi di base

Alcuni trucchi

Demonstrations (http://demonstrations.wolfram.com): esempi avanzati

Come nasce il concetto di computazione dinamica e interattiva

Mathematica ha rivoluzionato il concetto di computazione interattiva e dinamica, introducendo funzioni dinamiche che istantaneamente creano interfacce intuitive e interattive. Le computazioni sottostanti vengono eseguite in run-time:

Integrate[1/(x^3+1),x]

Come nasce il concetto di computazione dinamica e interattiva

Alla base di Manipulate c’è la funzione Dynamic

Grid[{{"Statico",Solve[a (x^2)+b x + c == 0,x]},{"Dinamico",Dynamic[Solve[a (x^2)+b x + c == 0,x]]}},Alignment->Left,Dividers->All]

Assegniamo ora dei valori ai parametri a, b, c

{a=0,b=1,c=-2}

Si può creare un oggetto di tipo SetterBar per modificare più semplicemente i valori di a, b e c

SetterBar[Dynamic[a],{-1,0,1}]

Panel[
Column[
{Row[{"Imposta a ",SetterBar[Dynamic[a],Range[-5,5]]}],Row[{"Imposta b ",SetterBar[Dynamic[b],Range[-5,5]]}],Row[{"Imposta c ", SetterBar[Dynamic[c],Range[-5,5]]}]}]]

I principali controller

DynamicModule[{x=0.5,y=1,b=True,r=Random[],filename="(no file)",n,s,c=LightGray,p={0,0}},Manipulate@Grid[({{Tooltip[Slider[Dynamic[s]],"Slider[Dynamic[x], {min, max}]"], Tooltip[InputField[Dynamic[r],Expression,FieldSize->{{10,10},{1,1}}],"InputField[Dynamic[x], type]"], Tooltip[CheckboxBar[{"apples","bananas"},{"apples","oranges","bananas"}],"CheckboxBar[Dynamic[x], list]"]}, {Tooltip[ProgressIndicator[Dynamic[x],{0,1}],"ProgressIndicator[Dynamic[x], {min, max}]"], Tooltip[PopupMenu["Alice",{"Alice","Bob","Cos" -> Plot[Cos[t],{t,0,10}],Integrate[1/(1 - ξ^3), ξ]},ImageSize->Automatic,Enabled->Dynamic[b]],"PopupMenu[Dynamic[x], list]"], Tooltip[RadioButtonBar["no",{"yes","no","maybe"}],"RadioButtonBar[Dynamic[x], list]"]}, {Tooltip[TogglerBar[{α},{α,β,γ,δ,ϵ}],"TogglerBar[Dynamic[x], list]"], Tooltip[ColorSlider[Dynamic[c]],"ColorSlider[Dynamic[x]]"], Row[{Tooltip[FileNameSetter[Dynamic[filename]],"FileNameSetter[Dynamic[x]]"],Dynamic[filename]},"  "]}, {Row[{Tooltip[Opener[],"Opener[Dynamic[x]]"],Tooltip[Checkbox[Dynamic[b]],"Checkbox[Dynamic[x]]"],Tooltip[RadioButton[Dynamic[y],3],"RadioButton[Dynamic[x], value]"],Tooltip[Button["click",r=Random[],ImageSize->Automatic],"Button[label, action]"]}], Tooltip[Animator[Dynamic[x],AnimationRunning->False,AppearanceElements -> {"StepLeftButton","StepRightButton","PlayPauseButton","FasterSlowerButtons","DirectionButton"}],"Animator[Dynamic[x], {min, max}]"], Tooltip[Hyperlink["www.wolfram.com","http://wolfram.com/"],"Hyperlink[label, url]"]}, {Tooltip[TabView[Plot[Sin[# x],{x,0,10},ImageSize -> Small,Background->Dynamic[c]]& /@ Range[5],Dynamic[n]],"TabView[list, Dynamic[x]]"], Row[{Tooltip[Slider2D[Dynamic[p],{-{1,1},{1,1}}],"Slider2D[Dynamic[x],{min,max}]"],Tooltip[VerticalSlider[Dynamic[s],ImageSize->Small],"VerticalSlider[Dynamic[x], {min, max}]"]},Spacer[10]], Labeled[
Tooltip[SetterBar[Dynamic[n],{1,2,3,4,5}],"SetterBar[Dynamic[x], list]"],
Tooltip[PaneSelector[{1->,2->,3->,4->,5->},Dynamic[n]],"PaneSelector[list, Dynamic[x]]"]]}, {Tooltip[Manipulator[Dynamic[s],Appearance->"Open"],"Manipulator[Dynamic[x], {min, max}]"], Tooltip[Deploy@Graphics[{Line[Table[{Dynamic[p],{Cos[a],Sin[a]}},{a,0,2π,π/16}]],Locator[Dynamic[p]]},PlotRange->1.2,ImageSize->80],"Graphics[{…, Locator[Dynamic[x]], …}]"], Tooltip[ActionMenu["To Do",{"Pink":>(c=Pink),
"Three":>(n=3),
"Top":>(p={0,1}),
"Bottom":>(p={0,-1})
}],"ActionMenu[name, {label :> action, …}]"]}}),Spacings->{2,1}]]

Tutto si può rendere dinamico: esempi di base

Grazie sempre alla filosofia sintetizzata dallo slogan “Everything is an expression” anche gli oggetti dinamici possono utilizzare qualsiasi espressione nel loro modulo, dunque qualsiasi cosa in Mathematica può essere resa dinamica.

Esempio 1: semplificare la comprensione di un concetto.

Plot[Sin[x],{x,0,5},PlotRange->{-5,5}]

Voglio introdurre il concetto di frequenza:

Plot[Sin[3 x],{x,0,5},PlotRange->{-5,5}]

e ampiezza:

Plot[3 Sin[3 x],{x,0,5},PlotRange->{-5,5}]

Se voglio rendere più veloce il cambiamento al fine di poter concentrare poi la spiegazione sui due concetti, posso usare una Manipulate che mi permette di gestire in automatico i due parametri ampiezza e frequenza:

Manipulate[
Plot[amp Sin[freq x],{x,0,5},PlotRange->{-5,5},ImageSize->Large],
{{amp,1,"Ampiezza"},1,5},
{{freq,1,"Frequenza"},1,5}]

Qualche ulteriore abbellimento:

Manipulate[Plot[amp funzione[freq x],{x,0,5},PlotRange->{-5,5},Filling->Axis,PlotStyle->pcol,FillingStyle->fcol,ImageSize->Large],
{{amp,1,"Ampiezza"},1,5},
{{freq,1,"Frequenza"},1,5},{{funzione,Sin,"Funzione"},{Sin,Cos,Tan,Csc,Sec}},{{pcol,Green,"Colore linea"},Red},{{fcol,LightGreen,"Riempimento"},LightRed}]

Tutto si può rendere dinamico: esempi di base

Esempio 2: un semplice esercizio.

Clear[a,b,c,x];
Manipulate[
Panel[Grid[{{"Equazione di partenza ", a (x^2)+b x +c },
{"Discriminante ((b^2)-4 a c)",b^2-4a c},
{"Soluzioni ",Replace[Reduce[a x^2+b x +c ==0,x,Reals], False->"Nessuna"]}}, Alignment->Left]],
{a,-5,5,1},
{b,-5,5,1},
{c,-5,5,1}]

Volendo posso impostare un valore di partenza per ciascun parametro/slider:

Clear[a,b,c,x];
Manipulate[
Panel[Grid[{{"Equazione di partenza ", a (x^2)+b x +c },
{"Discriminante ((b^2)-4 a c)",b^2-4a c},
{"Soluzioni ",Replace[Reduce[a x^2+b x +c ==0,x,Reals], False->"Nessuna"]}}, Alignment->Left]],
{{a,-1},-5,5,1},
{{b,1},-5,5,1},
{{c,-3},-5,5,1}]

Tutto si può rendere dinamico: esempi di base

Esempio 3: un calcolo racchiuso in una tabella.

Manipulate[
Grid[Prepend[Table[{i,m,(i^m)},{i,1,n}],{"n","m", "(n^m)"}]],
{n,1,20,1},{m,1,100,1}]

Con alcune opzioni aggiuntive possiamo migliorarne anche l’aspetto:

Manipulate[
Grid[
Prepend[Table[{i,m,(i^m)},{i,1,n}],{Style["n",Bold, Red],Style["m",Bold, Red], Style["(n^m)",Bold, Red]}], 
Alignment->{{Left,Left,Right},Automatic},Frame->All,
ItemStyle->{Blue,FontFamily->"Helvetica"},Background->LightGray],
{{n,5,"Base"},1,20,1},{{m,50,"Esponente"},1,100,1}]

Tutto si può rendere dinamico: esempi di base

Esempio 4: modificare l’ordine delle righe in una tabella.

Manipulate[
Grid[
Prepend[SortBy[{{"A",1,2},{"C",3,0},{"B",5,6}},(#[[sort]]&)],{"C1","C2","C3"}]],
{{sort,1,"Ordina per"},{1->"C1",2->"C2",3->"C3"}}]

Tutto si può rendere dinamico: esempi di base

Esempio 4: un data fitting manuale.

dati=Table[{x,2.5x^2-8x+1.87+RandomReal[{-1,1}]},{x,-2,5,0.05}];

ListPlot[dati,ImageSize->Large]

Manipulate[
Show[
ListPlot[dati,ImageSize->Large],
Plot[a x^2+b x+c,{x,-2,5},PlotStyle->{Thick,Red},ImageSize->Large],PlotRange->{{-2,5},{-40,40}}],
{a,-10,10},
{b,-10,10},
{c,-10,10}]

Tutto si può rendere dinamico: esempi di base

Esempio 5: una interpolazione manuale.

Manipulate[
Plot[InterpolatingPolynomial[pts,x],{x,-2,2},PlotRange-> {{-2,2},{-10,10}},Filling->Axis,FillingStyle->LightGreen,ImageSize->Large],{{pts,{{-0.25,0.86},{0.53,0.08},{0.97,0.73},{0.12,0.10},{0.78,0.52}}},{-2,-10},{2,10},Locator,LocatorAutoCreate->True}]

Tutto si può rendere dinamico: esempi di base

Esempio 6: una texture dinamica.

clock:=Module[{hour,min,sec,ht,mt,st},{hour,min,sec}=Take[DateList[],-3];ht=(π/2)-((hour π)/6)-((min π)/360);mt=(π/2)-((min π)/30);st=(π/2)-(1/30) π Floor[sec];Graphics[{AbsoluteThickness[5],Arrowheads[Large],Arrow[{{0,0},0.6 {Cos[ht],Sin[ht]}}],Arrow[{{0,0},0.9 {Cos[mt],Sin[mt]}}],PointSize[Large],Table[Point[0.9 {Cos[i],Sin[i]}],{i,0,2 π,(π/6)}],Point[{0,0}],Circle[],Red,Line[{{0,0},0.85 {Cos[st],Sin[st]}}]}]]

Dynamic[Refresh[clock,UpdateInterval->0]]

vtc={{0,0},{1,0},{1,1},{0,1}};
coords={{{0,0,0},{0,1,0},{1,1,0},{1,0,0}},{{0,0,0},{1,0,0},{1,0,1},{0,0,1}},{{1,0,0},{1,1,0},{1,1,1},{1,0,1}},{{1,1,0},{0,1,0},{0,1,1},{1,1,1}},{{0,1,0},{0,0,0},{0,0,1},{0,1,1}},{{0,0,1},{1,0,1},{1,1,1},{0,1,1}}};
Dynamic[Graphics3D[{Dynamic[Texture[clock],UpdateInterval->1],Polygon[coords,VertexTextureCoordinates->Table[vtc,{6}]]},Lighting->"Neutral",Boxed->False]]

Tutto si può rendere dinamico: esempi di base

Esempio 6: integrazione con le banche dati.

Manipulate[
Grid[Prepend[Outer[CountryData[#1,#2]&,CountryData[continent],{"Name","Area","Population"}],{"Country","Area","Population"}],
Alignment->Left,BaseStyle->{FontFamily->"Helvetica"},Frame->All,Background->{None,{LightBlue,{LightYellow}}}],
{{continent,"Europe","Continent"},DeleteCases[CountryData["Continents"],"Antarctica"]}]

Tutto si può rendere dinamico: esempi di base

Esempio 7: dinamicità ed interattività non significa solo Manipulate & Dynamic.

Ci sono molte altre funzionalità che contribuiscono a rendere Mathematica un ambiente estremamente flessibile e versatile per la creazione di applicazioni user-friendly.
Vediamo alcuni esempi.

OpenerView

OpenerView[{Dynamic[DateString[],UpdateInterval->1],Dynamic[clock,UpdateInterval->1]}]

Tooltip

data=Tooltip[CountryData[#,"LiteracyFraction"],Framed@
Column[{
Style[CountryData[#,"Name"],Bold],
CountryData[#,"Flag"]}]]&/@CountryData["Africa"];
BarChart[{data},PlotLabel->Style["Tasso di alfabetizzazione nei paesi Africani",FontFamily->"Arial",Bold,24]]

Visualizzatori come TabView e FlipView

TabView[Map[Tooltip[Show[CountryData[#,"Shape"],ImageSize->50],#]->DateListPlot[CountryData[#,{{"GDP"},{1970,2010}}]]&,CountryData["GroupOf8"]]]

FlipView[Row[{#,"\t",Rasterize@CountryData[#,"Shape"]}]&/@CountryData["Europe"]]

Mouseover

data=RandomReal[{0,10},1000];
Mouseover[ListPlot[data],BarChart[BinCounts[data,{0,10,1}]]]

data=RandomReal[10,{50,2}];
Mouseover[ListPlot[data],Tooltip[ListLinePlot[data[[Last@FindShortestTour[data]]]],"Percorso minimo"]]

OpenerView[{Dynamic[DateString[],UpdateInterval->1],Dynamic[clock,UpdateInterval->1]}]

Alcuni trucchi

Personalizzazione della posizione dei controllers.

In alcuni casi il modo in cui Manipulate dispone i controller potrebbe non soddisfare le esigenze dell’utente. Per ovviare a questo problema si può usare il costrutto Control che ci permette di personalizzare in maniera più flessibile i controller che governano le variabili. Ovviamente bisogna scrivere del codice in più e comporre manualmente ogni singolo pezzo dell’applicazione.

Manipulate[x,{x,0,1}]

Manipulate[x,Control[{x,0,1}]]

Manipulate ha delle opzioni che ci permettono di dire che tipo di controller utilizzare e dove collocarli rispetto al riquadro principale (Left, Right, Top, Bottom) ma non ci permette di modificarne altre disposizioni. Facciamo alcuni esempi.

Manipulate[
Plot[a Cos[b (t-c)],{t,0,2 π},PlotRange->12],
{a,1,12},
{b,1,12},
{c,1,12}]

Posso spostare i controller in altri punti. Nota: per semplificarne la visualizzazione uso una Manipulate di Manipulate ;-)

Manipulate[
Manipulate[
Plot[a Cos[b (t-c)],{t,0,2 π},PlotRange->12],
{a,1,12},
{b,1,12},
{c,1,12}, ControlPlacement->posizione],
{posizione,{Left,Top,Right,Bottom}}]

Si noti in particolare come sono “scomode” le posizioni Left e Right.
Proviamo il caso Left e proviamo a specificare che gli slider devono essere verticali, così forse l’apparenza migliora.

Manipulate[
Plot[a Cos[b (t-c)],{t,0,2 π},PlotRange->12],
{a,1,12},
{b,1,12},
{c,1,12},
ControlPlacement->Left,
ControlType->VerticalSlider]

Bene, anzi male: Manipulate non ci soddisfa con le impostazioni di default dei controller. Possiamo ricorrere a Control.

Manipulate[Plot[a Cos[b (t-c)],{t,0,2 π},PlotRange->12],
Grid[{{"amp","freq","phase"},
{Control[{{a,3,Null},1,12,ControlType-> VerticalSlider}],
Control[{{b,3,Null},1,12,ControlType-> VerticalSlider}],
Control[{{c,3,Null},1,12,ControlType-> VerticalSlider}]}}],
ControlPlacement-> Left]

Un esempio leggermente più complesso. In questo caso è fondamentale non solo la posizione dei controller ma anche il loro raggruppamento in diverse sezioni, altrimenti l’utente potrebbe vedere troppi bottoni in una sola volta e fare confusione.

Manipulate[
Plot[amp f[freq x],{x,0,6},PlotStyle->{color,Dashing[dashing],Thickness[thickness]},Axes->axes,Frame->frame,AxesOrigin->axesorigin,PlotLabel->f,ImageSize->Large],
{f,{Sin,Cos,Tan}},
TabView[{
"Funzione" -> Column[{Control[{freq,1,5}],Control[{amp,1,5}]}],"Assi e frame" -> Column[{Control[{axes,{True,False}}],Control[{frame,{False,True}}],Control[{axesorigin,{0,0},{6,1}}]}],
"Stile" -> Column[{Control[{color,Blue}],Control[{dashing,0,0.1}],Control[{thickness,0.001,0.1}]}]}, ImageSize -> Automatic]]

Alcuni trucchi

Salvare le definizioni che intercorrono nella Manipulate.
Consideriamo un esempio di Manipulate dove abbiamo bisogno di definire una nostra funzione per poter eseguire dei calcoli (in questo esempio il calcolo dell’area di un triangolo dati i tre vertici).

TriangleArea[{v1_,v2_,v3_}]:=Abs[Det[Join[Transpose[{v1,v2,v3}],{{1,1,1}}]]]/2

TriangleArea[{{(Subscript[x, 1]),(Subscript[y, 1])},{(Subscript[x, 2]),(Subscript[y, 2])},{(Subscript[x, 3]),(Subscript[y, 3])}}]//TraditionalForm

Ora con la Manipulate vogliamo rendere dinamico il calcolo facendo variare all’utente la posizione dei vertici.

Manipulate[
Graphics[{Pink,Polygon[pts]},PlotRange->1,
PlotLabel->StringForm["Triangle area = `1`",TriangleArea[pts]]],
{{pts,{{0,0},{1,0},{0,1/2}}},Locator}]

Cosa succede se chiudo il kernel?

Quit[]

L’alternativa è data dall’opzione SaveDefinitions che permette di salvare tutto il codice necessario al suo funzionamento dentro la Manipulate stessa.

TriangleArea[{v1_,v2_,v3_}]:=Abs[Det[Join[Transpose[{v1,v2,v3}],{{1,1,1}}]]]/2

Manipulate[
Graphics[{Pink,Polygon[pts]},PlotRange->1,
PlotLabel->StringForm["Triangle area = `1`",TriangleArea[pts]]],
{{pts,{{0,0},{1,0},{0,1/2}}},Locator},
SaveDefinitions->True
]

Quit[]

Un’altra possibilità è data dall’opzione Initialization

Manipulate[
Graphics[{Pink,Polygon[pts]},PlotRange->1,
PlotLabel->StringForm["Triangle area = `1`",TriangleArea[pts]]],
{{pts,{{0,0},{1,0},{0,1/2}}},Locator},
Initialization:>(TriangleArea[{v1_,v2_,v3_}]:=Abs[Det[Join[Transpose[{v1,v2,v3}],{{1,1,1}}]]]/2)
]

Alcuni trucchi

Evitare continue ed inutili valutazioni del corpo di una Manipulate.

Frequentemente capita che la Manipulate si comporta apparentemente in modo strano, ossia valuta costantemente il suo corpo anche quando non dovrebbe perchè nessun controller viene toccato, e questo rallenta tutte le altre operazioni.
Vediamo bene cosa accade in questi casi.

Manipulate[
f[x_]:=x^3;
Graphics[{Thickness[0.01],Line[{{0,0},{n,f[n]}}]},PlotRange->1],
{n,-1,1}]

In effetti Manipulate si comporta correttamente secondo il suo principio di funzionamento. Infatti, il suo corpo

f[x_]:=x^3;
Graphics[{Thickness[0.01],Line[{{0,0},{n,f[n]}}]},PlotRange->1]

viene rivalutato, ma poi non smette più di essere rivalutato perchè esso modifica se stesso. Manipulate esegue il refresh del corpo ogni qualvolta esso subisce una variazione a causa di una qualsiasi modifica eseguita dal kernel o dal front end stesso (i controller). Ebbene assegnando un valore ad n si modifica il Graphics che richiamando f(n) modifica (ossia valuta) la funzione f, la quale fa scattare la modifica della Graphics e così in un loop infinito.
Per ovviare questo problema si può usare Module per isolare le variabili che non devono entrare nella “giostra” dei refresh.

Manipulate[
Module[{f},
f[x_]:=x^3;
Graphics[{Thickness[0.01],Line[{{0,0},{n,f[n]}}]},PlotRange->1]],
{n,-1,1}]

Questa volta f non fa più scattare il refresh perchè essendo locale al Module, una volta valutato il corpo la f viene rimossa ed il grafico viene restituito. In alternativa, Manipulate consente di esplicitare direttamente quali sono le variabili da cui deve dipendere l’aggiornamento tramite l’opzione TrackedSymbols

Manipulate[
f[x_]:=x^3;
Graphics[{Thickness[0.01],Line[{{0,0},{n,f[n]}}]},PlotRange->1],
{n,-1,1}, TrackedSymbols->{n}]

Alcuni trucchi

Dynamic al posto di Manipulate

Manipulate ha una sua struttura ben precisa del tipo

Manipulate[
                        espressione(i)_da_animare,
                        controller
                       ]
In alcuni casi questa struttura potrebbe essere eccessivamente rigida perchè, ad esempio, vorremmo poter collocare un controller in una posizione diversa.
Una possibile alternativa in molti casi è data dalla Dynamic stessa come sostituto della Manipulate (d’altronde Manipulate viene convertita automaticamente in Dynamic dal sistema).

Esempio 6: un controller dentro il grafico.

Voglio creare un grafico dinamico che mi permetta di scegliere se vedere o meno alcune proprietà, ma non voglio una sovra-struttura di tipo Manipulate

Manipulate[Plot[Cos[x],{x,-2,2},Axes->assi,ImagePadding->0],{assi,{False,True}}]

Se voglio il grafico senza la struttura della manipulate devo decidere quale controller utilizzare (Checkbox), costruire un elemento che lo contenga (Panel) e decidere dove collocarlo rispetto al grafico (Inset)

Dynamic[Plot[Cos[x],{x,-2,2},Axes->assi,ImagePadding->0,Epilog->Inset[Panel[Column[{"Disegna assi",Checkbox[Dynamic[assi]]}]],{1.5,.8}]]]

Alcuni trucchi

Dynamic è più flessibile di Manipulate

Quando si raggiunge una certa dimestichezza con le espressioni dinamiche di Manipulate, ci si rende conto che Dynamic per certi versi è più flessibile, in quanto è un costrutto più elementare e si può facilmente applicare a numerose espressioni o parti di esse.

Esempio 7: variabili con pedici dinamici.

{n=1000};
Dynamic[Panel[Column[{Slider[Dynamic[n],{1,(10^5),1}],(Subscript[p, Dynamic[n]])⟶Dynamic[Prime[n]]}]]]

Applicare funzioni prima, dopo e durante la manipolazione dinamica

Dynamic permette di aggiungere una funzione da applicare in vari momenti dell’interazione, utile in alcuni casi per ottimizzare la modifica delle variabili dinamiche. Vediamo due esempi.

In questo primo esempio, vogliamo creare un locator all’interno di un grafico ma lo vogliamo anche vincolare a rimanere sulla circonferenza.

p={0,1};
Graphics[{Dashed,Circle[],PointSize[0.1],Point[Dynamic[p]]},ImageSize->Tiny,PlotRange->1.2]

Di default Point[Dynamic[p]] ci fornisce un locator, ma ora dobbiamo vincolarlo a rimanere sulla circonferenza. Per fare questo possiamo usare Normalize per normalizzare il vettore rappresentato da p. Dunque abbiamo bisogno di applicare Normalize al valore di p ogni volta che muoviamo il locator. In casi come questi si usano gli argomenti aggiuntivi di Dynamic.

p={0,1};
Graphics[{Dashed,Circle[],PointSize[0.1],Point[Dynamic[p,(p=Normalize[#])&]]},ImageSize->Tiny,PlotRange->1.2]

Graphics[Locator[Dynamic[p,(p=Normalize[#])&]],PlotRange->2]

In questo altro esempio la funzione serve perchè altrimenti il secondo slider tenterebbe di assegnare un valore alla espressione (1-x)

{Slider[Dynamic[x]],Slider[Dynamic[1-x]]}

{Slider[Dynamic[x]],Slider[Dynamic[1-x,(x=1-#)&]]}

Alcuni trucchi

Dynamic è più flessibile di Manipulate

Esempio 8: monitorare una computazione tramite finestre con aggiornamenti dinamici.

i=2π;
CreatePalette[Dynamic[Plot[Cos[x],{x,-i,i},PlotRange->{{-10,10},{-1,1}}]]];
CreatePalette[Dynamic[Plot[Sin[x],{x,-i,i},PlotRange->{{-10,10},{-1,1}}]]];
CreatePalette[Dynamic[Plot[Tan[x],{x,-i,i},PlotRange->{{-10,10},{-10,10}}]]];
Table[i=RandomReal[{1,10}];Pause[1],{20}]

Demonstrations: esempi avanzati

Sul sito www.demonstrations.wolfram.com, si possono trovare migliaia (oltre 7000) di applicazioni dinamiche ed interattive sviluppate con Mathematica da utenti di tutto il mondo.