Recursion in Prolog when calculating coordinates of koch curve - recursion

I have to calculate coordinates of a koch curve in Prolog and already got some nice and good
help here which really made it easier to understand how to decompose the problem into smaller problems.
I tried to do that but didn't come that far. I must admit I'm really quarreling with recursions and don't come behind what I'm doing wrong.
I have to programm a koch-curve of Level N which should start at (Sx,Sy) and end at (Ex,Ey).
The advice I already got was to do the implementation in the following way:
generatelines(N, S, E, Segments) :-
segments(S, E, InitialSegments),
iterate_level(N, InitialSegments, Segments).
I started to do it like this:
segments(Ls1,Ls):-segments((Sx,Sy),(Ex,Ey),Ls).
segments((Sx,Sy),(Ex,Ey),Ls):-
X2 is Sx+(Ex-Sx)/3,
Y2 is Sy+(Ey-Sy)/3,
R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
Phi1 is atan((Y2-Sy)/(X2-Sx)),
X3 is X2 +R1*cos((Phi1-240)*pi/180),
Y3 is Y2 +R1*sin((Phi1+240)*pi/180),
X4 is X2+(X2-Sx),
Y4 is Y2+(Y2-Sy),
Ls=[
[(Sx,Sy),(X2,Y2)],
[(X2,Y2),(X3,Y3)],
[(X3,Y3),(X4,Y4)],
[(X4,Y4),(Ex,Ey)]
],
next_level_segments(Ls).
next_level_segments(Ls):-next_level_segments(Ls,List).
next_level_segments([[(Sx,Sy),(Ex,Ey)]|E],Ls):-
X2 is Sx+(Ex-Sx)/3,
Y2 is Sy+(Ey-Sy)/3,
R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
Phi1 is atan((Y2-Sy)/(X2-Sx)),
X3 is X2 +R1*cos((Phi1-240)*pi/180),
Y3 is Y2 +R1*sin((Phi1+240)*pi/180),
X4 is X2+(X2-Sx),
Y4 is Y2+(Y2-Sy),
append(Cs,[
[(Sx,Sy),(X2,Y2)],
[(X2,Y2),(X3,Y3)],
[(X3,Y3),(X4,Y4)],
[(X4,Y4),(Ex,Ey)],
Ls ],
next_level_segments(E,Cs).
next_level_segments([],_):-!.
append([],Ls,Ls).
append([X|As],Bs,[X|Cs]):- append(As,Bs,Cs).
When I'm trying to calculate segments((60,0),(-60,0),X)) without
the next_level_segments I get the right four coordinates between
the start-point (60,0) and (-60,0):
[[ (60, 0), (20, 0)],
[ (20, 0), (0.0, -34.64)],
[ (0.0, -34.64), (-20, 0)],
[ (-20, 0), (-60, 0)]]
With this pairs I would like to generate the next 4 coordinates between for example start point (60,0) and end point (20,0) using the auxiliary predicate next_level_segment.
When I look at the trace it seems that I'm (hopefully) not that wrong with my
implementation, but I'm not able to get those next 16 new coordinates and
I guess the problem is the way I'm doing the recursion.
Maybe somebody may give me some advice what I'm doing wrong.
Thanks

I don't know much about your problem domain, but I definitely see a problem in your code:
next_level_segments(Ls) :- next_level_segments(Ls,List).
You probably get a singleton variable "warning" here (every singleton variable warning should be regarded as an indication of a serious error in Prolog!). So you're going along, evaluating segments when Prolog gets to this line. Let me remove some intervening lines to highlight the issue:
segments((Sx,Sy),(Ex,Ey),Ls):-
Ls=[...],
next_level_segments(Ls).
So, at this point, for Prolog to prove segments/3, all it has to do is see if next_level_segments(Ls) succeeds. Because next_level_segments/1 essentially discards the binding of List (you could replace it with _), nothing happens here to propagate that information anywhere. This is probably the nut of your problem. You need to get the result of that and do something with it.

Related

How to indicate intersection points on graph?

I am using Insertion and Merge sort and trying to indicate the intersection point on the graph below. I found a possible solution on rosettacode, but a bit confusing for a newbie like me... Where should I look, do you guys know how to indicate it in Julia?
The output would is like
I am trying to show something like this
Your data has some noise, which means there might be more than one intersection point (all close). Assuming no noise, just two monotonically increasing functions, this should work:
using Plots
x = 1:5
y1 = x .+ 5
y2 = 3x
idx = argmin(abs.(y1-y2))
plot(x, [y1, y2], label=["y1", "y2"], markershape=:circle)
scatter!([x[idx]], [y1[idx]], label="intersection", markershape=:circle, markersize=10)
Note that this method gives you 1/4 possible points closest to the intersection. The intersection itself is not defined for functions only defined from discrete points. By changing the order of y1 and y2 in the code above you can get all 4 points. For fine enough discretization using one of those 4 points might be good enough for your needs.
A better approximation would be to use those 4 points to fit 2 lines, for y1 and y2, and find the intersection of those two lines analytically (e.g. with the equations y1=m1*x+b1, ...). But I leave this to you ;)

