Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 699297
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T03:22:15+00:00 2026-05-14T03:22:15+00:00

Is there a good algorithm to calculate the cartesian product of three seq s

  • 0

Is there a good algorithm to calculate the cartesian product of three seqs concurrently in Clojure?

I’m working on a small hobby project in Clojure, mainly as a means to learn the language, and its concurrency features. In my project, I need to calculate the cartesian product of three seqs (and do something with the results).

I found the cartesian-product function in clojure.contrib.combinatorics, which works pretty well. However, the calculation of the cartesian product turns out to be the bottleneck of the program. Therefore, I’d like to perform the calculation concurrently.

Now, for the map function, there’s a convenient pmap alternative that magically makes the thing concurrent. Which is cool :). Unfortunately, such a thing doesn’t exist for cartesian-product. I’ve looked at the source code, but I can’t find an easy way to make it concurrent myself.

Also, I’ve tried to implement an algorithm myself using map, but I guess my algorithmic skills aren’t what they used to be. I managed to come up with something ugly for two seqs, but three was definitely a bridge too far.

So, does anyone know of an algorithm that’s already concurrent, or one that I can parallelize myself?


EDIT

Put another way, what I’m really trying to achieve, is to achieve something similar to this Java code:

for (ClassA a : someExpensiveComputation()) {
    for (ClassB b : someOtherExpensiveComputation()) {
        for (ClassC c : andAnotherOne()) {
            // Do something interesting with a, b and c
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T03:22:16+00:00Added an answer on May 14, 2026 at 3:22 am

    If the logic you’re using to process the Cartesian product isn’t somehow inherently sequential, then maybe you could just split your inputs into halves (perhaps splitting each input seq in two), calculate 8 separate Cartesian products (first-half x first-half x first-half, first-half x first-half x second-half, …), process them and then combine the results. I’d expect this to give you quite a boost already. As for tweaking the performance of the Cartesian product building itself, I’m no expert, but I do have some ideas & observations (one needs to calculate a cross product for Project Euler sometimes), so I’ve tried to summarise them below.

    First of all, I find the c.c.combinatorics function a bit strange in the performance department. The comments say it’s taken from Knuth, I believe, so perhaps one of the following obtains: (1) it would be very performant with vectors, but the cost of vectorising the input sequences kills its performance for other sequence types; (2) this style of programming doesn’t necessarily perform well in Clojure in general; (3) the cumulative overhead incurred due to some design choice (like having that local function) is large; (4) I’m missing something really important. So, while I wouldn’t like to dismiss the possibility that it might be a great function to use for some use cases (determined by the total number of seqs involved, the number of elements in each seq etc.), in all my (unscientific) measurements a simple for seems to fare better.

    Then there are two functions of mine, one of which is comparable to for (somewhat slower in the more interesting tests, I think, though it seems to be actually somewhat faster in others… can’t say I feel prepared to make a fully educated comparison), the other apparently faster with a long initial input sequence, as it’s a restricted functionality parallel version of the first one. (Details follow below.) So, timings first (do throw in the occasional (System/gc) if you care to repeat them):

    ;; a couple warm-up runs ellided
    user> (time (last (doall (pcross (range 100) (range 100) (range 100)))))
    "Elapsed time: 1130.751258 msecs"
    (99 99 99)
    user> (time (last (doall (cross (range 100) (range 100) (range 100)))))
    "Elapsed time: 2428.642741 msecs"
    (99 99 99)
    user> (require '[clojure.contrib.combinatorics :as comb])
    nil
    user> (time (last (doall (comb/cartesian-product (range 100) (range 100) (range 100)))))
    "Elapsed time: 7423.131008 msecs"
    (99 99 99)
    ;; a second time, as no warm-up was performed earlier...
    user> (time (last (doall (comb/cartesian-product (range 100) (range 100) (range 100)))))
    "Elapsed time: 6596.631127 msecs"
    (99 99 99)
    ;; umm... is syntax-quote that expensive?
    user> (time (last (doall (for [x (range 100)
                                   y (range 100)
                                   z (range 100)]
                               `(~x ~x ~x)))))
    "Elapsed time: 11029.038047 msecs"
    (99 99 99)
    user> (time (last (doall (for [x (range 100)
                                   y (range 100)
                                   z (range 100)]
                               (list x y z)))))
    "Elapsed time: 2597.533138 msecs"
    (99 99 99)
    ;; one more time...
    user> (time (last (doall (for [x (range 100)
                                   y (range 100)
                                   z (range 100)]
                               (list x y z)))))
    "Elapsed time: 2179.69127 msecs"
    (99 99 99)
    

    And now the function definitions:

    (defn cross [& seqs]
      (when seqs
        (if-let [s (first seqs)]
          (if-let [ss (next seqs)]
            (for [x  s
                  ys (apply cross ss)]
              (cons x ys))
            (map list s)))))
    
    (defn pcross [s1 s2 s3]
      (when (and (first s1)
                 (first s2)
                 (first s3))
        (let [l1 (count s1)
              [half1 half2] (split-at (quot l1 2) s1)
              s2xs3 (cross s2 s3)
              f1 (future (for [x half1 yz s2xs3] (cons x yz)))
              f2 (future (for [x half2 yz s2xs3] (cons x yz)))]
          (concat @f1 @f2))))
    

    I believe that all versions produce the same results. pcross could be extended to handle more sequences or be more sophisticated in the way it splits its workload, but that’s what I came up with as a first approximation… If you do test this out with your programme (perhaps adapting it to your needs, of course), I’d be very curious to know the results.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Is there a good algorithm to split a randomly generated number into three buckets,
Having recently begun working on a project which might need (good) scaling possibilities, I've
my question is: is there a good (common) algorithm to create numbers, which match
Hi I would like to know if there is a good algorithm to the
What's a good algorithm to solve this problem? I have three groups of people
Is there a good gem to track/log user activities on the site? Like when
Are there some good resources tutorials or anyone has tried to implement a Capcha
Is there any good library which supports WebSockets and is compatible with GWT? Ideally,
Are there any good technical comparisons available between the various game development options available.
Is there a good C library for graph theoretic manipulations? I particularly need to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.