Unwanted evaluation on prolog - prolog

I was making a prolog knowledge base to implement geometry rules. When testing if a rectangle had a right angle, I found two answers.
?- rect_tri(triangle(line(point(0,0),point(0,1)),line(point(0,1),point(1,0)),line(point(1,0),point(0,0)))).
true ;
false.
Here is the kwnoledge base:
point(X,Y).
line(X,Y) :- X = point(A,B), Y = point(C,D), not(X = Y).
len(X,R) :- X = line(P,Q), P = point(A,B), Q = point(C,D), not(P = Q),
R is sqrt((A - C) * (A - C) + (B - D) * (B - D)).
triangle(X,Y,Z) :- X = point(A,B), Y = point(C,D), Z = point(E,F),
not(X = Y), not(X = Z), not(Y = Z),
L1 = line(X,Y), L2 = line(X,Z), L3 = line(Y,Z),
len(L1,G), len(L2,H), len(L3,I),
G + H > I, G + I > H, H + I > G.
triangle(X,Y,Z) :- X = line(A,B), Y = line(B,C), line(A,C),
len(X,G), len(Y,H), len(Z,I),
G + H > I, G + I > H, H + I > G.
rect_tri(X) :- X = triangle(A,B,C), len(A,G), len(B,H), len(C,I),
(G is sqrt(H * H + I * I);
H is sqrt(G * G + I * I);
I is sqrt(H * H + G * G)).
When tracing, I found that the answer true comes when prolog hits the line H is sqrt(G * G + I * I), and false when it evaluates the last line.
I don't want the last evaluation to occur, because I want it to exit when a true has been found.

Daniel comment probably shows the most sensible way to solve your problem. Some other option...
in modern compilers there is the if/then/else construct:
rect_tri(X) :- X = triangle(A,B,C), len(A,G), len(B,H), len(C,I),
( G is sqrt(H * H + I * I)
-> true
; H is sqrt(G * G + I * I)
-> true
; I is sqrt(H * H + G * G)
).
You could as well use cuts (old fashioned way, somewhat more readable here):
rect_tri(X) :- X = triangle(A,B,C), len(A,G), len(B,H), len(C,I),
( G is sqrt(H * H + I * I), !
; H is sqrt(G * G + I * I), !
; I is sqrt(H * H + G * G)
).

Related

Monte Carlo program throws a method error in Julia

I am running this code but it shows a method error. Can someone please help me?
Code:
function lsmc_am_put(S, K, r, σ, t, N, P)
Δt = t / N
R = exp(r * Δt)
T = typeof(S * exp(-σ^2 * Δt / 2 + σ * √Δt * 0.1) / R)
X = Array{T}(N+1, P)
for p = 1:P
X[1, p] = x = S
for n = 1:N
x *= R * exp(-σ^2 * Δt / 2 + σ * √Δt * randn())
X[n+1, p] = x
end
end
V = [max(K - x, 0) / R for x in X[N+1, :]]
for n = N-1:-1:1
I = V .!= 0
A = [x^d for d = 0:3, x in X[n+1, :]]
β = A[:, I]' \ V[I]
cV = A' * β
for p = 1:P
ev = max(K - X[n+1, p], 0)
if I[p] && cV[p] < ev
V[p] = ev / R
else
V[p] /= R
end
end
end
return max(mean(V), K - S)
end
lsmc_am_put(100, 90, 0.05, 0.3, 180/365, 1000, 10000)
error:
MethodError: no method matching (Array{Float64})(::Int64, ::Int64)
Closest candidates are:
(Array{T})(::LinearAlgebra.UniformScaling, ::Integer, ::Integer) where T at /Volumes/Julia-1.8.3/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/LinearAlgebra/src/uniformscaling.jl:508
(Array{T})(::Nothing, ::Any...) where T at baseext.jl:45
(Array{T})(::UndefInitializer, ::Int64) where T at boot.jl:473
...
Stacktrace:
[1] lsmc_am_put(S::Int64, K::Int64, r::Float64, σ::Float64, t::Float64, N::Int64, P::Int64)
# Main ./REPL[39]:5
[2] top-level scope
# REPL[40]:1
I tried this code and I was expecting a numeric answer but this error came up. I tried to look it up on google but I found nothing that matches my situation.
The error occurs where you wrote X = Array{T}(N+1, P). Instead, use one of the following approaches if you need a Vector:
julia> Array{Float64, 1}([1,2,3])
3-element Vector{Float64}:
1.0
2.0
3.0
julia> Vector{Float64}([1, 2, 3])
3-element Vector{Float64}:
1.0
2.0
3.0
And in your case, you should write X = Array{T,1}([N+1, P]) or X = Vector{T}([N+1, P]). But since there's such a X[1, p] = x = S expression in your code, I guess you mean to initialize a 2D array and update its elements through the algorithm. For this, you can define X like the following:
X = zeros(Float64, N+1, P)
# Or
X = Array{Float64, 2}(undef, N+1, P)
So, I tried the following in your code:
# I just changed the definition of `X` in your code like the following
X = Array{T, 2}(undef, N+1, P)
#And the result of the code was:
julia> lsmc_am_put(100, 90, 0.05, 0.3, 180/365, 1000, 10000)
3.329213731484463