Prolog, diagonal distance

I have grid based map, and I'm trying to develop a predicate that gives me the diagonal distance between 2 points, this is what I have,
dist_diagonal((X,Y),(X,W),Passos,D):-
dist_ortogonal((X,Y),(X,W),D1),
D is D1 + Passos.
dist_diagonal((X,Y),(Z,Y),Passos,D):-
dist_ortogonal((X,Y),(Z,Y),D1),
D is D1 + Passos.
dist_diagonal((X,Y),(Z,W),Passos,_):-
X>Z,
Y<W,
Passos1 is Passos+1,
X1 is X-1,
Y1 is Y+1,
dist_diagonal((X1,Y1),(Z,W),Passos1,_).
dist_diagonal((X,Y),(Z,W),Passos,_):-
X<Z,
Y<W,
Passos1 is Passos+1,
X1 is X+1,
Y1 is Y+1,
dist_diagonal((X1,Y1),(Z,W),Passos1,_).
but when I try to test it :
dist_diagonal((5,4),(3,8),0,D).
I get true instead of a value for D
What's wrong with my predicate?
PS: I should add that I'm going to use this only with points that verrify Y<Z.
PS2: Notice that I'm calculating the distance using 8 kinds of movements, not the euclidean distance.Diagonal distance
You need to write : dist_diagonal((X,Y),(Z,W),Passos,D):- instead of dist_diagonal((X,Y),(Z,W),Passos,_):-
Your predicate is returning true since D could be anything (since you use anonymous variables '_').
So you need to write:
dist_diagonal((X,Y),(Z,W),Passos,D):-
X>Z,
Y<W,
Passos1 is Passos+1,
X1 is X-1,
Y1 is Y+1,
dist_diagonal((X1,Y1),(Z,W),Passos1,D).
dist_diagonal((X,Y),(Z,W),Passos,D):-
X<Z,
Y<W,
Passos1 is Passos+1,
X1 is X+1,
Y1 is Y+1,
dist_diagonal((X1,Y1),(Z,W),Passos1,D).
I wasn't able to test since I have no definition of dist_ortogonal/3 predicate but I wrote a simple version of it and it worked so it should be working fine.

R: Writing a recursive function for a Random Walk (initial values)

