I have the following function for combining two lists into one. It's supposedly of type:
# : 'a list * 'a list -> 'a list
fun # (nil, k) = k
| # (x::l, k) = x :: #(l,k);
Let's say we have two lists: [1, 2, 3] and [4, 5, 6]. If I call:
#([1, 2, 3], [4, 5, 6])
1::#([2, 3], [4, 5, 6])
1::2::#([3], [4, 5, 6])
1::2::3::#(nil, [4, 5, 6])
But here we reach the base case and our # call returns the list [4, 5, 6], yielding:
1::2::3::[4, 5, 6]
which is obviously not what I want. Is the function definition correct or am I misunderstanding something?
Yes your function definition is correct.
:: or Cons as it is called in Lisp and other functional programming languages is used for creating lists. It takes a value and a list (which may be empty) and creates a new list with the former prepended to the latter. So for example 42::[17, 23] equals [42, 17, 23].
Cons is right associative which means that your list
1::2::3::[4,5,6]
can be written as
(1::(2::(3::[4,5,6])))
and by successive reductions we get
[1,2,3,4,5,6]
Related
I'm new to Pytorch and having an issue with the gather() function:
I have a 3d tensor, x[i,j,k]:
x=tensor([[[1,2,3],
[4,5,6],
[7,8,9]],
[[10,11,12],
[13,14,15],
[16,17,18]]])
I have an index tensor:
index=tensor([[1,2,0]])
I want to use the values of index to iterate over x[j] and fetch the (complete) rows. I've tried gather() with all dims, squeezing, unsqueezing and it never seems to get the output I'm looking for, which would be:
output=tensor([[[4,5,6],
[7,8,9],
[1,2,3]],
[[13,14,15],
[16,17,18],
[10,11,12]]])
I've also tried repeating the values of index to get the same shape as x but it did not work.
I know I can do this with an if loop, but I'm pretty sure I can do it with gather() as well. Thanks for the help
Let us set up the two tensors x and index:
>>> x = torch.arange(1,19).view(2,3,3)
>>> index = torch.tensor([[1,2,0]])
What you are looking for is the torch.gather operation:
out[i][j][k] = x[i][index[i][j][k]][k]
In other to apply this function, you need to expand index to the same shape as out. Additionally, a transpose operation is required to flip your original index tensor.
>>> i = index.T.expand_as(x)
tensor([[[1, 1, 1],
[2, 2, 2],
[0, 0, 0]],
[[1, 1, 1],
[2, 2, 2],
[0, 0, 0]]])
If you compare with the pseudo code line above, you can see how every element of i represents the row of the original tensor x the operator will gather values from.
Applying the function gets us to the desired result:
x.gather(dim=1, index=index.T.expand_as(x))
tensor([[[ 4, 5, 6],
[ 7, 8, 9],
[ 1, 2, 3]],
[[13, 14, 15],
[16, 17, 18],
[10, 11, 12]]])
Let's say I have a vector a = [1, 0, 1, 2, 3, 4, 5, 0, 5, 6, 7, 8, 0, 9, 0] and I want to split it to smaller vectors based on a condition depending on value in that array. E.g. value being zero.
Thus I want to obtain vector of following vectors
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
So far this was working for me as a naive solution, but it loses the type.
function split_by_λ(a::Vector, λ)
b = []
temp = []
for i in a
push!(temp, i)
if λ(i)
push!(b, temp)
temp = []
end
end
b
end
split_by_λ(a, isequal(0))
Then I tried to play with ranges, which feels a bit more idiomatic, and does not lose the type.
function split_by_λ(a::Vector, λ)
idx = findall(λ, a)
ranges = [(:)(i==1 ? 1 : idx[i-1]+1, idx[i]) for i in eachindex(idx)]
map(x->a[x], ranges)
end
split_by_λ(a, isequal(0))
but it still feels very cumbersome regarding it's a rather simple task.
Is there something I'm missing, some easier way?
Maybe someone has a shorter idea but here is mine:
julia> inds = vcat(0,findall(==(0),a),length(a))
julia> getindex.(Ref(a), (:).(inds[1:end-1].+1,inds[2:end]))
5-element Array{Array{Int64,1},1}:
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
[]
Or if you want to avoid copying a
julia> view.(Ref(a), (:).(inds[1:end-1].+1,inds[2:end]))
5-element Array{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},1}:
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
0-element view(::Array{Int64,1}, 16:15) with eltype Int64
Pretty much the same as Przemyslaw's answer, but maybe less cryptic dense:
function split_by(λ, a::Vector)
first, last = firstindex(a), lastindex(a)
splits = [first-1; findall(λ, a); last]
s1, s2 = #view(splits[1:end-1]), #view(splits[2:end])
return [view(a, i1+1:i2) for (i1, i2) in zip(s1, s2)]
end
Also, I changed the signature to the conventional one of "functions first", which allows you to use do-blocks. Additionally, this should work with offset indexing.
One could surely get rid of the intermediate allocations, but I think that gets ugly without yield:
function split_by(λ, a::Vector)
result = Vector{typeof(view(a, 1:0))}()
l = firstindex(a)
r = firstindex(a)
while r <= lastindex(a)
if λ(a[r])
push!(result, #view(a[l:r]))
l = r + 1
end
r += 1
end
push!(result, #view(a[l:end]))
return result
end
Let's say I have a vector of unique integers, for example [1, 2, 6, 4] (sorting doesn't really matter).
Given some n, I want to get all possible values of summing n elements of the set, including summing an element with itself. It is important that the list I get is exhaustive.
For example, for n = 1 I get the original set.
For n = 2 I should get all values of summing 1 with all other elements, 2 with all others etc. Some kind of memory is also required, in the sense that I have to know from which entries of the original set did the sum I am facing come from.
For a given, specific n, I know how to solve the problem. I want a concise way of being able to solve it for any n.
EDIT: This question is for Julia 0.7 and above...
This is a typical task where you can use a dictionary in a recursive function (I am annotating types for clarity):
function nsum!(x::Vector{Int}, n::Int, d=Dict{Int,Set{Vector{Int}}},
prefix::Vector{Int}=Int[])
if n == 1
for v in x
seq = [prefix; v]
s = sum(seq)
if haskey(d, s)
push!(d[s], sort!(seq))
else
d[s] = Set([sort!(seq)])
end
end
else
for v in x
nsum!(x, n-1, d, [prefix; v])
end
end
end
function genres(x::Vector{Int}, n::Int)
n < 1 && error("n must be positive")
d = Dict{Int, Set{Vector{Int}}}()
nsum!(x, n, d)
d
end
Now you can use it e.g.
julia> genres([1, 2, 4, 6], 3)
Dict{Int64,Set{Array{Int64,1}}} with 14 entries:
16 => Set(Array{Int64,1}[[4, 6, 6]])
11 => Set(Array{Int64,1}[[1, 4, 6]])
7 => Set(Array{Int64,1}[[1, 2, 4]])
9 => Set(Array{Int64,1}[[1, 4, 4], [1, 2, 6]])
10 => Set(Array{Int64,1}[[2, 4, 4], [2, 2, 6]])
8 => Set(Array{Int64,1}[[2, 2, 4], [1, 1, 6]])
6 => Set(Array{Int64,1}[[2, 2, 2], [1, 1, 4]])
4 => Set(Array{Int64,1}[[1, 1, 2]])
3 => Set(Array{Int64,1}[[1, 1, 1]])
5 => Set(Array{Int64,1}[[1, 2, 2]])
13 => Set(Array{Int64,1}[[1, 6, 6]])
14 => Set(Array{Int64,1}[[4, 4, 6], [2, 6, 6]])
12 => Set(Array{Int64,1}[[4, 4, 4], [2, 4, 6]])
18 => Set(Array{Int64,1}[[6, 6, 6]])
EDIT: In the code I use sort! and Set to avoid duplicate entries (remove them if you want duplicates). Also you could keep track how far in the index on vector x in the loop you reached in outer recursive calls to avoid generating duplicates at all, which would speed up the procedure.
I want a concise way of being able to solve it for any n.
Here is a concise solution using IterTools.jl:
Julia 0.6
using IterTools
n = 3
summands = [1, 2, 6, 4]
myresult = map(x -> (sum(x), x), reduce((x1, x2) -> vcat(x1, collect(product(fill(summands, x2)...))), [], 1:n))
(IterTools.jl is required for product())
Julia 0.7
using Iterators
n = 3
summands = [1, 2, 6, 4]
map(x -> (sum(x), x), reduce((x1, x2) -> vcat(x1, vec(collect(product(fill(summands, x2)...)))), 1:n; init = Vector{Tuple{Int, NTuple{n, Int}}}[]))
(In Julia 0.7, the parameter position of the neutral element changed from 2nd to 3rd argument.)
How does this work?
Let's indent the one-liner (using the Julia 0.6 version, the idea is the same for the Julia 0.7 version):
map(
# Map the possible combinations of `1:n` entries of `summands` to a tuple containing their sum and the summands used.
x -> (sum(x), x),
# Generate all possible combinations of `1:n`summands of `summands`.
reduce(
# Concatenate previously generated combinations with the new ones
(x1, x2) -> vcat(
x1,
vec(
collect(
# Cartesian product of all arguments.
product(
# Use `summands` for `x2` arguments.
fill(
summands,
x2)...)))),
# Specify for what lengths we want to generate combinations.
1:n;
# Neutral element (empty array).
init = Vector{Tuple{Int, NTuple{n, Int}}}[]))
Julia 0.6
This is really just to get a free critique from the experts as to why my method is inferior to theirs!
using Combinatorics, BenchmarkTools
function nsum(a::Vector{Int}, n::Int)::Vector{Tuple{Int, Vector{Int}}}
r = Vector{Tuple{Int, Vector{Int}}}()
s = with_replacement_combinations(a, n)
for i in s
push!(r, (sum(i), i))
end
return sort!(r, by = x -> x[1])
end
#btime nsum([1, 2, 6, 4], 3)
It runs in circa 4.154 μs on my 1.8 GHz processor for n = 3. It produces a sorted array showing the sum (which may appear more than once) and how it is made up (which is unique to each instance of the sum).
My book has the following definition of inorder traversal (it computes a list with the elements of the tree in the inorder order within a list:
fun trav Empty = []
| trav(Node(t_1, x, t_2)) = trav t_1 # (x::trav t_2);
What's the convention / standard for simplifying the calls in the second line (namely, trav t_1 and x::trav t_2)? I know I simplify both of them before making use of the # operator but I'd like to know whether the first trav call evaluates completely before the other call, vice versa (unlikely), or both simultaneously.
Thanks
bclayman
Your intuition is correct, trav t_1 gets evaluated first as function arguments are evaluated in left to right order. This might seem a little strange, since # is an infix operator, but [1, 2, 3] # [4, 5, 6] can actually be rewritten as (op #)([1, 2, 3], [4, 5, 6]). You can verify that # evaluates its left argument first by doing:
Standard ML of New Jersey v110.78 [built: Sun Jun 7 20:21:33 2015]
- (print "test1\n"; [1, 2, 3]) # (print "test2\n"; [4, 5, 6]);
test1
test2
val it = [1,2,3,4,5,6] : int list
-
Essentially what you have is equivalent to:
fun trav Empty = []
| trav(Node(t_1, x, t_2)) =
let val l = trav t_1
val r = trav t_2
in l # (x::r) end
I'm trying to match all the paths (up to a certain length) among a group of nodes. I can successfully do so by issuing the following query:
MATCH (n) WHERE ID(n) IN [1, 2, 3, 4, 5]
MATCH (m) WHERE ID(m) IN [1, 2, 3, 4, 5]
MATCH paths = allShortestPaths((n)-[*..3]-(m))
RETURN paths
I'm satisfied with both the result itself and its speed. What I don't understand is whether there is a way of defining a variable to define the collection [1, 2, 3, 4, 5] just once. Sort of:
x = [1, 2, 3, 4, 5]
MATCH (n) WHERE ID(n) IN x
MATCH (m) WHERE ID(m) IN x
MATCH paths = allShortestPaths((n)-[*..3]-(m))
RETURN paths
Is this possible? I've tried several alternatives (using WITH and AS) but with no luck.
Thanks
Use:
WITH [1, 2, 3, 4, 5] AS x
As in:
WITH [1, 2, 3, 4, 5] AS x
MATCH (n) WHERE ID(n) IN x
MATCH (m) WHERE ID(m) IN x
MATCH paths = allShortestPaths((n)-[*..3]-(m))
RETURN paths
By the way, there seems to be a regression in neo4j-community-2.2.0-M03, which causes an error with the above query. M02 seems to have no problems.