when I want to extract a real part of g(x) and integrate a new function g1(x), the result b contains a Vector {Float 64} rather than just a number. How to get its integrated result?
Here is the code
g(x) = (exp.(-x).^2).*exp.(1im*x)
R_initial=real(g(x));
g1(x)= R_initial
b = quadgk(g1,0.6,0.7)
c = b[1]
Just do the following:
julia> g(x) = real((exp(-x)^2)*exp(1im*x))
g (generic function with 1 method)
julia> quadgk(g,0.6,0.7)
(0.021750435727577098, 3.469446951953614e-18)
In your code:
R_initial=real(g(x))
takes some global value of x that you probably have and R_initial is bound to some value. So you get something like:
julia> R_initial = [1.0, 2.0]
2-element Vector{Float64}:
1.0
2.0
julia> g1(x) = R_initial
g1 (generic function with 1 method)
julia> quadgk(g1,0.6,0.7)
([0.09999999999999998, 0.19999999999999996], 0.0)
which produces a vector in the first element as the input is multi-dimensional. Note that g1 is just a constant function.
Related
I came across Julia in some graduate research and have done a few projects already in C++. I'm trying to "translate" some of my C++ work into Julia to compare performance, among other things.
Basically what I'm trying to do is implement something like the functional library from C++ such that I can do something like
g(x, b) = x*b # Modifier function
A = [1,2,...] # Some array of values
f(x) = 1 # Initialize the function
### This is the part that I am seeking
for i = 1:length(A)
f(x) = f(x)*g(x, A[i]) # This thing right here
end
###
and then be able to call f(x) and get the value of all the g(x, _) terms included (similar to using bind in C++)
I'm not sure if there is native syntax to support this, or if I'll need to look into some symbolic representation stuff. Any help is appreciated!
You are probably looking for this:
julia> g(x, b) = x * b
g (generic function with 1 method)
julia> bind(g, b) = x -> g(x, b) # a general way to bind the second argument in a two argument function
bind (generic function with 1 method)
julia> A = [1, 2, 3]
3-element Vector{Int64}:
1
2
3
julia> const f = bind(g, 10) # bind a second argument of our specific function g to 10; I use use const for performance reasons only
#1 (generic function with 1 method)
julia> f.(A) # broadcasting f, as you want to apply it to a collection of arguments
3-element Vector{Int64}:
10
20
30
julia> f(A) # in this particular case this also works as A*10 is a valid operation, but in general broadcasting would be required
3-element Vector{Int64}:
10
20
30
In particular for fixing the first and the second argument of the two argument function there are standard functions in Julia Base that are called Base.Fix1 and Base.Fix2 respectively.
You may be looking for the function composition operator ∘
help?> ∘
"∘" can be typed by \circ<tab>
search: ∘
f ∘ g
Compose functions: i.e. (f ∘ g)(args...) means f(g(args...)). The ∘ symbol can be
entered in the Julia REPL (and most editors, appropriately configured) by typing
\circ<tab>.
Function composition also works in prefix form: ∘(f, g) is the same as f ∘ g. The
prefix form supports composition of multiple functions: ∘(f, g, h) = f ∘ g ∘ h and
splatting ∘(fs...) for composing an iterable collection of functions.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> map(uppercase∘first, ["apple", "banana", "carrot"])
3-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
julia> fs = [
x -> 2x
x -> x/2
x -> x-1
x -> x+1
];
julia> ∘(fs...)(3)
3.0
so, for example
julia> g(b) = function(x); x*b; end # modifier function
g (generic function with 1 method)
julia> g(3)(2)
6
julia> f() = 3.14
f (generic function with 1 method)
julia> h = g(2) ∘ f
var"#1#2"{Int64}(2) ∘ f
julia> h()
6.28
For a fixed n, I would like to create a function with n variables
f(x_1, ..., x_n)
For example if n=3, I would like to create an algorithm such that
f(x_1, x_2, x_3) = x_1 + x_2 + x_3
It would be very nice to have an algorithm for every n:
f(x_1, ..., x_n) = x_1 + ... + x_n
I don't know how to declare the function and how can create the n variables.
Thank you for your help,
In Julia you can just do
function f(x...)
sum(x)
end
And now:
julia> f(1,2,3)
6
Note that within the function f, x is just seen as a Tuple so you can do whatever you want (including asking for type of elements etc).
More generally you can define function f(x...;y...). Let us give it a spin
function f(x...;y...)
#show x
#show Dict(y)
end
And now run it:
julia> f(1,2,"hello";a=22, b=777)
x = (1, 2, "hello")
Dict(y) = Dict(:a => 22, :b => 777)
Dict{Symbol, Int64} with 2 entries:
:a => 22
:b => 777
Finally, another one (perhaps less elegant) way could be:
g(v::NTuple{3,Int}) = sum(v)
This forces v to be a 3-element Tuple and g be called as g((1,2,3))
If your n is small, you can do this manually thanks to multiple dispatch.
julia> f(x) = x + 1 # Method definition for one variable.
f (generic function with 1 method)
julia> f(x, y) = x + y + 1 # Method definition for two variables.
f (generic function with 2 methods)
julia> f(2)
3
julia> f(2, 4)
7
You could use macro programming to generate a set of these methods automatically, but that quickly becomes complicated. You are likely better off structuring your function so that it operates on either a Vector or a Tuple of arbitrary length. The definition of the function will depend on what you want to do. Some examples which expect x to be a Tuple, Vector, or other similar datatype are below.
julia> g(x) = sum(x) # Add all the elements
g (generic function with 1 method)
julia> h(x) = x[end - 1] # Return the second to last element
h (generic function with 1 method)
julia> g([10, 11, 12])
33
julia> h([10, 11, 12])
11
If you would rather the function accept an arbitrary number of inputs rather than a single Tuple or Vector as you wrote in the original question, then you should define a method for the functions with the slurping operator ... as below. Note that the bodies of the function definitions and the outputs from the functions are exactly the same as before. Thus, the slurping operator ... is just for syntactical convenience. The functions below still operate on the Tuple x. The function arguments are just slurped into the tuple before doing anything else. Also note that you can define both the above and below methods simultaneously so that the user can choose either input method.
julia> g(x...) = sum(x) # Add all the variables
g (generic function with 2 methods)
julia> h(x...) = x[end - 1] # Return the second to last variable
h (generic function with 2 methods)
julia> g(10, 11, 12)
33
julia> h(10, 11, 12)
11
Finally, another trick that is sometimes useful is to call a function recursively. In other words, to have a function call itself (potentially using a different method).
julia> q(x) = 2 * x # Double the input
q (generic function with 1 method)
julia> q(x...) = q(sum(x)) # Add all the inputs and call the function again on the result
q (generic function with 2 methods)
julia> q(3)
6
julia> q(3, 4, 5)
24
I want to evaluate a set of vectors (or tuples) in a function $f$ but Julia says me that is imposible.
For example: If I have an array of tuples p=[(1,1), (1,-1), (-1,1), (-1,-1)] and a function f(x,y)=x+y. I would like to calculate f(p[1]) = f(1,1)= 2. But Julia says me that the types are incompatible.
Can you help me please?
You have to splat a tuple like this:
julia> p=[(1,1), (1,-1), (-1,1), (-1,-1)]
4-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(1, -1)
(-1, 1)
(-1, -1)
julia> f(x,y)=x+y
f (generic function with 1 method)
julia> f(p[1]...)
2
you could also define a higher order function splat that would conveniently wrap any function and perform splatting. It is useful as then you can e.g. broadcast such function:
julia> splat(f) = x -> f(x...)
splat (generic function with 1 method)
julia> splat(f)(p[1])
2
julia> splat(f).(p)
4-element Array{Int64,1}:
2
0
0
-2
Alternatively you can define your function f like this:
julia> f((x,y),)=x+y
f (generic function with 1 method)
julia> f(p[1])
2
and now you do not have to do splatting.
Just use the ... operator to unpack the tuple as parameters:
julia> f(p[1]...)
2
In addition to other answers, if your task allows you, you can just define
julia> f(x) = f(x...)
and use it as
julia> f.(p)
4-element Vector{Int64}:
2
0
0
-2
I have an image and a 3x3 perspective projection matrix M. How do I apply the transform on the image?
I tried to use the warp(img, tform) function but don't know how to construct the transform object from the matrix.
Tried tform = PerspectiveMap() ∘ inv(LinearMap(M)), no idea if this is a correct to create the transform, but it fails with:
ERROR: Inverse transformation for CoordinateTransformations.PerspectiveMap has not been defined.
There are two components to the answer:
You have to define a transformation that takes a 2-vector to a 2-vector
If the transformation isn't invertible, then you have to specify the range of indices of the final image manually.
For the first, the following suffices:
julia> using StaticArrays, CoordinateTransformations
julia> M = #SMatrix [1 0 0; 0 1 0; -1/1000 0 1] # a 3x3 perspective transformation matrix
3×3 StaticArrays.SArray{Tuple{3,3},Float64,2,9}:
1.0 0.0 0.0
0.0 1.0 0.0
-0.001 0.0 1.0
julia> tform = PerspectiveMap() ∘ inv(LinearMap(M))
(CoordinateTransformations.PerspectiveMap() ∘ LinearMap([1.0 0.0 0.0; -0.0 1.0 0.0; 0.001 -0.0 1.0]))
julia> tform(#SVector([1,1,1])) # this takes a 3-vector as input and returns a 2-vector
2-element SVector{2,Float64}:
0.999001
0.999001
julia> push1(x) = push(x, 1)
push1 (generic function with 1 method)
julia> tform2 = PerspectiveMap() ∘ inv(LinearMap(M)) ∘ push1 # here's one that takes a 2-vector as input (appends 1 to the 2-vector)
(::#55) (generic function with 1 method)
julia> tform2(#SVector([1,1]))
2-element SVector{2,Float64}:
0.999001
0.999001
Now let's try this on an image. We'll create an output image that has the same indices as the input image, although you can choose any indices you want:
julia> using Images, TestImages
julia> img = testimage("lighthouse");
julia> imgw = warp(img, tform2, indices(img)); # 3rd argument sets the indices
julia> using ImageView
julia> imshow(imgw)
img looks like this:
and imgw looks like this:
Is there a way to concatenate ArrayViews in Julia, that doesn't copy the underlying data? (I'd also be glad to use a SubArray, if that solves the problem.)
In the code below, for example, I want a single ArrayView that references the data in both y1 and y2.
julia> x = [1:50];
julia> using ArrayViews;
julia> y1 = view(x, 2:5);
julia> y2 = view(x, 44:48);
julia> concat(y1, y2) # I wish there were a function like this
ERROR: concat not defined
julia> [y1, y2] # This copies the data in y1 and y2, unfortunately
9-element Array{Int64,1}:
2
3
4
5
44
45
46
47
48
Not directly. But you could roll your own type with something like:
julia> type CView{A<:AbstractArray} <: AbstractArray
a::A
b::A
end
julia> import Base: size, getindex, setindex!
julia> size(c::CView) = tuple([sa+sb for (sa, sb) in zip(size(c.a), size(c.b))]...)
size (generic function with 57 methods)
julia> getindex(c::CView, i::Int) = i <= length(c.a) ? getindex(c.a, i) : getindex(c.b, i)
getindex (generic function with 180 methods)
julia> c = CView(y1, y2);
julia> size(c)
(9,)
julia> c[1]
2
julia> c[4]
5
julia> c[5]
48
These methods may not be optimal but they can certainly get you started. To be useful, more methods would probably be needed. Note that the key is simply in deciding which member array to index into. For multidimensional indexing sub2ind can be used.