If I have predicates in the following format:
edge(a,b,50).
edge(b,c,70).
speed(am,70).
speed(pm,100).
How can I write a prolog program where I can say total(From,To,Time,Duration), where time is AM or PM time, duration is total distance of the trip?
if this result if what you're after
?- total(a,c,Time,Tot).
Time = am,
Tot = 1.7142857142857142 ;
Time = pm,
Tot = 1.2 ;
false.
you can get it with
total(From,To,Time,Duration) :-
distance(From, To, Distance),
speed(Time, Speed),
Duration is Distance / Speed.
distance(From, To, Distance) :-
edge(From, To, Distance).
distance(From, To, Distance) :-
edge(From, T, DistA),
distance(T, To, DistB),
Distance is DistA + DistB.
Note there must not be cycles in edge/3 graph. Otherwise see any of the many questions about basic graph navigation here on SO.
Related
I am looking for a sequence of inputs for the Dijsktra algorigthm implemented with a regular heap, where Dijsktras actual complexity would be Θ((e+v)logv).
I know how to implement Dijsktra and how it works, I also understand that the most time consuming operations are adding a vertex to the heap and changing the distance of a vertex. However, I am not sure how to find a graph (sequence of graphs) that would be the worst case inputs for Dijkstra.
Also if you had any general tips on how to find a sequence of inputs for the worst case complexity, that would be helpful.
Let vertices be numbered from 1 to n and you want to find path from vertex 1 to vertex n. Let e[i][j] be length of edge, connecting i and j. Initially e[1][2] = e[2][3] = ... = e[n - 1][n] = 1. Now we iterate through the vertices from n - 2 to 1. In i-th vertex for each j in [i + 2, n] we make e[i][j] = e[i][i + 1] + e[i + 1][j] + 1.
Now we have full graph. In each iteration dijkstra will update O(n) vertices, so it's O(n ^ 2) = O(E) actions working in O(log n).
So final asymptotics will be O(n log(n) + E log(n))
I know there's a similar question in stack overflow, where one person has asked, why time complexity of BFS/DFS is not simply O(V).
The appropriate answer given was that E can be as large as V^2 in case of complete graph, and hence it is valid to include E in time complexity.
But, if V cannot be greater than E+1. So, in that case not having V in the time complexity, should work?
If it is given that E = kV + c, for some real constants k and c then,
O(E + V) = O(kV + c + V) = O(V) = O(E) and your argument is correct.
An example of this is trees.
In general (i.e., without any prior information), however, E = O(V^2), and thus we cannot do better than O(V^2).
Why not write just O(E) always?
EDIT: The primary reason for always writing O(E + V) is to avoid ambiguity.
For example, there might be cases when there are no edges in the graph at all (i.e. O(E) ~ O(1)). Even for such cases, we'll have to go to each of the vertex (O(V)), we cannot finish in O(1) time.
Thus, only writing O(E) won't do in general.
V has to be included because both BFS and DFS rely on arrays of size |V| to track which vertices have been processed/discovered/explored (whatever the case may be). If a graph has 0 edges and 100000 vertices, such arrays will still take more time to initialize than they would if there were only 5 vertices. Thus, the time complexities of BFS and DFS scale on |V|.
The graph is positive weighted and might be acyclic or not.
input file consists of
vertex number, edge number, begining vertex, ending vertex
edge1(from, to, weight)
edge2(from, to, weight)
and so on.
the length of the path will be infinite if there is cycle in the graph and will be 0 if there is no way
the way I do is that I remove the same edges with less lengths and use bellman ford or dijkstra's algorithm in adjecent list or matrix and both work fine.
however, program should find the path at most 2 seconds and some input files contain 10000 vertices and 100000 edges
what should I do?
The time limit is 2 sec, it means the program should have near about ~10^6 iterations. See the limits of V = 10000 and e = 100000. This means an algorithm of O(V) or O(E) or O(V + E) or even O(E + VlogV)will easily compute your requirement well in given time.
Note E + Vlogv ~ (100000 + ~132877) which is less than 10^6
// This 10^6 limit is quit good for processors with 10^9 Hz frequency. So, even if your algo has 1000 instructions for each iteration, you will be in safe zone.
So, here is the proposed algorithm:
You will build the graph in O(E). Use Adjacency list data structure to represent the graph.
-> While building this data structure, store indegree of each vertex and also store count of vertices.
countV := V;
foreach edge_i
inDegree[to] := inDegree[to] + 1;
Check if there is cycle in the graph in O(V + E).
if no vertex with indegree = 0 and countV = 0
graph has no cycle
else if no vertex with indegree = 0 and countV != 0
graph has cycle
else select any vertex having 0 indegree
countV := countV - 1;
decrease all its directed neighbours' inDegree by 1.
So if you get a cycle, your answer is directly infinite.
Make a BFS or DFS to get whether the ending vertex is reachable from beginning vertex or not. This can be done in O(V + E) or even O(E). Let us take O(V + E). If not reacable your answer is directly 0.
Now, apply dijkstra but in relax condition, just check the opposite. i.e in the pseudocode given here, instead of doing
if alt < dist[v]:
dist[v] := alt;
do
if alt > dist[v]:
dist[v] := alt;
This can be done in O(E + VlogV). Hence overall complexity of the solution will be O(E + VlogV) which is well in constraints.
I'm trying to design a 2D physics engine with continuous collision detection. Objects are stored as a list of non-rotating line-segments. Therefore I can detect collisions by finding the collision time between each pair of line segments between any two objects.
I want to find the exact time for an intersection between two moving line-segments that are moving in a constant direction, and it is proving to be difficult.
I have figured out that I can simplify the problem further by finding the collision time between each point on a line-segment and the other line-segment (and vice versa). It's possible that it is computationally inefficient, so a general solution for two line segments would be the ideal answer. I can also ignore the case in which lines are parallel (I want to treat a line/point sharing the same position and velocity as 'no collision').
If the answer is "not possible" to exactly find this intersection time, I would accept it as a solution. Any help on the subject would be appreciated.
EDIT: According to Wikipedia's article on a Line segment, for a line segment with endpoints A = (a_x, a_y) and C = (c_x, c_y), a general equation for the line segment looks like this:
For a line-segment--point intersection, would substituting
p_x + p_v * t for a_x (left-side only, right-side is just p_x)
p_y + p_v * t for a_y (left-side only, right-side is just p_y)
q_x + q_v * t for c_x (left-side only, right-side is just q_x)
q_y + q_v * t for c_y (left-side only, right-side is just q_y)
r_x + r_v * t for x
r_y + r_v * t for y
for a line segment pq [(p_x, p_y), (q_x, q_y)], point r (r_x, r_y), moving at rates of p_v == q_v != r_v be solvable for t? Here's the full equation:
The equation I have up above is incorrect in that it uses the same velocity for both its x and y components.
Since velocity is constant, I can simplify the equation such that the point is moving in reference to the line segment. The amount of variables used for velocity reduces greatly, by using v = r_v - qp_v for the velocity of the point r, and 0 for the velocity of each line segment. The equation with the variables plugged in then becomes:
Thanks to WolframAlpha, the equation is then solved for t:
What's interesting is that if you analyze this, it's symmetrical for 3D. Cross product for [x1, y1, 0] and [x2, y2, 0] is [0, 0, x1*y2 - y1*x2]. This equation then translates into:
For a line-segment--point intersection, I can find an interval in which there is a collision (although this interval is larger than the actual time for the collision):
Given a line segment [p, q] moving at velocity v, and a point r with velocity w, direction(w) != direction(v), define three lines L1 = [p, p+v], L2 = [q, q+v], L3 = [r, r+w]. Let t1, t_p and t2, t_q be the intersection times between L1 and L3 and between L2 and L3, respectively. If the interval [t1, t2] is not mutually exclusive with [t_p, t_q], then there is an intersection in the intersection of these two intervals (e.g. intersection between [-1, 10] and [2, 20] is [2, 10]). If these intervals are mutually exclusive, then there is no collision.
Additionally, if the direction of v and w ARE the same, but not of equal length, then you can find the exact time of collision. Let s be the point r when projected onto the line [p, q]. If this point is in the line segment [p, q], there is a collision at time t1, which can be calculated by dividing the distance between point r and point s by the relative velocity between the point r and the line-segment [p, q].
Using the interval it's possible to get an estimate for the time by using a binary-search--like method of comparing distances between the segment and point at specific times. This is very inefficient, however.
I have two paths in 3D and I want to "average" them, if there's such a thing.
I have the xyz pairs timestamped at the time they were sampled:
ms x y z
3 0.1 0.2 0.6
12 0.1 0.2 1.3
23 2.1 4.2 0.3
55 0.1 6.2 0.3
Facts about the paths:
They all start and end on/near the same xyz point.
I have the total duration it took to complete the path as well as individual vertices
They have different lengths (i.e. different number of xyz pairs).
Any help would be appreciated.
A simple method is the following...
First build a function interp(t, T, waypoints) that given the current time t, the total path duration T and the path waypoints returns the current position. This can be done using linear interpolation or more sophisticated approaches to avoid speed or acceleration discontinuities.
Once you have interp the average path can be defined as (example in python)
def avg(t, T1, waypoints1, T2, waypoints2):
T = (T1 + T2) / 2
return middlePoint(interp(t*T1/T, T1, waypoints1),
interp(t*T2/T, T2, waypoints2))
the duration of the average path will be the average T = (T1 + T2) / 2 of the two durations.
It's also easy to change this approach to make a weighted average path.
In R, the distances between consecutive points in that series assuming it is in a dataframe named "dat"
would be:
with(dat, sqrt(diff(x)^2 +diff(y)^2 +diff(z)^2) )
#[1] 0.700000 4.582576 2.828427
There are a couple of averages I could think of average distance in interval, average distance traveled per unit time. Depends on what you want. This gives the average velocity in the three intervals:
with(dat, sqrt(diff(x)^2 +diff(y)^2 +diff(z)^2) /diff(ms) )
#[1] 0.07777778 0.41659779 0.08838835
There is definitely such a thing. For each point on path A, find the point that correponds to your current point on path B, and then find the mid-point between those corresponding verticies. You will then get a path in-between the two that is the "average" of the two paths. If you have a mis-match where you did not sample the two paths the same, then for an interior point on path A (i.e., not the end-point), find the two closest sampled points with a similar time-sampling on path B, and locate the mid-point of the triangle those three points will make.
Now since you've discreetized your path by sampling it, this "average" is only going to be an approximation, not a "true" average like you could do by solving for the average function between two differentiable parametric functions defined by r(t) = <x(t), y(t), z(t)>.
Expanding on #6502's answer.
If you wish to retrieve a list of points that would make up the average path, you could sample the avg function at the instances of the individual input points. (Stretched toward the average length)
def avg2(T1, waypoints1, T2, waypoints2):
# Collect the times we want to sample at
T = (T1 + T2) / 2
times = []
times.extend(t*T/T1 for (t,x,y) in waypoints1) # Shift the time towards
times.extend(t*T/T2 for (t,x,y) in waypoints2) # the average
times.sort()
result = []
last_t = None
for t in times:
# Check if we have two points in close succession
if last_t is not None and last_t + 1.0e-6 >= t:
continue
last_t = t
# Sample the average path at this instance
x, y = avg(t, T1, waypoints1, T2, waypoints2)
yield t, x, y