You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by ap...@apache.org on 2016/03/15 23:20:14 UTC
mahout git commit: MAHOUT-1813: Functional 'apply' DSL for
distributed and in-memory matrices closes apache/mahout#194
Repository: mahout
Updated Branches:
refs/heads/master 7d71ad00a -> ff51ab448
MAHOUT-1813: Functional 'apply' DSL for distributed and in-memory matrices closes apache/mahout#194
Project: http://git-wip-us.apache.org/repos/asf/mahout/repo
Commit: http://git-wip-us.apache.org/repos/asf/mahout/commit/ff51ab44
Tree: http://git-wip-us.apache.org/repos/asf/mahout/tree/ff51ab44
Diff: http://git-wip-us.apache.org/repos/asf/mahout/diff/ff51ab44
Branch: refs/heads/master
Commit: ff51ab448b07c5b218d1a08ed5c1194ad5b24179
Parents: 7d71ad0
Author: Andrew Palumbo <ap...@apache.org>
Authored: Tue Mar 15 18:19:49 2016 -0400
Committer: Andrew Palumbo <ap...@apache.org>
Committed: Tue Mar 15 18:19:49 2016 -0400
----------------------------------------------------------------------
.../org/apache/mahout/math/drm/DrmLikeOps.scala | 23 ++++++-
.../mahout/math/scalabindings/MatrixOps.scala | 63 ++++++++++++++++++--
.../mahout/math/scalabindings/package.scala | 6 ++
.../mahout/math/drm/RLikeDrmOpsSuiteBase.scala | 14 +++++
.../math/scalabindings/MatrixOpsSuite.scala | 12 ++++
5 files changed, 112 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mahout/blob/ff51ab44/math-scala/src/main/scala/org/apache/mahout/math/drm/DrmLikeOps.scala
----------------------------------------------------------------------
diff --git a/math-scala/src/main/scala/org/apache/mahout/math/drm/DrmLikeOps.scala b/math-scala/src/main/scala/org/apache/mahout/math/drm/DrmLikeOps.scala
index e2c6e17..43b4f56 100644
--- a/math-scala/src/main/scala/org/apache/mahout/math/drm/DrmLikeOps.scala
+++ b/math-scala/src/main/scala/org/apache/mahout/math/drm/DrmLikeOps.scala
@@ -19,7 +19,7 @@ package org.apache.mahout.math.drm
import scala.reflect.ClassTag
import org.apache.mahout.math.scalabindings._
-import org.apache.mahout.math.drm.logical.{OpPar, OpMapBlock, OpRowRange}
+import org.apache.mahout.math.drm.logical.{OpAewUnaryFunc, OpPar, OpMapBlock, OpRowRange}
/** Common Drm ops */
class DrmLikeOps[K](protected[drm] val drm: DrmLike[K]) {
@@ -116,4 +116,25 @@ class DrmLikeOps[K](protected[drm] val drm: DrmLike[K]) {
} else rowSrc
}
+
+ /**
+ * Apply a function element-wise.
+ *
+ * @param f element-wise function
+ * @param evalZeros Do we have to process zero elements? true, false, auto: if auto, we will test
+ * the supplied function for `f(0) != 0`, and depending on the result, will
+ * decide if we want evaluation for zero elements. WARNING: the AUTO setting
+ * may not always work correctly for functions that are meant to run in a specific
+ * backend context, or non-deterministic functions, such as {-1,0,1} random
+ * generators.
+ * @return new DRM with the element-wise function applied.
+ */
+ def apply(f: Double ⇒ Double, evalZeros: AutoBooleanEnum.T = AutoBooleanEnum.AUTO) = {
+ val ezeros = evalZeros match {
+ case AutoBooleanEnum.TRUE ⇒ true
+ case AutoBooleanEnum.FALSE ⇒ false
+ case AutoBooleanEnum.AUTO ⇒ f(0) != 0
+ }
+ new OpAewUnaryFunc[K](drm, f, ezeros)
+ }
}
http://git-wip-us.apache.org/repos/asf/mahout/blob/ff51ab44/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/MatrixOps.scala
----------------------------------------------------------------------
diff --git a/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/MatrixOps.scala b/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/MatrixOps.scala
index cb92e1d..f3be285 100644
--- a/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/MatrixOps.scala
+++ b/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/MatrixOps.scala
@@ -128,10 +128,60 @@ class MatrixOps(val m: Matrix) {
}
/**
- * Warning: This provides read-only view only.
+ * Apply a function element-wise without side-effects to the argument (creates a new matrix).
+ *
+ * @param f element-wise function "value" ⇒ "new value"
+ * @param evalZeros Do we have to process zero elements? true, false, auto: if auto, we will test
+ * the supplied function for `f(0) != 0`, and depending on the result, will
+ * decide if we want evaluation for zero elements. WARNING: the AUTO setting
+ * may not always work correctly for functions that are meant to run in a specific
+ * backend context, or non-deterministic functions, such as {-1,0,1} random
+ * generators.
+ * @return new DRM with the element-wise function applied.
+ */
+ def apply(f: Double ⇒ Double, evalZeros: AutoBooleanEnum.T): Matrix = {
+ val ezeros = evalZeros match {
+ case AutoBooleanEnum.TRUE ⇒ true
+ case AutoBooleanEnum.FALSE ⇒ false
+ case AutoBooleanEnum.AUTO ⇒ f(0) != 0
+ }
+ if (ezeros) m.cloned := f else m.cloned ::= f
+ }
+
+ /**
+ * Apply a function element-wise without side-effects to the argument (creates a new matrix).
+ *
+ * @param f element-wise function (row, column, value) ⇒ "new value"
+ * @param evalZeros Do we have to process zero elements? true, false, auto: if auto, we will test
+ * the supplied function for `f(0) != 0`, and depending on the result, will
+ * decide if we want evaluation for zero elements. WARNING: the AUTO setting
+ * may not always work correctly for functions that are meant to run in a specific
+ * backend context, or non-deterministic functions, such as {-1,0,1} random
+ * generators.
+ * @return new DRM with the element-wise function applied.
+ */
+ def apply(f: (Int, Int, Double) ⇒ Double, evalZeros: AutoBooleanEnum.T): Matrix = {
+ val ezeros = evalZeros match {
+ case AutoBooleanEnum.TRUE ⇒ true
+ case AutoBooleanEnum.FALSE ⇒ false
+ case AutoBooleanEnum.AUTO ⇒ f(0,0,0) != 0
+ }
+ if (ezeros) m.cloned := f else m.cloned ::= f
+ }
+
+ /** A version of function apply with default AUTO treatment of `evalZeros`. */
+ def apply(f: Double ⇒ Double): Matrix = apply(f, AutoBooleanEnum.AUTO)
+
+ /** A version of function apply with default AUTO treatment of `evalZeros`. */
+ def apply(f: (Int, Int, Double) ⇒ Double): Matrix = apply(f, AutoBooleanEnum.AUTO)
+
+
+ /**
+ * Warning: This provides read-only view only.
* In most cases that's what one wants. To get a copy,
* use <code>m.t cloned</code>
- * @return transposed view
+ *
+ * @return transposed view
*/
def t = Matrices.transposedView(m)
@@ -143,7 +193,8 @@ class MatrixOps(val m: Matrix) {
/**
* Assigning from a row-wise collection of vectors
- * @param that -
+ *
+ * @param that -
*/
def :=(that: TraversableOnce[Vector]) = {
var row = 0
@@ -212,7 +263,8 @@ class MatrixOps(val m: Matrix) {
* Ideally, we would probably want to override equals(). But that is not
* possible without modifying AbstractMatrix implementation in Mahout
* which would require discussion at Mahout team.
- * @param that
+ *
+ * @param that
* @return
*/
def equiv(that: Matrix) =
@@ -233,7 +285,8 @@ class MatrixOps(val m: Matrix) {
/**
* test if rank == min(nrow,ncol).
- * @return
+ *
+ * @return
*/
def isFullRank: Boolean =
new QRDecomposition(if (nrow < ncol) m t else m cloned).hasFullRank
http://git-wip-us.apache.org/repos/asf/mahout/blob/ff51ab44/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/package.scala
----------------------------------------------------------------------
diff --git a/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/package.scala b/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/package.scala
index 426996b..6a3aa06 100644
--- a/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/package.scala
+++ b/math-scala/src/main/scala/org/apache/mahout/math/scalabindings/package.scala
@@ -29,6 +29,12 @@ package object scalabindings {
// Reserved "ALL" range
final val `::`: Range = null
+ // Some enums
+ object AutoBooleanEnum extends Enumeration {
+ type T = Value
+ val TRUE, FALSE, AUTO = Value
+ }
+
implicit def seq2Vector(s: TraversableOnce[AnyVal]) =
new DenseVector(s.map(_.asInstanceOf[Number].doubleValue()).toArray)
http://git-wip-us.apache.org/repos/asf/mahout/blob/ff51ab44/math-scala/src/test/scala/org/apache/mahout/math/drm/RLikeDrmOpsSuiteBase.scala
----------------------------------------------------------------------
diff --git a/math-scala/src/test/scala/org/apache/mahout/math/drm/RLikeDrmOpsSuiteBase.scala b/math-scala/src/test/scala/org/apache/mahout/math/drm/RLikeDrmOpsSuiteBase.scala
index b46ee30..685c540 100644
--- a/math-scala/src/test/scala/org/apache/mahout/math/drm/RLikeDrmOpsSuiteBase.scala
+++ b/math-scala/src/test/scala/org/apache/mahout/math/drm/RLikeDrmOpsSuiteBase.scala
@@ -634,5 +634,19 @@ trait RLikeDrmOpsSuiteBase extends DistributedMahoutSuite with Matchers {
}
+ test("functional apply()") {
+ val mxA = sparse (
+ (1 -> 3) :: (7 -> 7) :: Nil,
+ (4 -> 5) :: (5 -> 8) :: Nil
+ )
+
+ val mxAControl = mxA cloned
+ val drmA = drmParallelize(mxA)
+
+ (drmA(x => x + 1).collect - (mxAControl + 1)).norm should be < 1e-7
+ (drmA(x => x * 2).collect - (2 * mxAControl)).norm should be < 1e-7
+
+ }
+
}
http://git-wip-us.apache.org/repos/asf/mahout/blob/ff51ab44/math-scala/src/test/scala/org/apache/mahout/math/scalabindings/MatrixOpsSuite.scala
----------------------------------------------------------------------
diff --git a/math-scala/src/test/scala/org/apache/mahout/math/scalabindings/MatrixOpsSuite.scala b/math-scala/src/test/scala/org/apache/mahout/math/scalabindings/MatrixOpsSuite.scala
index 5c8a310..1296d9e 100644
--- a/math-scala/src/test/scala/org/apache/mahout/math/scalabindings/MatrixOpsSuite.scala
+++ b/math-scala/src/test/scala/org/apache/mahout/math/scalabindings/MatrixOpsSuite.scala
@@ -131,6 +131,18 @@ class MatrixOpsSuite extends FunSuite with MahoutSuite {
g.sum shouldBe 3
}
+ test("functional apply()") {
+ val mxA = sparse (
+ (1 -> 3) :: (7 -> 7) :: Nil,
+ (4 -> 5) :: (5 -> 8) :: Nil
+ )
+ val mxAControl = mxA cloned
+
+ (mxA(x ⇒ x + 1) - (mxAControl + 1)).norm should be < 1e-7
+ (mxA(x ⇒ x * 2) - (2 * mxAControl)).norm should be < 1e-7
+
+ }
+
test("sparse") {
val a = sparse((1, 3) :: Nil,