I'm a new user to R, and I am trying to create a function that will simulate a random walk. The issue for me is trying to integrate some initial values smoothly. Say I have this basic function.
y(t) = y(t-2) + eps(t)
Epsilon (or eps(t)) will be the randomness factor. I want to define y(-1)=0, and y(0)=0.
Here is my code:
ran.walk=function(n){ # 'n' steps will be the input
eps=rnorm(n) # creates a vector taking random values from N(0,1)
y= c(eps[1], eps[2]) # this will set up my initial vector
for (i in 3:n){
ytemp = y[i-2] + eps[i] ## !!! problem is here. Details below !!!
y= c(y, ytemp)
}
return(y)
}
I'm trying to get this start adding y3, y4, y5, etc, but I think there is a flaw in this design... I'm not sure if I should just set up two separate lines, with an if statement: testing if n is even or odd, perhaps with:
if i%%2 == 1 #using modulus
Since,
y1= eps1,
y2= eps2,
y3= y1 + eps3,
y4= y2 + eps4,
y5= y3 + eps5 and so on...
Currently, I see the error in my code.
I have y1, and y2 concatenated, but I don't think it knows how to incorporate y[1]
Can I define beforehand somehow y[-1]=0, and y[0]=0 ? I tried this also and got an error.
Thank you kindly in advance for any assistance. This is first times attempting a for loop with recursion.
-N (sorry for any formatting issues, I had a lot of problems getting this question to go through)
I found that your odd and even series is independent one of the other. Assuming that it is the case, I just split the problem in two columns and use cumsum to get the random walk. The final data frame include the random numbers and the random walk, so you can compare it is working properly.
Hoping it helps
ran.walk=function(n) {
eps=rnorm(ceiling(n / 2)*2)
dim(eps) <- c(2,ceiling(n/2))
# since each series is independent, we can tally each one in its own
eps2 <- apply(eps, 1, cumsum)
# and just reorganize it
eps2 <- as.numeric(t(eps2))
rndwlk <- data.frame(rnd=as.numeric(eps), walk=eps2)
# remove the extra value if needed
rndwlk <- rndwlk[1:n,]
return(rndwlk)
}
ran.walk(13)
After taking a break with my piano, it came to me. It's funny how simple the answer becomes once you discover it... almost trivial.
Setting the initial value to be a vector, that is:
[y(1) = y(-1) + eps(1), y(2)= y(0) + eps(2)]
everything works out. It is still true that the evens and odds don't interact, but there is no reason to specify any of that.
The method to split the iterations with modulus, then concatenating it back into the main vector would also work, but is unnecessary and more complicated. Shorter is better for users and computers. As Einstein said, make it as simple as possible, but no simpler.

Interpretation of logn^logn?

How should I interpret
How do I interpret this? One way is to take it as logn(logn) and other is . Both would be giving different answers.
For eg:
Taking base 2 and n=1024, in first case we get 10*10 as ans. In the second case, we get 10^10 as ans or am I doing something wrong?
From a programmer's viewpoing a good way to better understand a function is to plot it at different parts of its domain.
But what is the domain of f(x) := ln(x)^ln(x)? Well, given that the exponent is not an integer, the base cannot be smaller than 1. Why? Because ln(x) is negative for 0 < x < 1 and it is not even defined for x <= 0.
But what about x = 1. Given that ln(1) = 0, we would get 0^0, which is not defined either. So, let's plot f(x) for x between: 1.000001 and 1.1. We get:
The plot reveals that there would be no harm in extending the definition of f(x) at 1 in this way (let me use pseudocode here):
f(x) := if x = 1 then 1 else ln(x)^ln(x)
Now, let's see what happens for larger values of x. Here is a plot between 1 and 10:
This plot is also interesting because it exposes a singular behavior between 1 and 3, so let's plot that part of the domain to see it better:
There are a couple of questions that one could ask by looking at this plot. For instance, what is the value of x such that f(x)=1? Mm... this value is visibly between 2.7 and 2.8 (much closer to 2.7). And what number do we know that is a little bit larger than 2.7? This number should be related to the ln function, right? Well, ln is logarithm in base e and the number e is something like 2.71828182845904.... So, it looks like a good candidate, doesn't it? Let's see:
f(e) = ln(e)^ln(e) = 1^1 = 1!
So, yes, the answer to our question is e.
Another interesting value of x is the one where the curve has a minimum, which lies somewhere between 1.4 and 1.5. But since this answer is getting too long, I will stop here. Of course, you can keep plotting and answering your own questions as you happen to encounter them. And remember, you can use iterative numeric algorithms to find values of x or f(x) that, for whatever reason, appear interesting to you.
Because log(n^log n)=(log n)^2, I would assume that log n^log n should be interpreted as (log n)^(log n). Otherwise, there's no point in the exponentiation. But whoever wrote that down for you should have clarified.

