# 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¶

//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¶

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¶

//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¶

//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¶

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


#### Vector of Ones¶

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


#### Vector of Random Values¶

val random_var = RandomVariable(new Beta(1.5, 2.5))

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


### Vector Concatenation¶

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.

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.

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

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


## Misc. Operations¶

### Map Partitions¶

Map each index, partition pair by a scala function.

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.

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

val other_vec = vec(999L until 2000L)


### Reverse¶

Reverse a block vector

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

val reverse_vec = vec.reverse


### Convert to Breeze Vector¶

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