Skip to content

Block Vectors

Summary

Here we show how to use blocked vectors and blocked dual vectors.

Blocked vectors and dual vectors in the algebra package are wrappers around Stream[(Long, DenseVector[Double])] each partition consists of an ordered index and the partition content which is in the form of a breeze vector.

The relevant API endpoints are PartitionedVector and PartitionedDualVector. In order to access these objects, you must do import io.github.mandar2812.dynaml.algebra._ (already loaded by default in the DynaML shell).

Creation

Block vectors can be created in a number of ways. PartitionedVector and PartitionedDualVector are column row vectors respectively and treated as transposes of each other.

From Input Blocks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Create the data blocks
val data_blocks: Stream[(Long, DenseVector[Double])] =
  (0L until 10L).toStream.map(index => (index, DenseVector.ones[Double](500)))

//Instantiate the partitioned vector

val part_vector = PartitionedVector(data_blocks)

//Optionally you may also provide the total length
//of the partitioned vector

val part_vector = PartitionedVector(data_blocks, num_rows: Long = 5000L)


//Created Block Dual Vector

val part_dvector = PartitionedDualVector(data_blocks)

//Optionally you may also provide the total length
//of the partitioned dual vector

val part_dvector = PartitionedDualVector(data_blocks, num_rows: Long = 5000L)

From Tabulating Functions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
val tabFunc: (Long) => Double =
  (index: Long) => math.sin(2d*math.Pi*index/5000d)

//Instantiate the partitioned vector
val part_vector = PartitionedVector(
  length = 5000L, numElementsPerBlock = 500,
  tabFunc)

//Instantiate the partitioned dual vector
val part_dvector = PartitionedDualVector(
  length = 5000L, numElementsPerBlock = 500,  tabFunc)

From a Stream

1
2
3
4
5
//Create the data stream
val data: Stream[Double] = Stream.fill[Double](5000)(1.0)

//Instantiate the partitioned vector
val part_vector = PartitionedVector(data, length = 5000L, num_elements_per_block = 500)

From a Breeze Vector

1
2
3
4
5
//Create the data blocks
val data_vector = DenseVector.ones[Double](5000)

//Instantiate the partitioned vector
val part_vector = PartitionedVector(data_vector, num_elements_per_block = 500)

Apart from the above methods of creation there are a number of convenience functions available.

Vector with Filled Values

Vector of zeros

1
val ones_vec = PartitionedVector.zeros(5000L, 500)

Vector of Ones

1
val ones_vec = PartitionedVector.ones(5000L, 500)

Vector of Random Values

1
2
3
val random_var = RandomVariable(new Beta(1.5, 2.5))

val rand_vec = PartitionedVector.rand(5000L, 500, random_var)

Vector Concatenation

1
2
3
4
5
6
7
val random_var = RandomVariable(new Beta(1.5, 2.5))

val rand_vec1 = PartitionedVector.rand(2000L, 500, random_var)
val rand_vec2 = PartitionedVector.rand(2000L, 500, random_var)

//Vector of length 4000, having 8 blocks of 500 elements each
val vec = PartitionedVector.vertcat(rand_vec1, rand_vec2)

Tip

A PartitionedDualVector can be created via the transpose operation on a PartitionedVector instance and vice versa.

1
2
3
4
5
val random_var = RandomVariable(new Beta(1.5, 2.5))

val p_vec = PartitionedVector.rand(5000L, 500, random_var)

val p_dvec = p_vec.t

Algebraic Operations

Partitioned vectors and dual vectors have a number of algebraic operations available in the API.

 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
28
29
val beta_var = RandomVariable(Beta(1.5, 2.5))
val gamma_var = RandomVariable(Gamma(1.5, 2.5))

val p_vec_beta = PartitionedVector.rand(5000L, 500, beta_var)
val p_vec_gamma = PartitionedVector.rand(5000L, 500, gamma_var)

val dvec_beta = p_vec_beta.t
val dvec_gamma = p_vec_gamma.t

//Addition
val add_vec = p_vec_beta + p_vec_gamma
val add_dvec = dvec_beta + dvec_gamma

//Subtraction
val sub_vec = p_vec_beta - p_vec_gamma
val sub_dvec = dvec_beta - dvec_gamma

//Element wise multiplication
val mult_vec = p_vec_beta :* p_vec_gamma

//Element wise division
val div_vec = p_vec_beta :/ p_vec_gamma

//Inner Product
val prod = dvec_gamma*p_vec_beta

//Scaler multiplication
val sc_vec = add_vec*1.5
val sc_dvec = add_dvec*2.5

Misc. Operations

Map Partitions

Map each index, partition pair by a scala function.

1
2
3
4
5
val vec: PartitionedVector = _

val other_vec = vec.map(
   (pair: (Long, DenseVector[Double])) => (pair._1, pair._2*1.5)
)

Slice

Obtain subset of elements, the new vector is repartitioned and re-indexed accordingly.

1
2
3
val vec: PartitionedVector = PartitionedVector.ones(5000L, 500)

val other_vec = vec(999L until 2000L)

Reverse

Reverse a block vector

1
2
3
val vec: PartitionedVector = PartitionedVector.ones(5000L, 500)

val reverse_vec = vec.reverse

Convert to Breeze Vector

1
2
3
4
5
val vec: PartitionedVector = PartitionedVector.ones(5000L, 500)

//Do not use on large vectors as
//it might lead to overflow of memory.
val breeze_vec = vec.toBreezeVector

Comments