3
$\begingroup$

OK, so I've never had to write a line of Mathematica code (except for using it interactively as a calculator), but for this it looks like I have to. If someone could provide me with the code for the following, then I can edit it to do what I'm actually trying to accomplish. I need to do the following:

  1. Input is a set $S$ of integers and some positive integers $n,m$

  2. I want to generate all the possible vectors $X$ and $Y$, where $X$ has length $n$ and $Y$ has length $m$ and the elements of each vector belong to the set $S$.

  3. I need to loop over all the possible values of $X$ and $Y$.

Something like this would be trivial to write down in, say, Haskell using list comprehensions, but having flipped through the Mathematica language reference for an hour, I couldn't figure out an easy way to do this.

The values of $n$ and $m$ are such that there are about 300 million possible combinations. Therefore, it's not possible to just take Cartesian products of $S$ and then iterate over the set, unless there's a way of generating the elements in a lazy way. Otherwise the machine would run out of memory.

$\endgroup$
  • $\begingroup$ Welcome to the world of Mathematica programming! Unfortunately I don't have the time this morning to address this question in full. You are correct that Mathematica doesn't have Haskell's list comprehensions. Usually the fastest non-compiled approach is to process in chunks. See (21584) for a few ideas there. It may help if you explain what you are doing with each X and Y pair. $\endgroup$ – Mr.Wizard Sep 21 '14 at 10:34
  • $\begingroup$ There ARE For loops. Which are slow, but if you generate partial cartesian product (with Outer) and finish with a single For loop (if your set has cardinality, say, 10) that should address both the memory and the speed problems. $\endgroup$ – Igor Rivin Sep 21 '14 at 10:34
  • $\begingroup$ In the actual problem I have four of these vectors that I need to independently generate, but I only need two as an example to extrapolate from the code. I compute $X^tY$ for a bunch of these vectors to form a matrix, compute left and right kernels, check whether they intersect certain subspaces. What I need to find is values for these vectors, where the matrix and its kernel satisfies a bunch of constraints... and I hope it exists and I don't need to search the whole space. $\endgroup$ – eof Sep 21 '14 at 10:38
  • $\begingroup$ I'm also expecting that an exhaustive search can take a week or so, but it's OK, since what I'm doing is searching for a counterexample. $\endgroup$ – eof Sep 21 '14 at 10:43
2
$\begingroup$

Mathematica has no built-in notion of Haskell-like lazy computation. Although there have been attempts to simulate it, I would probably tackle this problem with a simple imperative loop.

Let's start with an example generator set, which we will call $s:

$s = Array[Prime, 20]
(* {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71} *)

We will now define a helper function s that can return a vector of any rank using elements from that set:

s[i__] := $s[[{i}]]

So now:

s[3, 7]
(* {5, 17} *)

s[12, 9, 15]
(* {37, 23, 47} *)

This enables us to write a simple Do loop to scan over pairs of vectors of any size. Here is an example that scans pairs of 2-vectors and 3-vectors to find the first such pair with a nonsense property:

Module[{c = Length @ $s, x, y}
, Do[
    x = s[x0, x1]
  ; y = s[y0, y1, y2]
  ; If[Total[x] - Total[y] == 39, Return[{x, y}]]
  , {x0, c}, {x1, c}
  , {y0, c}, {y1, c}, {y2, c}
  ]
]

(* {{2, 43}, {2, 2, 2}} *)
$\endgroup$
  • $\begingroup$ Yes, just having the lambda operator in the language makes it possible to simulate lazynes, but doing so would be a pain. Your method is to be able to do this without that much boilerplate code. Thanks. $\endgroup$ – eof Sep 21 '14 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.