slicing multidimensional vectors (vectors of vectors of vectors ...)

26 views
Skip to first unread message

Rock

unread,
Jan 9, 2010, 3:22:37 PM1/9/10
to Clojure
Hi all.

I'm working on implementing a solution for extracting slices of
multidimensional vectors, in the sense of vectors of vectors. I'm
taking the recursive route. I'm almost there, just have to work out a
few things. But I was wondering, this being a rather straightforward
need, perhaps it's already been done by someone, or maybe it's even in
the colujure.contrib libraries somewhere, so I thought I'd come here
and ask to see if anybody knows something I don't! I wouldn't want to
reinvent the wheel so to speak :)

Anyway, I'm trying to follow the MATLAB path. For instance, suppose
this is a 5x5 matrix:

(def a [[2 3 5 7 11] [13 17 19 23 29] [31 37 41 43 47] [53 59 61
67 71] [73 79 83 89 97]])

This:

(submvec a [[0 2 4] [0 2 4]])

would yield:

[[2 5 11] [13 19 29] [31 41 47] [53 61 71] [73 83 97]] (actually a
sequence)

In other words, [0 2 4] is to be interpreted as [START STRIDE END].
STRIDE should be optional.

What do you think? And, above all, has it already been done (or
something similar)?

Thank you.

Rock

Konrad Hinsen

unread,
Jan 10, 2010, 4:01:11 AM1/10/10
to clo...@googlegroups.com
On 09.01.2010, at 21:22, Rock wrote:

> I'm working on implementing a solution for extracting slices of
> multidimensional vectors, in the sense of vectors of vectors. I'm
> taking the recursive route.

I have some code for working with nested vectors here:

http://code.google.com/p/clj-multiarray/source/browse/src/clj_multiarray/nested_vectors.clj

It's work in progress, but it may give you some ideas.

> Anyway, I'm trying to follow the MATLAB path. For instance, suppose
> this is a 5x5 matrix:
>
> (def a [[2 3 5 7 11] [13 17 19 23 29] [31 37 41 43 47] [53 59 61
> 67 71] [73 79 83 89 97]])
>
> This:
>
> (submvec a [[0 2 4] [0 2 4]])
>
> would yield:
>
> [[2 5 11] [13 19 29] [31 41 47] [53 61 71] [73 83 97]] (actually a
> sequence)
>
> In other words, [0 2 4] is to be interpreted as [START STRIDE END].
> STRIDE should be optional.

That's my "sample" function:

