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.

View this sample in: C# F#

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