How to find the distance between a point x,y and the diagonales?

I need to find the distance of O and N with the diagonales (with a 90° angle/ the shortest). I found a formula online, but why in this case, it does not return the good distance ?
And if possible, how to normalize the result (e.g. O is at20% of the diagonale?)
import numpy as np
import math
O = (1,3)
N = (3,2)
r = np.arange(24).reshape((6, 4))
def get_diagonal_distance(centroid, img_test):
x1, y1 = centroid
a, b = img.shape[1], img.shape[0]
c = np.sqrt(np.square(a) + np.square(b))
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
return d
print(f"diagonal d: {get_diagonal_distance(O, r): .4f}")
d = abs((a * x1 + b * y1 + c)) / (math.sqrt(a * a + b * b))
Your computation is wrong because a, b and c refer to the coefficients of the equation of the line ax+by+c=0
import numpy as np
O = (1,3)
N = (3,2)
M, L, I, H = (-1,-2), (3, -2), (3, 2), (-1, 2)
# Following your initial idea
def get_diagonal_distance(diagonal_extremes, point):
diagonal_vector = (diagonal_extremes[1][0] - diagonal_extremes[0][0],
diagonal_extremes[1][1] - diagonal_extremes[0][1])
a = diagonal_vector[1]
b = - diagonal_vector[0]
c = - diagonal_extremes[0][0]*a - diagonal_extremes[0][1]*b
x, y = point[0], point[1]
return abs((a * x + b * y + c)) / (np.sqrt(a * a + b * b))
# Taking advantage of numpy
def distance_from_diagonal(diagonal_extremes, point):
u = (diagonal_extremes[1][0] - diagonal_extremes[0][0],
diagonal_extremes[1][1] - diagonal_extremes[0][1])
v = (point[0] - diagonal_extremes[0][0],
point[1] - diagonal_extremes[0][1])
return np.cross(u, v) / np.linalg.norm(u)
print(f"diagonal d: {get_diagonal_distance((M, I), O): .4f}")
print(f"diagonal d: {distance_from_diagonal((M, I), O): .4f}")

difficult in understanding some logic circuits