(defn nv-sample
[x dim start end step]
(assert (vector? x))
(if (zero? dim)
(vec (take-nth step (subvec x start end)))
(vec (map #(nv-sample % (dec dim) start end step) x))))

Just call it once for each dimension (0 and 1).

Konrad.

Rock

unread,
Jan 10, 2010, 4:35:12 AM1/10/10
to Clojure
Great Konrad! Thank you. My code is similar to yours. I think I will
put what you've just shown me to good use. There are a few good points
I hadn't thought about. I'm so happy that you are working on this as
well. I think Clojure has immense potential for scientific and
mathematical computing, but this aspect has been somewhat neglected
until now for some reason. Let's hope for a big change in this respect
as soon as possible.

Rock

On Jan 10, 10:01 am, Konrad Hinsen <konrad.hin...@fastmail.net> wrote:
> On 09.01.2010, at 21:22, Rock wrote:
>
> > I'm working on implementing a solution for extracting slices of
> > multidimensional vectors, in the sense of vectors of vectors. I'm
> > taking the recursive route.
>
> I have some code for working with nested vectors here:
>

>        http://code.google.com/p/clj-multiarray/source/browse/src/clj_multiar...

Konrad Hinsen

unread,
Jan 10, 2010, 6:15:42 AM1/10/10
to clo...@googlegroups.com
On 10.01.2010, at 10:35, Rock wrote:

> I hadn't thought about. I'm so happy that you are working on this as
> well. I think Clojure has immense potential for scientific and
> mathematical computing, but this aspect has been somewhat neglected
> until now for some reason. Let's hope for a big change in this respect
> as soon as possible.

I agree! I believe that a good array library is essential for
scientific applications, so that's what I started to work on. There
are already a couple of array libraries in the Java world, but they
all "suffer" from being designed for Java rather than for a dynamical
language such as Clojure.

My project clj-multiarray is in fact quite ambitious: I want to design
an array library not only for Clojure, but for other dynamic libraries
on the JVM as well. I am thinking in particular of Jython, which still
lacks an equivalent of the NumPy library for C-Python. My goal thus is
to have both a nice Clojure interface and a Java-level interface on
which other JVM languages can build. And I also want to facilitate
interfacing with the existing Java array libraries, in particular for
using I/O libraries (netCDF) and matrix-related code (linear algebra
etc.) that already exists in the Java world.

All this to explain why this is a slowly progressing project and still
likely to undergo important changes. It's definitely not ready for use
yet, but I welcome comments on its design.

Konrad.

Rock

unread,
Jan 10, 2010, 7:55:19 AM1/10/10
to Clojure
An ambitious project indeed!

As for the Java libraries, have you had a look at JScience? From what
I've seen, it's not at all bad. However, I do believe that, as far as
Clojure is concerned, it should have its own scientific libraries and
infrastructure. So I'm really glad that you've started this project. I
hope I will be able to contribute and help in any possible way.

Thanks again.

Konrad Hinsen

unread,
Jan 10, 2010, 2:23:52 PM1/10/10
to clo...@googlegroups.com
On 10.01.2010, at 13:55, Rock wrote:

> As for the Java libraries, have you had a look at JScience? From what
> I've seen, it's not at all bad.

It's an interesting library, but it lives clearly in the Java universe
of strict typing. Moreover, it doesn't really have arrays, just
vectors and matrices. Those are very well thought out and implemented,
but it's still a more limited approach than providing general N-
dimensional arrays.

A problem with all Java libraries is their orientation towards static
typing. In Clojure (like in Python), it is natural to have nested data
structures, and in particular nested vectors (in Python nested lists)
as a conceptual representation of multidimensional arrays. This
implies that array indexing operations can return either another array
or an element, meaning that the return type must be Object. This can
be done in Java but it is not a natural approach. Therefore the Java
libraries typically have separate operations for accessing elements
and for extracting subarrays, which makes many algorithms
unnecessarily cumbersome.

Konrad.

extrackc

unread,
Jan 10, 2010, 3:39:27 PM1/10/10
to Clojure
Have you looked into Incanter project? I just found out about it
recently. "Incanter is a Clojure-based, R-like platform for
statistical computing and graphics." http://incanter.org/

In particular, maybe this is useful:
http://liebke.github.com/incanter/core-api.html#incanter.core/sel

Carson

Konrad Hinsen

unread,
Jan 11, 2010, 2:26:15 AM1/11/10
to clo...@googlegroups.com
On 10 Jan 2010, at 21:39, extrackc wrote:

> Have you looked into Incanter project? I just found out about it
> recently. "Incanter is a Clojure-based, R-like platform for
> statistical computing and graphics." http://incanter.org/

Incanter uses ParallelColt as its underlying matrix library. While
this is a fine library for working with matrices, it is not a
multidimensional array library. Colt arrays exist only in 1, 2, and 3
dimensions and there are no generic (dimension-independent) operations
on array structure.

As the huge success of Matlab has shown, a lot can be done with just
matrices and vectors, but anyone who has used an array language (such
as APL) or an equivalent library (such as Python's NumPy) will feel
constrained by such an approach.

Konrad.

Rock

unread,
Jan 23, 2010, 8:45:55 AM1/23/10
to Clojure
I have a working function to slice multidimensional nested vectors a
la MATLAB (actually more like NumPy).

I'm using Konrad Hinsen's multi-array library (keep up the great work
Konrad!). Here's the code (I'm sure it can be greatly improved and
optimized):

(defn nv-subvec [x & ind]
(loop [v x
dim 0
i ind]
(let [[start end step] (first i)
other (rest i)]
(if (empty? other)
(nv-sample v dim start end step)
(recur (nv-sample v dim start end step) (inc dim) other)))))

It works like this:

(nv-subvec VECTOR SLICE+)

where each SLICE is [STAR END STEP].

Here's a 3 x 3 matrix:

(def a [[[1 2 3] [4 5 6] [7 8 9]] [[10 11 12] [13 14 15] [16 17 18]]
[[19 20 21] [22 23 24] [25 26 27]]])

user=> (nv-subvec a [0 3 2] [0 2 1] [1 3 1])

[[[2 3] [5 6]] [[20 21] [23 24]]]

user=> (nv-subvec a [0 3 2] [0 2 1])

[[[1 2 3] [4 5 6]] [[19 20 21] [22 23 24]]]

The result is correct in both cases. Seems to work fine. Of course a
lot of space for improvement.

Let me know what you think.

Rock

unread,
Jan 23, 2010, 8:47:59 AM1/23/10
to Clojure
Pardon, in the example above we have a 3 x 3 x 3 nested vector, not a
3 x 3 matrix!
Reply all
Reply to author
Forward
0 new messages