folks!
I have a working function named "LookAt" written in Lua language.
There is no mistakes in code and logic of this function.
But i believe we can simplify the math logic.
function LookAt(target)
local origin = Vec3.New(Engine.ClientData.Origin)
local direction = origin - target
Engine.Pitch = math.deg(math.atan(direction.Z, math.sqrt((direction.X ^ 2) + (direction.Y ^ 2))))
Engine.Yaw = math.deg(math.atan(direction.Y, direction.X)) - 180.0
end
I don't think there's much you can do to simplify the math logic. There's very little redundancy here you can take advantage of. But you can factor it into pieces like this:
function atan_deg(y, x)
return (math.deg(math.atan(y, x)))
end
function hypotenuse(x, y)
return (math.sqrt(x^2 + y^2))
end
function LookAt(target)
local origin = Vec3.New(Engine.ClientData.Origin)
local direction = origin - target
local X, Y, Z = direction.X, direction.Y, direction.Z
Engine.Pitch = atan_deg(Z, hypotenuse(X, Y))
Engine.Yaw = atan_deg(Y, X) - 180.0
end
Related
I found a workaround to make composite function, but I believe there should be a better way to do this:
? f = x^2
%1 = x^2
? g = x^3
%2 = x^3
? x = g
%3 = x^3
? fog = eval(f)
%4 = x^6
? x = 2
%5 = 2
? result = eval(fog)
%6 = 64
In this method, I need to assign x many times and I don't want to use eval function. The code is not readable and maintainable.
You can simplify Piotr's nice answer to
comp(f, g) = x->f(g(x));
Indeed, you do not need to assign to the (global) variable h in the comp function itself. Also, the braces are not necessary for a single-line statement, and neither are type annotations (which are meant to optimize the byte compiler output or help gp2c; in this specific case they do not help).
Finally the parentheses around the argument list are optional in the closure definition when there is a single argument, as (x) here.
I would modify the examples as follows
f(x) = x^2;
g(x) = x^3;
h = comp(f, g);
? h('x) \\ note the backquote
%1 = x^6
? h(2)
%2 = 64
The backquote in 'x makes sure we use the formal variable x and not whatever value was assigned to the GP variable with that name. For the second example, there is no need to assign the value 2 to x, we can call h(2) directly
P.S. The confusion between formal variables and GP variables is unfortunate but very common for short names such as x or y. The quote operator was introduced to avoid having to kill variables. In more complicated functions, it can be cumbersome to systematically type 'x instead of x. The idiomatic construct to avoid this is my(x = 'x). This makes sure that the x GP variable really refers to the formal variable in the current scope.
PARI/GP supports the anonymous closures. So you can define the function composition on your own like this:
comp(f: t_FUNC, g: t_FUNC) = {
h = (x) -> f(g(x))
};
Then your code can be transformed to a more readable form:
f(x) = x^2;
g(x) = x^3;
h = comp(f, g);
h(x)
? x^6
x = 2; h(x)
? 64
Hope, this helps.
I have implemented the multivariate Newton's method in Julia.
function newton(f::Function, J::Function, x)
h = Inf64
tolerance = 10^(-10)
while (norm(h) > tolerance)
h = J(x)\f(x)
x = x - h
end
return x
end
On the one hand, when I try to solve the below system of equations, LoadError: SingularException(2) is thrown.
f(θ) = [cos(θ[1]) + cos(θ[2] - 1.3),
sin(θ[1]) + sin(θ[2]) - 1.3]
J(θ) = [-sin(θ[1]) -sin(θ[2]);
cos(θ[1]) cos(θ[2])]
θ = [pi/3, pi/7]
newton(f, J, θ)
On the other hand, when I try to solve this other system
f(x) = [(93-x[1])^2 + (63-x[2])^2 - 55.1^2,
(6-x[1])^2 + (16-x[2])^2 - 46.2^2]
J(x) = [-2*(93-x[1]) -2*(63-x[2]); -2*(6-x[1]) -2*(16-x[2])]
x = [35, 50]
newton(f, J, x)
no errors are thrown and the correct solution is returned.
Furthermore, if I first solve the second system and then try to solve the first system, which normally throwns SingularException(2), I now instead encounter no errors but am returned a totally inaccurate solution to the first system.
What exactly is going wrong when I try to solve the first system and how can I resolve the error?
I'm struggling to amend the Julia-specific tutorial on NLopt to meet my needs and would be grateful if someone could explain what I'm doing wrong or failing to understand.
I wish to:
Minimise the value of some objective function myfunc(x); where
x must lie in the unit hypercube (just 2 dimensions in the example below); and
the sum of the elements of x must be one.
Below I make myfunc very simple - the square of the distance from x to [2.0, 0.0] so that the obvious correct solution to the problem is x = [1.0,0.0] for which myfunc(x) = 1.0. I have also added println statements so that I can see what the solver is doing.
testNLopt = function()
origin = [2.0,0.0]
n = length(origin)
#Returns square of the distance between x and "origin", and amends grad in-place
myfunc = function(x::Vector{Float64}, grad::Vector{Float64})
if length(grad) > 0
grad = 2 .* (x .- origin)
end
xOut = sum((x .- origin).^2)
println("myfunc: x = $x; myfunc(x) = $xOut; ∂myfunc/∂x = $grad")
return(xOut)
end
#Constrain the sums of the x's to be 1...
sumconstraint =function(x::Vector{Float64}, grad::Vector{Float64})
if length(grad) > 0
grad = ones(length(x))
end
xOut = sum(x) - 1
println("sumconstraint: x = $x; constraint = $xOut; ∂constraint/∂x = $grad")
return(xOut)
end
opt = Opt(:LD_SLSQP,n)
lower_bounds!(opt, zeros(n))
upper_bounds!(opt,ones(n))
equality_constraint!(opt,sumconstraint,0)
#xtol_rel!(opt,1e-4)
xtol_abs!(opt,1e-8)
min_objective!(opt, myfunc)
maxeval!(opt,20)#to ensure code always terminates, remove this line when code working correctly?
optimize(opt,ones(n)./n)
end
I have read this similar question and documentation here and here, but still can't figure out what's wrong. Worryingly, each time I run testNLopt I see different behaviour, as in this screenshot including occasions when the solver uselessly evaluates myfunc([NaN,NaN]) many times.
You aren't actually writing to the grad parameters in-place, as you write in the comments;
grad = 2 .* (x .- origin)
just overrides the local variable, not the array contents -- and I guess that's why you see these df/dx = [NaN, NaN] everywhere. The simplest way to fix that would be with broadcasting assignment (note the dot):
grad .= 2 .* (x .- origin)
and so on. You can read about that behaviour here and here.
How do I evaluate the function in only one of its variables, that is, I hope to obtain another function after evaluating the function. I have the following piece of code.
deff ('[F] = fun (x, y)', 'F = x ^ 2-3 * y ^ 2 + x * y ^ 3');
fun (4, y)
I hope to get 16-3y ^ 2 + 4y ^ 3
If what you want to do is to write x = f(4,y), and later just do x(2) to get -36, that is called partial application:
Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments".
This is a very useful feature, and very common Functional Programming Languages, such as Haskell, but even JS and Python now are able to do it. It is also possible to do this in MATLAB and GNU/Octave using anonymous functions (see this answer). In Scilab, however, this feature is not available.
Workround
Nonetheless, Scilab itself uses a workarounds to carry a function with its arguments without fully evaluating. You see this being used in ode(), fsolve(), optim(), and others:
Create a list containing the function and the arguments to partial evaluation: list(f,arg1,arg2,...,argn)
Use another function to evaluate such list and the last argument: evalPartList(list(...),last_arg)
The implementation of evalPartList() can be something like this:
function y = evalPartList(fList,last_arg)
//fList: list in which the first element is a function
//last_arg: last argument to be applied to the function
func = fList(1); //extract function from the list
y = func(fList(2:$),last_arg); //each element of the list, from second
//to last, becomes an argument
endfunction
You can test it on Scilab's console:
--> deff ('[F] = fun (x, y)', 'F = x ^ 2-3 * y ^ 2 + x * y ^ 3');
--> x = list(fun,4)
x =
x(1)
[F]= x(1)(x,y)
x(2)
4.
--> evalPartList(x,2)
ans =
36.
This is a very simple implementation for evalPartList(), and you have to be careful not to exceed or be short on the number of arguments.
In the way you're asking, you can't.
What you're looking is called symbolic (or formal) computational mathematics, because you don't pass actual numerical values to functions.
Scilab is numerical software so it can't do such thing. But there is a toolbox scimax (installation guide) that rely on a the free formal software wxmaxima.
BUT
An ugly, stupid but still sort of working solution is to takes advantages of strings :
function F = fun (x, y) // Here we define a function that may return a constant or string depending on the input
fmt = '%10.3E'
if (type(x)==type('')) & (type(y)==type(0)) // x is string is
ys = msprintf(fmt,y)
F = x+'^2 - 3*'+ys+'^2 + '+x+'*'+ys+'^3'
end
if (type(y)==type('')) & (type(x)==type(0)) // y is string so is F
xs = msprintf(fmt,x)
F = xs+'^2 - 3*'+y+'^2 + '+xs+'*'+y+'^3'
end
if (type(y)==type('')) & (type(x)==type('')) // x&y are strings so is F
F = x+'^2 - 3*'+y+'^2 + '+x+'*'+y+'^3'
end
if (type(y)==type(0)) & (type(x)==type(0)) // x&y are constant so is F
F = x^2 - 3*y^2 + x*y^3
end
endfunction
// Then we can use this 'symbolic' function
deff('F2 = fun2(y)',' F2 = '+fun(4,'y'))
F2=fun2(2) // does compute fun(4,2)
disp(F2)
I want to use instead of matlab integration command, a basic self created one. Do you have any Idea how to fix the error? If I use Matlab quad command, my algorithm works good but when I try to use my self created integral function,not suprisingly for sure, it does not work:(
M-File:
function y = trapapa(low, up, ints, fun)
y = 0;
step = (up - low) / ints;
for j = low : step : up
y = y + feval(fun,j);
end
y = (y - (feval(fun, low) + feval(fun, up))/2) * step;
Mean algorithm:
clear;
x0=linspace(0,4,3);
y=linspace(0,2,3);
for i=1:length(x0)
for j=1:length(y)
x(i,j)=y(j)+x0(i);
alpha=#(rho)((5-2*x(i,j)).*exp(y(j)-rho))./2;
%int(i,j)=quad(alpha,0,y(j))
int(i,j)=trapapa(alpha,0,y(j),10)
end
end
You are not following your function definition in the script. The fun parameter (variable alpha) is supposed to be the last one.
Try int(i,j)=trapapa(0,y(j),10,alpha)