"Tag Part in (...) is Protected" - wolfram-mathematica

I am currently writing a module that's supposed to take some data points of 2-dimensional function (a 3 x N matrix) and draw contour plot of approximation based on those points (functions and variables for fitting are provided by user).
The "header" looks like this:
project4[dataPoints_, functionList_, fittingVarsList_, plotArgs___] :=
Module[{fitFunc, functionContourPlot, dataPointsXY, pointsPlot,
xList, yList},
Example of usage:
project4[data, {1, x, y, x y, x^2, y^2}, {x, y}]
(where data = {{x1,y1,f1}...})
After checking if the arguments are valid I do:
fitFunc = Fit[dataPoints, functionList, fittingVarsList];
To obtain the approximation.
Then I want to obtain plot of it by doing:
functionContourPlot = ContourPlot[fitFunc, {fittingVarsList[[1]], xMin, xMax},{fittingVarsList[[2]],yMin, yMax};
Which leads to an errors:
ContourPlot::write: Tag Part in {x,y}[[1]] is Protected. Show::gcomb:
"Could not combine the graphics objects in
Show[ContourPlot[fitFunc$2187,{{x,y}[[1]],xMin,xMax},{{x,y}[[2]],yMin,yMax}],"
What am I doing wrong?

The problem is ContourPlot having attribute HoldAll, which prevents Part evaluating.
Attributes#ContourPlot
You can fix it like this.
data = {{6, 4, 7.92}, {6, 5, 9.31}, {6, 6, 9.74},
{7, 4, 11.24}, {7, 5, 12.09}, {7, 6, 12.62},
{8, 4, 14.31}, {8, 5, 14.58}, {8, 6, 16.16}};
fittingVarsList = {x, y};
{xMin, xMax} = Through[{Min, Max}#data[[All, 1]]];
{yMin, yMax} = Through[{Min, Max}#data[[All, 2]]];
fitFunc = Fit[data, {1, x, y}, {x, y}]
This reproduces the problem :-
functionContourPlot = ContourPlot[fitFunc,
{fittingVarsList[[1]], xMin, xMax},
{fittingVarsList[[2]], yMin, yMax}];
The problem can be fixed by using With to create local variables :-
functionContourPlot =
With[{a = fittingVarsList[[1]], b = fittingVarsList[[2]]},
ContourPlot[fitFunc, {a, xMin, xMax}, {b, yMin, yMax}]]
If you remove HoldAll from the attributes of ContourPlot the first version works ...
Unprotect#ContourPlot;
ClearAttributes[ContourPlot, HoldAll]
... but that would be reckless programming.

Related

Fitting data with exponential form

I'm newbie in Mathematica .I'm trying to fit data that ( i think) best fits on a exponential function. My code:
data = {{1, 0.5}, {10, 0.25}, {20, 0.2}, {60, 0.14}, {100, 0.1}, {500,
0.03}, {1000, 0.02}, {2000, 0.015}, {3000, 0.014}, {4000,
0.0125}};
line = FindFit[data, Exp[-bx], b, x]
but i get
FindFit::nrlnum: The function value s not a list of real numbers with dimensions {10} at {b} = {1.}
Any idea;
Change
line = FindFit[data, Exp[-bx], b, x]
to
line = FindFit[data, Exp[-b*x], b, x]

Mathematica: how to apply more than one rule at once

I have a list of points where each point is a list of its 3 coordinates: x,y and z.
But some of those points in their coordinates x and y are "bad" and I'd like to clean them. Is it possibile to write a single rule to do that? I've tried with:
cleanAdjustedPoints[adjustedPoints_List] := adjustedPoints /. {x_, y_, z_} /; x < 0 -> {0, y, z}; /; y > constB -> {x, constB, z};
and I've seen that only the first rule is applied to the points with bad x, while the ones with bad y do not change. Mathematica does not give a sintax error so I thought that it was right.
Any suggestions? thanks.
You just need to put the rules in a list. Also, note use of RuleDelayed (:>) which localises the variables x, y & z ensuring they don't pick up values from elsewhere in your program.
cleanAdjustedPoints[adjustedPoints_List] :=
adjustedPoints /. {{x_, y_, z_} /; x < 0 :> {0, y, z},
{x_, y_, z_} /; y > constB :> {x, constB, z}};
constB = 5;
cleanAdjustedPoints[{{-1, 2, 3}, {4, 5, 6}, {7, 8, 9}}]
{{0, 2, 3}, {4, 5, 6}, {7, 5, 9}}

Working with implicit functions in Mathematica

Can I plot and deal with implicit functions in Mathematica?
for example :-
x^3 + y^3 = 6xy
Can I plot a function like this?
ContourPlot[x^3 + y^3 == 6*x*y, {x, -2.7, 5.7}, {y, -7.5, 5}]
Two comments:
Note the double equals sign and the multiplication symbols.
You can find this exact input via the WolframAlpha interface. This interface is more forgiving and accepts your input almost exactly - although, I did need to specify that I wanted some type of plot.
Yes, using ContourPlot.
And it's even possible to plot the text x^3 + y^3 = 6xy along its own curve, by replacing the Line primitive with several Text primitives:
ContourPlot[x^3 + y^3 == 6 x y, {x, -4, 4}, {y, -4, 4},
Background -> Black, PlotPoints -> 7, MaxRecursion -> 1, ImageSize -> 500] /.
{
Line[s_] :>
Map[
Text[Style["x^3+y^3 = 6xy", 16, Hue[RandomReal[]]], #, {0, 0}, {1, 1}] &,
s]
}
Or you can animate the equation along the curve, like so:
res = Table[ Normal[
ContourPlot[x^3 + y^3 == 6 x y, {x, -4, 4}, {y, -4, 4},
Background -> Black,
ImageSize -> 600]] /.
{Line[s_] :> {Line[s],
Text[Style["x^3+y^3 = 6xy", 16, Red], s[[k]], {0, 0},
s[[k + 1]] - s[[k]]]}},
{k, 1, 448, 3}];
ListAnimate[res]
I'm guessing this is what you need:
http://reference.wolfram.com/mathematica/Compatibility/tutorial/Graphics/ImplicitPlot.html
ContourPlot[x^3 + y^3 == 6 x*y, {x, -10, 10}, {y, -10, 10}]

Update Manipulate[]'d plots when parameters change

I've been fighting with Mathematica's Manipulate function for the last few days for a project.
I'm working on tweaking assumptions and boundary conditions that go into a physical model. For this, I want to be able to plot different equations and adjust the parameters and have the graphs update on the fly. Manipulate seems to be the perfect tool for the job -- except that I can't get it to work. The plots won't update when the parameters are changed.
Basic example:
a =.;
b =.;
c =.;
func1[x_] := a*x;
func2[x_] := a*x^2 + b*x + c;
funcNamesList := {"Linear", "Quadratic"};
funcList := {func1[x], func2[x]}
Manipulate[
Plot[function, {x, -5, 5}], {function,MapThread[Function[#1 -> #2],
{funcList, funcNamesList}]}, {a, -5, 5}, {b, -5, 5}, {c, -5, 5},
LocalizeVariables -> False
]
I can get, for example, func1 to refresh by clicking func1, adjusting a, and then clickingfunc1 again, but I'm hoping to have it update when I adjust a because the real functions I'm using are rather temperamental with respect to their parameters.
-Because I'll be dealing with long functions that have different parameters, using a list of functions is useful.
EDIT:
In case it produces any ideas for anyone, here are some working examples of the individual components of what I want to do (from the Wolfram documentation):
Plot graphs and have them update when parameters are changed:
Manipulate[
Plot[Sin[a x + b], {x, 0, 6}], {{a, 2, "Multiplier"}, 1, 4},
{{b, 0, "Phase Parameter"}, 0, 10}
]
Note: This breaks when the function is taken outside:
func[x] := Sin[a x + b];
Manipulate[
Plot[func[x], {x, 0, 6}], {{a, 2, "Multiplier"}, 1, 4},
{{b, 0, "Phase Parameter"}, 0, 10}, LocalizeVariables -> False
]
Example of changing the function being plotted:
Manipulate[
Plot[f[x], {x, 0, 2 Pi}], {f, {Sin -> "sine", Cos -> "cosine", Tan -> "tangent"}}
]
Edit 2
Changed func2 from a*x^2 to a*x^2 + b*x + c to reflect the fact that the functions may have different parameters.
Edit 3 Added the tidbit I use to get nice names on the function buttons.
There are two problems that prevent your Manipulate statement from working.
First, while the Manipulate variable a is global due to the LocalizeVariables -> False setting, the Plot variable x is not. x is local to the Plot expression.
The second problem is that Manipulate, by default, assumes TrackedSymbols -> Full. This means that only symbols that explicitly appear in the manipulated expression are tracked. Note that a does not appear in the expression, so it is not tracked.
We can correct both problems thus:
a =.;
function =.;
func1[x_] := a*x;
func2[x_] := a*x^2;
funcList := {func1, func2}
Manipulate[
Plot[function[x], {x, -5, 5}], {function, funcList}, {a, -5, 5},
LocalizeVariables -> False, TrackedSymbols :> {a, function}
]
The changes are:
funcList was changed to {func1, func2}
The Plot expression was changed to function[x], thereby referencing the local x variable.
The Manipulate option TrackedSymbols :> {a, function} was added.
function is initially unset.
I'd do this in a slightly different way:
func1[x_, a_] := a*x;
func2[x_, a_] := a*x^2;
funcList = {func1, func2};
Manipulate[
Plot[Evaluate[function[x, b]],
{x, -5, 5},
PlotLabel \[Rule] funcList
],
{function, funcList},
{b, -5, 5}
]
but this may be unsuitable for what you want. Do your functions have different signatures?
EDIT: I've renamed the parameter to b to make it clearer that is it just a parameter being passed, as opposed to a global variable as you were using it.

Algorithm to find bijection between arrays

I have two arrays, say A={1, 2, 3} and B={2, 4, 8} (array item count and numbers may vary). How do I find a bijection between the arrays.
In this case, it would be f:A->B; f(x)=2^(x)
I don't think this problem has a general solution. You may try FindSequenceFunction, but it will not always find the solution. For the case at hand, you'd need a bit longer lists:
In[250]:= FindSequenceFunction[Transpose[{{1, 2, 3}, {2, 4, 8}}], n]
Out[250]= FindSequenceFunction[{{1, 2}, {2, 4}, {3, 8}}, n]
but
In[251]:= FindSequenceFunction[Transpose[{{1, 2, 3, 4}, {2, 4, 8, 16}}], n]
Out[251]= 2^n
You can also play with FindFit, if you have some guesses about the bijection:
In[252]:= FindFit[Transpose[{{1, 2, 3}, {2, 4, 8}}], p*q^x, {p, q}, x]
Out[252]= {p -> 1., q -> 2.}
As others have remarked, this problem is ill-defined.
Other possible functions that give the same results are (among probably infinite others): (8 x)/3 - x^2 + x^3/3, x + (37 x^2)/18 - (4 x^3)/3 + (5 x^4)/18, and (259 x^3)/54 - (31 x^4)/9 + (35 x^5)/54.
I found these solutions using:
n = 5; (* try various other values *)
A = {1, 2, 3} ; B = {2, 4, 8}
eqs = Table[
Sum[a[i] x[[1]]^i, {i, n}] == x[[2]], {x, {A, B}\[Transpose]}]
sol = Solve[eqs, Table[a[i], {i, n}], Reals]
Sum[a[i] x^i, {i, n}] /. sol
Sometimes not all of the a[i]'s are fully determined and you may come up with values of your own.
[tip: better not use variables starting with a capital letter in Mathematica so as not to get into conflict with reserved words]
Since you tag Mathematica, I'll use Mathematica functions as a reference.
If you are interested in an arbitrary fit of your data with a smooth function, you can use Interpolation. E.g.
a = {1, 2, 3}; b = {2, 4, 8};
f = Interpolation[Transpose[{a, b}]];
(* Graph the interpolation function *)
Show[Plot[f[x], {x, 1, 3}], Graphics[Point /# Transpose[{a, b}]],
PlotRange -> {{0, 4}, {0, 9}}, Frame -> Automatic, Axes -> None]
Interpolation uses piecewise polynomials. You can do the same in your favorite programming language if you happen know or are willing to learn a bit about numerical methods, especially B-Splines.
If instead you know something about your data, e.g. that it is of the form c d^x, then you can do a minimization to find the unknowns (c and d in this case). If your data is in fact generated from the form c d^x, then the fit will be fairly, otherwise it's the error is minimized in the least-squares sense. So for your data:
FindFit[Transpose[{a, b}], c d^x, {c, d}, {x}]
reports:
{c -> 1., d -> 2.}
Indicating that your function is 2^x, just as you knew all along.

Resources