Accessing Tensor Elements in Visual Basic QuickStart Sample
Illustrates different ways of accessing elements of a tensor and sub-tensors using classes in the Numerics.NET.Tensors namespace in Visual Basic.
Imports Numerics.NET.Tensors
' Illustrates different ways of getting and setting
' elements of a tensor.
Module AccessingTensorElements
Sub Main()
' The license is verified at runtime. We're Imports
' a 30 day trial key here. For more information, see
' https:'numerics.net/trial-key
Numerics.NET.License.Verify("64542-18980-57619-62268")
'
' Accessing tensor elements
'
' Let's create a few tensors to work with:
Dim t = Tensor.CreateFromFunction((3, 4), Function (i, j) 11 + 10 * i + j)
' t -> ( ( 11, 12, 13, 14 ),
' ( 21, 22, 23, 24 ),
' ( 31, 32, 33, 34 ) )
' Actually, let's use something a little bigger:
t = Tensor.CreateFromFunction((3, 4, 5), Function (i, j, k) 100 * i + 10 * j + k)
' Tensors have indexer properties which get or set all or part
' of a tensor, including individual values.
' Important: All indexers return Tensor<T> objects,
' even if it contains just a single element!
Dim t123 = t(1, 2, 3)
' t123 -> ( 123 )
Console.WriteLine($"Type of t(1, 2, 3) -> {t123.GetType()}")
' Single values can be set Imports the indexer, but you
' have to assign a scalar tensor:
t(1, 2, 3) = Tensor.CreateScalar(999)
t123 = t(1, 2, 3)
' t123 -> ( 999 )
' To get an element's value, and not a scalar tensor,
' use the GetValue method:
Dim tValue = t.GetValue(1, 2, 3)
' tValue -> ( 999 )
' A corresponding SetValue method lets you set the value:
t.SetValue(99, 1, 2, 3)
tValue = t.GetValue(1, 2, 3)
' tValue -> ( 99 )
' When you leave out dimensions, the entire dimensions
' are returned:
Dim t12x = t(1, 2)
' t12x -> ( 120, 121, 122, 999, 124 )
' You can use ranges and slices to get or set sub-tensors.
' You can use either Numerics.NET.Range or System.Range:
Dim r12 = new Numerics.NET.Range(1, 2)
Dim trrr = t(r12, r12, r12)
' trrr -> ((( 111, 112), (121, 122)), (211, 212), (221, 222)))
Dim r13 = New Range(1, 3)
trrr = t(r13, r13, r13)
' You can mix and match:
Dim s = Tensor.CreateFromFunction((3, 3), Function (i, j) 11 + 10 * i + j)
' s -> (( 11 12 13 )
' ( 21 22 23 )
' ( 31 32 33 ))
Dim row1 = s(0, Range.All)
' row1 -> ( 11 12 13 )
Dim column1 = s(Range.All, New Index(2, True))
' column1 -> ( 12 22 32 )
Dim row2 = s(1, New System.Range(1, New Index(0, True)))
' row2 -> ( 22 23 )
' C#'s ranges do not support strides. For that, you have to use
' either Numerics.NET.Range or Numerics.NET.Slice:
Dim row3 = s(1, new Numerics.NET.Range(0, 2, 2))
' row3 -> ( 21 23 )
row3 = s(1, new Numerics.NET.Slice(2, 0, 2))
' row3 -> ( 21 23 )
' You can even have ranges with negative strides:
Dim x = Tensor.CreateRange(3)
' x -> ( 0 1 2 )
Dim reverse = x(new Numerics.NET.Range(2, 0, -1))
' reverse -> ( 2 1 0 )
reverse = x(new Numerics.NET.Slice(2, 2, -1))
' reverse -> ( 2 1 0 )
' You can set values Imports ranges and slices:
s(1, New System.Range(1, 3)) = Tensor.CreateFromArray({ 88, 99 })
' s -> (( 11 12 13 )
' ( 21 88 99 )
' ( 31 32 33 ))
s(New System.Range(0, New Index(1, True)), New Index(2, True)) = Tensor.CreateFromArray({ 1, 2 })
' s -> (( 11 1 13 )
' ( 21 2 99 )
' ( 31 32 33 ))
' TODO: s(1, new Range(0, 2, 2)) = Tensor.CreateFromArray(new() { 77, 66 })
' s -> (( 11 1 13 )
' ( 77 2 66 )
' ( 31 32 33 ))
'
' Advanced indexes:
'
' You can use sets of integers to specify only those elements:
Dim indexes = { 0, 3 }
Dim t1 = t(1, indexes, New Range(3, 5))
' t1 -> (( 103 133 )
' ( 104 134 ))
' You can also use a mask, an array of booleans, that are true
' for the elements you want to select:
Dim mask = { True, False, False, True }
Dim t2 = t(1, mask, New Range(3, 5))
' t2 -> (( 103 133 )
' ( 104 134 ))
'
' Copying and cloning tensors
'
' A shallow copy of a tensor constructs a tensor
' that shares the component storage with the original.
' This is done Imports an indexer:
Console.WriteLine("Shallow copy vs. clone:")
Dim t10 = t2(TensorIndex.All)
' The Copy method creates a full copy.
Dim t11 = t2.Copy()
' When we change t2, t10 changes, but t11 is left
' unchanged:
Console.WriteLine($"t2(1,1) = {t2(1, 1)}")
t2.SetValue(-2, 1, 1)
Console.WriteLine($"t10(1,1) = {t10(1, 1)}")
Console.WriteLine($"t11(1,1) = {t11(1, 1)}")
#If CLONEDATA
#End If
' We can give a tensor its own component storage
' by calling the CloneData method:
Console.WriteLine("CloneData:")
' TODO: t11.CloneData()
' Now, changing the original v2 no longer changes v7:
' t2(1, 1) = 4
Console.WriteLine($"t11(1,1) = {t11(1, 1)}")
Console.Write("Press Enter key to exit...")
Console.ReadLine()
End Sub
End Module