scalanlp / breeze

Breeze is/was a numerical processing library for Scala.
https://www.scalanlp.org
Apache License 2.0
3.45k stars 693 forks source link

How to dynamically create a matrix from tuples? #774

Closed aliakhtar closed 4 years ago

aliakhtar commented 4 years ago

If I try to create a DenseMatrix by harcoding a tuple of coordinates, the matrix correctly identifies the structure of the matrix (in this case, being 3x2) and inferring the x,y coordinates correctly from the tuples:

val foo = DenseMatrix((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
println(foo)

1.0 2.0
3.0 4.0
5.0 6.0

But, there can be cases in which we don't know the values of the tuples upfront, instead we might have an iterable containing the tuples. E.g:

        val tuples = Seq(
            (1.0, 2.0), (3.0, 4.0), (5.0, 6.0)
        )
       val foo = DenseMatrix(tuples)
        println(foo)

However, this gives a DenseMatrix[(Double, Double)] instead of DenseMatrix[Double] and the output will be just a 1x3 matrix instead of 3x2:

(1.0,2.0) (3.0,4.0) (5.0,6.0)

Converting the tuples to an array of numbers, and passing the number of rows & cols, doesn't work either:

val numbers = Seq(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).toArray
val bar = new DenseMatrix(rows = 3, cols = 2, data = numbers)
println(bar

While the resulting matrix is correctly 3x2, the order of the data is weird:

1.0  4.0  
2.0  5.0  
3.0  6.0  

We're getting (1, 4) instead of (1, 2) and so on.

So, what can be done so the constructor DenseMatrix((1.0, 2.0), (3.0, 4.0), (5.0, 6.0)) is called, but without hardcoding the tuples? Why is the order of the numbers weird when passing in the array of numbers?

dlwh commented 4 years ago

DenseMatrix(tuples:_*) should do it. You're hitting a different method by not explicitly unpacking the seq.

aliakhtar commented 4 years ago

@dlwh Yeah, that method can only be hit if you pass in the tuples manually. How can it be called with a dynamic seq / iterable of tuples?

dlwh commented 4 years ago

I feel fairly confident that DenseMatrix(seq:_*) will work.

On Tue, Mar 10, 2020 at 10:48 AM Ali Akhtar notifications@github.com wrote:

@dlwh https://github.com/dlwh Yeah, that method can only be hit if you pass in the tuples manually. How can it be called with a dynamic seq / iterable of tuples?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/scalanlp/breeze/issues/774?email_source=notifications&email_token=AAACLIL36SB75TTZ7T7MW63RGZ4OPA5CNFSM4LESTK3KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEOMOT4A#issuecomment-597223920, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAACLIIYTHJANVRRLKCXLILRGZ4OPANCNFSM4LESTK3A .

aliakhtar commented 4 years ago

@dlwh You're right. That's some dark magic right there. Mind explaining what its doing? I've never seen this syntax before

aliakhtar commented 4 years ago

Nvm, found an explanation: https://stackoverflow.com/questions/7938585/what-does-param-mean-in-scala

Still, I wish there was a better way which made it clearer what was going on.