Finding it difficult to get the logic expression for this circuit? Help will be appreciated
enter image description here
Here is a detailed solution, I hope (i) that the steps are clear, and (ii) that my calculation is correct :-)
The circuit has four logical gates: an AND gate with output X = B*C (short for B AND C), a NOT gate which inverts the value of A yielding A' (short for NOT A), a NOR gate with inputs A' and X and output Y = (A' + X)' (short for NOT ((NOT A) OR X))) and a final AND gate with inputs Y, A and B and output Z = A*B*Y (short for Z = A AND B AND Y). The expression for Z is then:
Z = A * B * Y = A * B * ( (A' + X)' ) = A * B * { [A' + (B*C)]' }
Repeatedly applying DeMorgan laws to the expression in the brackets yields:
[A' + (B*C)]' = A'' * (B*C)' = A *(B' + C')
So
Z = A * B * [ A *(B' + C') ] = A * B * A * (B' + C')
Since A*B*A = A*A*B = (A*A)*B and A*A = A this yields
Z = A * B * (B' + C') = A * B * B' + A * B * C'
And finally, since B * B' = 0, X * 0 = 0:
Z = 0 + A * B * C' = A * B * C' = A AND B AND (NOT C)

Convert Euler to Heun (improved Euler)

I already have implemented Euler method in Mathematica.
Now I want to convert this method to Heun method (improved Euler).
I have this Euler implementation:
a = 2;(*my a parameter*)
b = .01; (*my b parameter*)
x = 0; (*starting x value*)
p = 1; (*starting p value*)
t = 1; (*step size t*)
f[p_] := a p - b p^2; (*my function*)
f[0] = 1;
eulertable = {}; (*build table (x,p).n steps in loop*)
For[n = 1,
n <= 21, n++,
AppendTo[eulertable, {x, p}];
p = p + t f[p];
x = x + t;]
Now I want to implement this with the Heun method. I already have this implementation of the Heun method.
heun[f_, {x_, x0_, xn_}, {y_, y0_}, steps_] :=
Block[{ xold = x0, yold = y0, sollist = {{x0, y0}}, x, y, h },
h = N[(xn - x0) / steps];
Do[ xnew = xold + h;
k1 = h * (f /. {x -> xold, y -> yold});
k2 = h * (f /. {x -> xold + h, y -> yold + k1});
ynew = yold + .5 * (k1 + k2);
sollist = Append[sollist, {xnew, ynew}];
xold = xnew;
yold = ynew,
{steps}
];
Return[sollist]
]
But I need to convert this method to have the input like it is in my Euler method. So I have to convert the Heun method that I have the parameter a, b, x, t, p, f[].
As I am new with Mathematica I am having problems to convert the method.
Why do you put f[0]=1?
Replace
p = p + t f[p];
x = x + t;
with
p1 = p + t f[p];
p2 = p + t f[p1];
p = (p1+p2)/2;
x = x + t;
Your step size is rather large for the values of your parameters.

Finding the intersection of two lines

I have two lines:
y = -1/3x + 4
y = 3x + 85
The intersection is at [24.3, 12.1].
I have a set of coordinates prepared:
points = [[1, 3], [4, 8], [25, 10], ... ]
#y = -1/3x + b
m_regr = -1/3
b_regr = 4
m_perp = 3 #(1 / m_regr * -1)
distances = []
points.each do |pair|
x1 = pair.first
y2 = pair.last
x2 = ((b_perp - b_regr / (m_regr - m_perp))
y2 = ((m_regr * b_perp) / (m_perp * b_regr))/(m_regr - m_perp)
distance = Math.hypot((y2 - y1), (x2 - x1))
distances << distance
end
Is there a gem or some better method for this?
NOTE: THE ABOVE METHOD DOES NOT WORK. See my answer for a solution that works.
What's wrong with using a little math?
If you have:
y = m1 x + b1
y = m2 x + b2
It's a simple system of linear equations.
If you solve them, your intersection is:
x = (b2 - b1)/(m1 - m2)
y = (m1 b2 - m2 b1)/(m1 - m2)
After much suffering and many different tries, I found a simple algebraic method here that not only works but is dramatically simplified.
distance = ((y - mx - b).abs / Math.sqrt(m**2 + 1))
where x and y are the coordinates for the known point.
For Future Googlers:
def solution k, l, m, n, p, q, r, s
intrsc_x1 = m - k
intrsc_y1 = n - l
intrsc_x2 = r - p
intrsc_y2 = s - q
v1 = (-intrsc_y1 * (k - p) + intrsc_x1 * (l - q)) / (-intrsc_x2 * intrsc_y1 + intrsc_x1 * intrsc_y2);
v2 = ( intrsc_x2 * (l - q) - intrsc_y2 * (k - p)) / (-intrsc_x2 * intrsc_y1 + intrsc_x1 * intrsc_y2);
(v1 >= 0 && v1 <= 1 && v2 >= 0 && v2 <= 1) ? true : false
end
The simplest and cleanest way I've found on the internet.

Resources