blob: 0da15636e28a750cc6ad4e81318696d49d2b8903 [file] [log] [blame]
// RUN: %target-run-simple-swift
import StdlibUnittest
import DifferentiationUnittest
var ArrayAutoDiffTests = TestSuite("ArrayAutoDiff")
typealias FloatArrayGrad = Array<Float>.TangentVector
ArrayAutoDiffTests.test("ArrayIdentity") {
func arrayIdentity(_ x: [Float]) -> [Float] {
return x
}
let backprop = pullback(at: [5, 6, 7, 8], in: arrayIdentity)
expectEqual(
FloatArrayGrad([1, 2, 3, 4]),
backprop(FloatArrayGrad([1, 2, 3, 4])))
}
ArrayAutoDiffTests.test("ArraySubscript") {
func sumFirstThree(_ array: [Float]) -> Float {
return array[0] + array[1] + array[2]
}
expectEqual(
FloatArrayGrad([1, 1, 1, 0, 0, 0]),
gradient(at: [2, 3, 4, 5, 6, 7], in: sumFirstThree))
}
ArrayAutoDiffTests.testWithLeakChecking("ArrayLiteral") {
func twoElementLiteral(_ x: Tracked<Float>, _ y: Tracked<Float>) -> [Tracked<Float>] {
return [x, y]
}
let (gradX, gradY) = pullback(at: Tracked<Float>(1), Tracked<Float>(1), in: twoElementLiteral)(
Array<Tracked<Float>>.DifferentiableView([Tracked<Float>(1), Tracked<Float>(2)]))
expectEqual(Tracked<Float>(1), gradX)
expectEqual(Tracked<Float>(2), gradY)
}
ArrayAutoDiffTests.test("ArrayLiteralIndirect") {
func twoElementLiteralIndirect<T: Differentiable & AdditiveArithmetic>(_ x: T, _ y: T) -> [T] {
return [x, y]
}
func twoElementLiteralIndirectWrapper(_ x: Float, _ y: Float) -> [Float] {
return twoElementLiteralIndirect(x, y)
}
let (gradX, gradY) = pullback(at: Float(1), Float(1), in: twoElementLiteralIndirectWrapper)(
Array<Float>.DifferentiableView([Float(1), Float(2)]))
expectEqual(Float(1), gradX)
expectEqual(Float(2), gradY)
}
ArrayAutoDiffTests.test("ArrayConcat") {
struct TwoArrays : Differentiable {
var a: [Float]
var b: [Float]
}
func sumFirstThreeConcatted(_ arrs: TwoArrays) -> Float {
let c = arrs.a + arrs.b
return c[0] + c[1] + c[2]
}
expectEqual(
TwoArrays.TangentVector(
a: FloatArrayGrad([1, 1]),
b: FloatArrayGrad([1, 0])),
gradient(
at: TwoArrays(a: [0, 0], b: [0, 0]),
in: sumFirstThreeConcatted))
expectEqual(
TwoArrays.TangentVector(
a: FloatArrayGrad([1, 1, 1, 0]),
b: FloatArrayGrad([0, 0])),
gradient(
at: TwoArrays(a: [0, 0, 0, 0], b: [0, 0]),
in: sumFirstThreeConcatted))
expectEqual(
TwoArrays.TangentVector(
a: FloatArrayGrad([]),
b: FloatArrayGrad([1, 1, 1, 0])),
gradient(
at: TwoArrays(a: [], b: [0, 0, 0, 0]),
in: sumFirstThreeConcatted))
}
ArrayAutoDiffTests.testWithLeakChecking("Array.init(repeating:count:)") {
@differentiable
func repeating(_ x: Tracked<Float>) -> [Tracked<Float>] {
Array(repeating: x, count: 10)
}
expectEqual(Tracked<Float>(10), gradient(at: .zero) { x in
repeating(x).differentiableReduce(0, {$0 + $1}).value
})
expectEqual(Tracked<Float>(20), pullback(at: .zero, in: { x in
repeating(x).differentiableReduce(0, {$0 + $1}).value
})(2))
}
ArrayAutoDiffTests.test("Array.DifferentiableView.init") {
@differentiable
func constructView(_ x: [Float]) -> Array<Float>.DifferentiableView {
return Array<Float>.DifferentiableView(x)
}
let backprop = pullback(at: [5, 6, 7, 8], in: constructView)
expectEqual(
FloatArrayGrad([1, 2, 3, 4]),
backprop(FloatArrayGrad([1, 2, 3, 4])))
}
ArrayAutoDiffTests.test("Array.DifferentiableView.base") {
@differentiable
func accessBase(_ x: Array<Float>.DifferentiableView) -> [Float] {
return x.base
}
let backprop = pullback(
at: Array<Float>.DifferentiableView([5, 6, 7, 8]),
in: accessBase)
expectEqual(
FloatArrayGrad([1, 2, 3, 4]),
backprop(FloatArrayGrad([1, 2, 3, 4])))
}
ArrayAutoDiffTests.test("Array.DifferentiableView : KeyPathIterable") {
struct Container : KeyPathIterable {
let a: Array<Float>.DifferentiableView
}
let container = Container(a: Array<Float>.DifferentiableView([1, 2, 3]))
expectEqual(
[1, 2, 3],
container.recursivelyAllKeyPaths(to: Float.self).map {
container[keyPath: $0]
})
}
runAllTests()