| @@ -18,10 +18,33 @@ namespace Tensorflow | |||||
| { | { | ||||
| public partial class tensorflow | public partial class tensorflow | ||||
| { | { | ||||
| public LinalgApi linalg { get; } = new LinalgApi(); | |||||
| public class LinalgApi | |||||
| { | |||||
| linalg_ops ops = new linalg_ops(); | |||||
| public Tensor eye(int num_rows, | |||||
| int num_columns = -1, | |||||
| TensorShape batch_shape = null, | |||||
| TF_DataType dtype = TF_DataType.TF_FLOAT, | |||||
| string name = null) | |||||
| => ops.eye(num_rows, num_columns: num_columns, batch_shape: batch_shape, dtype: dtype, name: name); | |||||
| public Tensor diag(Tensor diagonal, string name = null) | |||||
| => gen_array_ops.diag(diagonal, name: name); | |||||
| public Tensor matmul(Tensor a, Tensor b) | |||||
| => math_ops.matmul(a, b); | |||||
| public Tensor batch_matmul(Tensor x, Tensor y) | |||||
| => gen_math_ops.batch_mat_mul(x, y); | |||||
| } | |||||
| public Tensor diag(Tensor diagonal, string name = null) | public Tensor diag(Tensor diagonal, string name = null) | ||||
| => gen_array_ops.diag(diagonal, name: name); | => gen_array_ops.diag(diagonal, name: name); | ||||
| public Tensor matmul(Tensor a, Tensor b) | |||||
| public Tensor matmul(Tensor a, Tensor b) | |||||
| => math_ops.matmul(a, b); | => math_ops.matmul(a, b); | ||||
| public Tensor batch_matmul(Tensor x, Tensor y) | public Tensor batch_matmul(Tensor x, Tensor y) | ||||
| @@ -599,6 +599,46 @@ namespace Tensorflow | |||||
| public static Tensor invert_permutation(Tensor x, string name = null) | public static Tensor invert_permutation(Tensor x, string name = null) | ||||
| => gen_array_ops.invert_permutation(x, name: name); | => gen_array_ops.invert_permutation(x, name: name); | ||||
| public static Tensor matrix_diag(Tensor diagonal, | |||||
| string name = "diag", | |||||
| int k = 0, | |||||
| int num_rows = -1, | |||||
| int num_cols = -1, | |||||
| float padding_value = 0, | |||||
| string align = "RIGHT_LEFT") | |||||
| { | |||||
| if (tf.context.executing_eagerly()) | |||||
| { | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||||
| "MatrixDiagV3", name, | |||||
| null, | |||||
| diagonal, k, num_rows, num_cols, padding_value, | |||||
| "align", align); | |||||
| return results[0]; | |||||
| } | |||||
| throw new NotImplementedException(""); | |||||
| } | |||||
| public static Tensor matrix_set_diag(Tensor input, | |||||
| Tensor diagonal, | |||||
| string name = "set_diag", | |||||
| int k = 0, | |||||
| string align = "RIGHT_LEFT") | |||||
| { | |||||
| if (tf.context.executing_eagerly()) | |||||
| { | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||||
| "MatrixSetDiagV3", name, | |||||
| null, | |||||
| input, diagonal, k, | |||||
| "align", align); | |||||
| return results[0]; | |||||
| } | |||||
| throw new NotImplementedException(""); | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Computes the shape of a broadcast given symbolic shapes. | /// Computes the shape of a broadcast given symbolic shapes. | ||||
| /// When shape_x and shape_y are Tensors representing shapes(i.e.the result of | /// When shape_x and shape_y are Tensors representing shapes(i.e.the result of | ||||
| @@ -0,0 +1,43 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class linalg_ops | |||||
| { | |||||
| public Tensor eye(int num_rows, | |||||
| int num_columns = -1, | |||||
| TensorShape batch_shape = null, | |||||
| TF_DataType dtype = TF_DataType.TF_FLOAT, | |||||
| string name = null) | |||||
| { | |||||
| return tf_with(ops.name_scope(name, default_name: "eye", new { num_rows, num_columns, batch_shape }), scope => | |||||
| { | |||||
| if (num_columns == -1) | |||||
| num_columns = num_rows; | |||||
| bool is_square = num_columns == num_rows; | |||||
| var diag_size = Math.Min(num_rows, num_columns); | |||||
| if (batch_shape == null) | |||||
| batch_shape = new TensorShape(new int[0]); | |||||
| var diag_shape = batch_shape.dims.concat(new[] { diag_size }); | |||||
| int[] shape = null; | |||||
| if (!is_square) | |||||
| shape = batch_shape.dims.concat(new[] { num_rows, num_columns }); | |||||
| var diag_ones = array_ops.ones(diag_shape, dtype: dtype); | |||||
| if (is_square) | |||||
| return array_ops.matrix_diag(diag_ones); | |||||
| else | |||||
| { | |||||
| var zero_matrix = array_ops.zeros(shape, dtype: dtype); | |||||
| return array_ops.matrix_set_diag(zero_matrix, diag_ones); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public partial class TensorShape | |||||
| { | |||||
| public static implicit operator TensorShape(Shape shape) => new TensorShape((int[])shape.Dimensions.Clone()); | |||||
| public static implicit operator Shape(TensorShape shape) => new Shape((int[])shape.dims.Clone()); | |||||
| public static implicit operator int[](TensorShape shape) => shape == null ? null : (int[])shape.dims.Clone(); //we clone to avoid any changes | |||||
| public static implicit operator TensorShape(int[] dims) => dims == null ? null : new TensorShape(dims); | |||||
| public static explicit operator int(TensorShape shape) => shape.size; | |||||
| public static implicit operator TensorShape(int dim) => new TensorShape(dim); | |||||
| public static explicit operator (int, int)(TensorShape shape) => shape.dims.Length == 2 ? (shape.dims[0], shape.dims[1]) : (0, 0); | |||||
| public static implicit operator TensorShape((int, int) dims) => new TensorShape(dims.Item1, dims.Item2); | |||||
| public static explicit operator (int, int, int)(TensorShape shape) => shape.dims.Length == 3 ? (shape.dims[0], shape.dims[1], shape.dims[2]) : (0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3); | |||||
| public static explicit operator (int, int, int, int)(TensorShape shape) => shape.dims.Length == 4 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3]) : (0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4); | |||||
| public static explicit operator (int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 5 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4]) : (0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5); | |||||
| public static explicit operator (int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 6 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5]) : (0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6); | |||||
| public static explicit operator (int, int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 7 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5], shape.dims[6]) : (0, 0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6, dims.Item7); | |||||
| public static explicit operator (int, int, int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 8 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5], shape.dims[6], shape.dims[7]) : (0, 0, 0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6, dims.Item7, dims.Item8); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public partial class TensorShape | |||||
| { | |||||
| public override bool Equals(Object obj) | |||||
| { | |||||
| switch (obj) | |||||
| { | |||||
| case TensorShape shape1: | |||||
| return Enumerable.SequenceEqual(shape1.dims, dims); | |||||
| default: | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /*public static bool operator ==(TensorShape shape1, TensorShape shape2) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| public static bool operator !=(TensorShape shape1, TensorShape shape2) | |||||
| { | |||||
| return false; | |||||
| }*/ | |||||
| } | |||||
| } | |||||
| @@ -1,6 +1,7 @@ | |||||
| using NumSharp; | using NumSharp; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.ComponentModel; | |||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||
| @@ -12,7 +13,7 @@ namespace Tensorflow | |||||
| /// Represents the shape of a `Tensor`. | /// Represents the shape of a `Tensor`. | ||||
| /// </summary> | /// </summary> | ||||
| /// <remarks>https://www.tensorflow.org/api_docs/python/tf/TensorShape</remarks> | /// <remarks>https://www.tensorflow.org/api_docs/python/tf/TensorShape</remarks> | ||||
| public class TensorShape | |||||
| public partial class TensorShape | |||||
| { | { | ||||
| private readonly Shape shape; | private readonly Shape shape; | ||||
| @@ -255,35 +256,5 @@ namespace Tensorflow | |||||
| { | { | ||||
| return shape.ToString(); | return shape.ToString(); | ||||
| } | } | ||||
| public static implicit operator TensorShape(Shape shape) => new TensorShape((int[]) shape.Dimensions.Clone()); | |||||
| public static implicit operator Shape(TensorShape shape) => new Shape((int[]) shape.dims.Clone()); | |||||
| public static implicit operator int[](TensorShape shape) => shape == null ? null : (int[])shape.dims.Clone(); //we clone to avoid any changes | |||||
| public static implicit operator TensorShape(int[] dims) => dims == null ? null : new TensorShape(dims); | |||||
| public static explicit operator int(TensorShape shape) => shape.size; | |||||
| public static implicit operator TensorShape(int dim) => new TensorShape(dim); | |||||
| public static explicit operator (int, int)(TensorShape shape) => shape.dims.Length == 2 ? (shape.dims[0], shape.dims[1]) : (0, 0); | |||||
| public static implicit operator TensorShape((int, int) dims) => new TensorShape(dims.Item1, dims.Item2); | |||||
| public static explicit operator (int, int, int)(TensorShape shape) => shape.dims.Length == 3 ? (shape.dims[0], shape.dims[1], shape.dims[2]) : (0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3); | |||||
| public static explicit operator (int, int, int, int)(TensorShape shape) => shape.dims.Length == 4 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3]) : (0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4); | |||||
| public static explicit operator (int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 5 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4]) : (0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5); | |||||
| public static explicit operator (int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 6 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5]) : (0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6); | |||||
| public static explicit operator (int, int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 7 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5], shape.dims[6]) : (0, 0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6, dims.Item7); | |||||
| public static explicit operator (int, int, int, int, int, int, int, int)(TensorShape shape) => shape.dims.Length == 8 ? (shape.dims[0], shape.dims[1], shape.dims[2], shape.dims[3], shape.dims[4], shape.dims[5], shape.dims[6], shape.dims[7]) : (0, 0, 0, 0, 0, 0, 0, 0); | |||||
| public static implicit operator TensorShape((int, int, int, int, int, int, int, int) dims) => new TensorShape(dims.Item1, dims.Item2, dims.Item3, dims.Item4, dims.Item5, dims.Item6, dims.Item7, dims.Item8); | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,24 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow.UnitTest.TF_API | |||||
| { | |||||
| [TestClass] | |||||
| public class LinalgTest | |||||
| { | |||||
| [TestMethod] | |||||
| public void EyeTest() | |||||
| { | |||||
| var tensor = tf.linalg.eye(3); | |||||
| Assert.AreEqual((3, 3), tensor.TensorShape); | |||||
| Assert.AreEqual(0.0f, (float)tensor[2, 0]); | |||||
| Assert.AreEqual(0.0f, (float)tensor[2, 1]); | |||||
| Assert.AreEqual(1.0f, (float)tensor[2, 2]); | |||||
| } | |||||
| } | |||||
| } | |||||