Remove redundant points for line plot

I am trying to plot large amounts of points using some library. The points are ordered by time and their values can be considered unpredictable.
My problem at the moment is that the sheer number of points makes the library take too long to render. Many of the points are redundant (that is - they are "on" the same line as defined by a function y = ax + b). Is there a way to detect and remove redundant points in order to speed rendering ?
Thank you for your time.
The following is a variation on the Ramer-Douglas-Peucker algorithm for 1.5d graphs:
Compute the line equation between first and last point
Check all other points to find what is the most distant from the line
If the worst point is below the tolerance you want then output a single segment
Otherwise call recursively considering two sub-arrays, using the worst point as splitter
In python this could be
def simplify(pts, eps):
if len(pts) < 3:
return pts
x0, y0 = pts[0]
x1, y1 = pts[-1]
m = float(y1 - y0) / float(x1 - x0)
q = y0 - m*x0
worst_err = -1
worst_index = -1
for i in xrange(1, len(pts) - 1):
x, y = pts[i]
err = abs(m*x + q - y)
if err > worst_err:
worst_err = err
worst_index = i
if worst_err < eps:
return [(x0, y0), (x1, y1)]
else:
first = simplify(pts[:worst_index+1], eps)
second = simplify(pts[worst_index:], eps)
return first + second[1:]
print simplify([(0,0), (10,10), (20,20), (30,30), (50,0)], 0.1)
The output is [(0, 0), (30, 30), (50, 0)].
About python syntax for arrays that may be non obvious:
x[a:b] is the part of array from index a up to index b (excluded)
x[n:] is the array made using elements of x from index n to the end
x[:n] is the array made using first n elements of x
a+b when a and b are arrays means concatenation
x[-1] is the last element of an array
An example of the results of running this implementation on a graph with 100,000 points with increasing values of eps can be seen here.
I came across this question after I had this very idea. Skip redundant points on plots. I believe I came up with a far better and simpler solution and I'm happy to share as my first proposed solution on SO. I've coded it and it works well for me. It also takes into account the screen scale. There may be 100 points in value between those plot points, but if the user has a chart sized small, they won't see them.
So, iterating through your data/plot loop, before you draw/add your next data point, look at the next value ahead and calculate the change in screen scale (or value, but I think screen scale for the above-mentioned reason is better). Now do the same for the next value ahead (getting these values is just a matter of peeking ahead in your array/collection/list/etc adding the for next step increment (probably 1/2) to the current for value whilst in the loop). If the 2 values are the same (or perhaps very minor change, per your own preference), you can skip this one point in your chart by simply adding 'continue' in the loop, skipping adding the data point as the point lies exactly on the slope between the point before and after it.
Using this method, I reduce a chart from 963 points to 427 for example, with absolutely zero visual change.
I think you might need to perhaps read this a couple of times to understand, but it's far simpler than the other best solution mentioned here, much lighter weight, and has zero visual effect on your plot.
I would probably apply a "least squares" algorithm to obtain a line of best fit. You can then go through your points and downfilter consecutive points that lie close to the line. You only need to plot the outliers, and the points that take the curve back to the line of best fit.
Edit: You may not need to employ "least squares"; if your input is expected to hover around "y=ax+b" as you say, then that's already your line of best fit and you can just use that. :)

Resources