I solved a linear bi-objective mixed integer problem and I want to plot the results. results include lines and points. for example
list=[([0.0; 583000.0], 0), ([190670.0; 149600.0], 0), ([69686.0, 385000.0], 1), ([33296.0, 484000.0], 1), ([136554.0, 2.38075e5], 1), ([24556.0, 503800.0], 0), ([47462.0, 437800.0], 1), ([129686.0, 253000.0], 1), ([164278.0, 178200.0], 1)]
In this list third point ([69686.0, 385000.0], 1) second element 1 is determined that this point connected by a line to prior point ([190670.0; 149600.0], 0) is connected to second point by a line.
I coded that as follow:
using JuMP,Plots
list=[([0.0, 583000.0], 0), ([24556.0, 503800.0], 0), ([33296.0, 484000.0],1), ([47462.0, 437800.0], 1), ([69686.0, 385000.0], 1), ([129686.0, 253000.0], 1), ([136554.0, 23805.0], 1), ([164278.0, 178200.0], 1), ([190670.0, 149600.0], 0)]
x=zeros(1,1)
for i=1:size(list,1)
x=[x;list[i][1][1]]
end
row=1
x = x[setdiff(1:end, row), :]
y=zeros(1,1)
for i=1:size(list,1)
y=[y;list[i][1][2]]
end
row=1
y = y[setdiff(1:end, row), :]
for i=2:size(list,1)
if list[i][2]==0
plot(Int(x[i]),Int(y[i]),seriestype=:scatter)
plot(Int(x[i+1]),Int(y[i+1]),seriestype=:scatter)
end
if list[i][2]==1
plot(Int(x[i]),Int(y[i]))
plot(Int(x[i+1]),Int(y[i+1]))
end
end
but it is not worked. would you please help me.
thanks
You can simply push each line segment's x and y values to two separate arrays, x and y in the code below. After each line segment's values (i.e. x1 and x2 or y1 and y2) put a NaN into the arrays. This will prevent connecting a line segment to the next one if there should not be a connection. (for example, the case you see 1 and then a 0). And finally plot(x, y).
The following code snippet does it. Note that allx and ally are used to hold all points regardless of connection status. You may want to exclude connected points from them. x and y holds connected line segments.
using Plots
x, y, allx, ally = Float64[], Float64[], Float64[], Float64[]
# iterate through list
for i = 1:length(list)-1
if list[i+1][2] == 1
# push x1 from the first point, x2 from the second and a `NaN`
push!(x, list[i][1][1], list[i+1][1][1], NaN)
# push y1, y2, `NaN`
push!(y, list[i][1][2], list[i+1][1][2], NaN)
end
push!(allx, list[i][1][1])
push!(ally, list[i][1][2])
end
push!(allx, list[end][1][1])
push!(ally, list[end][1][2])
# scatter all points
scatter(allx, ally)
# plot connections with markers
plot!(x, y, linewidth=2, color=:red, marker=:circle)
This should hopefully give you the plot you wanted.
If you happen to use Gadfly.jl instead of Plots.jl, you can get a similar plot with
using Gadfly
connectedpoints = layer(x=x, y=y, Geom.path, Geom.point, Theme(default_color="red"))
allpoints = layer(x=allx, y=ally, Geom.point)
plot(connectedpoints, allpoints)
As a side note if you plan to plot another series on top of a plot object already created, you should use plot! instead of plot.
Related
I was trying to learn trigonometry from the beginning.
so I can plot a curve by giving these as commands.
x1 = linspace(-2*pi, 2*pi)
y1 = cos(x1)
plot(x1, y1)
But If I try to do this,
x1 = linspace(-2*pi, 2*pi)
y2 = diff(cos(x1))
plot(x1, y1)
I receive an error stating
error: __plt2vv__: vector lengths must match error: called from __plt__>__plt2vv__ at line 487 column 5 __plt__>__plt2__ at line 247 column 14 __plt__ at line 112 column 18 plot at line 229 column 10
However, I do get values for y2 = diff(cos(x1)), I can't plot anything because of this error.
Note: I know the differentiation of sin(x) is cos(x) and I can just use cos(x), but can't I do it this way?
Tried diff(cos(90)) I got
ans = \[\](0x0)
diff is one element shorter than its input, because it it the differences [v(2)-v(1), v(3)-v(2), ...].
You need to do something like y2 = [NaN, diff(cos(x1))]; to pad your array to be the same size as x1.
Note that of course this causes an offset, you would need a central differencing method instead of a forward difference method (like diff) to keep things well-aligned.
If I want to draw a boundary line to separate two classes which is the result of my classifier. How to draw it?
The picture is the sample, the black line is the boundary I want to draw.
the green points is the boundary points. I want to draw a curve perfectly fit those points. But when I plot those curve, the result is the purple line which is not a curve.
Here is a reproducible example how to do it:
using Plots
x = rand(1000)
y = rand(1000)
color = [3 * (b-0.5)^2 < a - 0.1 ? "red" : "blue" for (a, b) in zip(x, y)]
y_bound = 0:0.01:1
x_bound = #. 3 * (y_bound - 0.5)^2 + 0.1
scatter(x, y, color=color, legend=false)
plot!(x_bound, y_bound, color="green")
and you should get a plot like:
The crucial thing here is to make your boundary points ordered (i.e. they must be ordered in the vectors properly so that when you plot a line you connect proper points). In my example I achieved it by varying the y-dimension and calculating the x dimension.
In more complex cases it will be better to use contour plot, e.g.:
x = 1:0.1:8
y = 1:0.1:7
f(x, y) = begin
(3x + y ^ 2) * abs(sin(x) + cos(y)) - 40
end
X = repeat(reshape(x, 1, :), length(y), 1)
Y = repeat(y, 1, length(x))
Z = map(f, X, Y)
contour(x, y, Z, levels=[0], color="green", width=3)
x_s = 7 .* rand(1000) .+ 1
y_s = 6 .* rand(1000) .+ 1
color = [f(a, b) > 0 ? "red" : "blue" for (a, b) in zip(x_s, y_s)]
scatter!(x_s, y_s, color=color, legend=false)
and you should get something like:
However, as you can see this time for the best results it is best to pass scores to contour and specify the classification threshold as level.
I guess your TA asked you to conduct a grid search for this question.
The meaning of grid search is not searching over the data point you have, but searching over whole coordinate. (I.e. From (0,0), (0,1), (0,2) to (0,100), then to (1,0), (1,1) and so on.) You may change the distance between each point when you conduct a grid search.
In your case, you need to solve the equation d_1(X) = d_2(X). So what you need to do is to simulate some points (like the above example), then put those points into |d_1(X) - d_2(X)|, and pick the points that bring you to a value that is smaller than epsilon (a self-given small number like 0.05 or 0.1). Then use Plot() to connect them.
This is not the most efficient way to create the boundary but this is what you learnt in your tutorial. You may also try contour().
I watched and tried to understand bunch of sites and videos about this, and I came into a weird conclusions and some questions. I need some help to explain which one of the method is right, or even both of them are right (but I got different result from each methods).
I'm sorry that I'm bad at explaining things, the first method is solve the equations normally. But, here the link for the video I tried to learn from
https://www.youtube.com/watch?v=o7CfCDkRwfY
Second method is to do cross product for the direction and find the point by set one of the variables as 0. https://www.youtube.com/watch?v=jozabh0lFmo
I tried for this example
x+2y+z−1=0
2x+3y−2z+2=0
and turned out for different answers. Is both of the method are correct, or which one? Thank you.
You have two equations with three unknowns.
You can eliminate one variable and solve for a relationship between the remaining two. Let's eliminate z.
Multiply the first equation by 2:
2x + 4y + 2z = 2
Add this to the second equation:
4x + 7y = 0
You can solve for y as a function of x:
y = -4x/7
Substitute this back into the first equation:
x - 8x/7 + z = 1
Simplify by combining the first and second terms:
-x/7 + z = 1
Solve for z:
z = 1 + x/7
Now you have an equation for the line in 3D space.
-inf <= x <= +inf
y = -4x/7
z = 1 + x/7
Both your equations are satisfied by these two points. Since two points are enough to define a line in Euclidean space I'd say I've got the correct answer.
This line goes through the point (0, 0, 1). It also goes through (7, -4, 2)
Here's a parametric representation of that line for -inf <= t <= +inf:
(x, y, z) = (0, 0, 1) + t*(7, -4, 1)
You can see that when t = 0 (x, y, z) = (0, 0, 1) (first point above) and when t = 1 (x, y, z) = (7, -4, 2) (second point above).
I didn't look at either of your videos. This is how I'd solve it.
This is high school algebra.
Suppose you have two lines, L1 and L2, which for each x value (x1 and x2 for example) they have known points at L1={(x1,L1_y1), (x2,L1_y2)}, and L2={(x1,L2_y1), (x2,L2_y2)}. By joining these points they may or may not have an intersection at some x3 where x1
Now suppose you want to know the maximum at any x value (not restricted to just x1, x2 etc, but anywhere along the axis) of both of these lines. Obviously it is often trivial to calculate for just a few lines, and a few different x value, but in my case I have several tens of thousand x values and a few lines to check it against, so it can't be done manually.
In R, is there some code which will calculate the maximum at any given point x3?
An example of this can be seen here with L1={(1,1), (2,4)}, and L2={(1,4),(2,1)}, illustrated by:
Here the intersection of these lines is at (1.5, 2.5). L2 is the maximum before this, and L1 after. This maximum line is shown in red below.
As you can see, it isn't enough just to take the max at every point and join these up, and so it will need to consider the lines as some form of function, and then take the maximum of this.
Also, as mention before as there are several thousand x values it will need to generalise to larger data.
To test the code further if you wish you can randomly generate y values for some x values, and it will be clear to see from a plot if it works correctly or not.
Thanks in advance!
Defining points constituting your lines from the example
L1 <- list(x = c(1, 2), y = c(1, 4))
L2 <- list(x = c(1, 2), y = c(4, 1))
defining a function taking a pointwise maximum of two functions corresponding to the lines
myMax <- function(x)
pmax(approxfun(L1$x, L1$y)(x), approxfun(L2$x, L2$y)(x))
This gives
plot(L1$x, L1$y, type = 'l')
lines(L2$x, L2$y, col = 'red')
curve(myMax(x), from = 1, to = 2, col = 'blue', add = TRUE)
Clearly this extends to more complex L1 and L2 as approxfun is just a piecewise-linear approximation. Also, you may add L3, L4, and so on.
My dataset is a 3 dimensional array (30,15,4) representing temperature through the water column at four different depths (0.2 (layer1),0.4(layer2),0.6(layer3),0.8(layer4)). Thus, I am trying to get 3d plots with 4 layers.So far, I have used slice3Drgl function. However, I have realized that in the plots I got, the 2nd and 3rd layer look the same (T data from the 0.4 depth is plotted twice), and the fourth layer (upper layer in plot) shows T data belonging to the 0.6 depth.
This is my code:
dd<-array(d$T,dim=c(30,15,4))
x = seq(0.126,3.780, by=0.126)
y=seq(0.125,1.875,by=0.125)
z = seq(0.2,0.8,by=0.2)
grid<-mesh(x,y,z)
colvar<-with(grid,dd)
col=jet.col(100)
slice3Drgl (x, y, z, xs=NULL, ys=1,zs=c(0.2,0.4,0.6,0.8),colvar = colvar, col=col, clim = c( -1.392,0),theta = 60,smooth=TRUE,
colkey(clim = c(-1.392,0),at = do.breaks(c(-1.392,0), 2)))
This is the plot I get:
I have checked the data and its correct, no repeated T data in 2nd and 3rd layers.
In addition when defining zs as:
zs<-z[seq(1,length(z),len=4)]
The 3d plot improves a bit. I can see the correct T data on 1,2,3 layers. But 4th layer still shows T data corresponding to 0.6 depth, instead to 0.8 depth (the 4th layer).
Hope my question is more or less clear and that someone can give me some useful insight,
there is not too much information about this function in the web unfortunately.
Thanks in advance,
Best,
Amaia
This error originates with zs parameter for which package document provide no information. Here is a work around that I have used in the past:
dt<-seq(0.01,27, by=0.01)
dd<-array(dt,dim=c(30,15,5))
x = seq(0.126,3.780, by=0.126)
y=seq(0.125,1.875,by=0.125)
z = seq(0.2,1.0,by=0.2)
grid<-mesh(x,y,z)
colvar<-with(grid,dd)
col=jet2.col(100)
slice3Drgl (x, y, z, xs=NULL, ys=NULL,zs=z,zlim=c(0.2,0.8),colvar = colvar, col=col, clim = c(0,18),theta = 60,smooth=FALSE,
colkey(clim = c(0,18),at = do.breaks(c(0,18), 2)))
Basically all you need is add a dummy z layer into the data and then ignore it during the plotting by setting the zlim.
I hope this helps.