Skip to content

Commit e3db926

Browse files
authored
[AutoDiff] Remove '_Differentiable.zeroTangentVectorInitializer'. (#35329)
Remove `_Differentiable.zeroTangentVectorInitializer` to address the feedback on the [proposal thread](https://forums.swift.org/t/differentiable-programming-for-gradient-based-machine-learning/42147). The corresponding change has already been made in the [proposal](https://github.com/rxwei/swift-evolution/blob/autodiff/proposals/0000-differentiable-programming.md). Removed components: - `zeroTangentVectorInitializer` and `zeroTangentVector` in `Differentiable`, `Array`, `Optional`, `Float`, `Double`, `Float80`, and SIMD types. - `zeroTangentVectorInitializer` synthesis logic in `Differentiable` derived conformances.
1 parent 2243ffe commit e3db926

19 files changed

+11
-832
lines changed

docs/DifferentiableProgramming.md

Lines changed: 6 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -986,44 +986,6 @@ public protocol Differentiable {
986986
/// equivalent to exponential map, which moves `self` on the geodesic
987987
/// surface along the given tangent vector.
988988
mutating func move(along direction: TangentVector)
989-
990-
/// A closure that produces a zero tangent vector and does not capture `self`.
991-
///
992-
/// In some cases, the zero tangent vector of `self` is equal to
993-
/// `TangentVector.zero`. In other cases, the zero tangent vector depends on
994-
/// information in `self`, such as shape for an n-dimensional array type.
995-
/// For differentiable programming, it is more memory-efficient to define a
996-
/// custom `zeroTangentVectorInitializer` property which returns a closure
997-
/// that captures and uses only the necessary information to create a zero
998-
/// tangent vector. For example:
999-
///
1000-
/// ```swift
1001-
/// struct Vector {
1002-
/// var scalars: [Float]
1003-
/// var count: Int { scalars.count }
1004-
/// init(repeating repeatedElement: Float, count: Int) { ... }
1005-
/// }
1006-
///
1007-
/// extension Vector: Differentiable {
1008-
/// typealias TangentVector = Vector
1009-
///
1010-
/// @noDerivative
1011-
/// var zeroTangentVectorInitializer: () -> TangentVector {
1012-
/// let count = self.count
1013-
/// return { TangentVector(repeating: 0, count: count) }
1014-
/// }
1015-
/// }
1016-
/// ```
1017-
///
1018-
@noDerivative
1019-
var zeroTangentVectorInitializer: () -> TangentVector { get }
1020-
}
1021-
1022-
extension Differentiable {
1023-
/// A tangent vector such that `move(along: zeroTangentVector)` will not modify
1024-
/// `self`.
1025-
@noDerivative
1026-
var zeroTangentVector: TangentVector { zeroTangentVectorInitializer() }
1027989
}
1028990
```
1029991

@@ -1092,13 +1054,6 @@ public extension Differentiable where Self == TangentVector {
10921054
}
10931055
```
10941056

1095-
The `zeroTangentVector` property returns a tangent vector such that calling
1096-
`move(along:)` on the vector will not modify `self`. A zero tangent vector is
1097-
often used in the initialization of mathematical optimization, where tangent
1098-
vectors are initially zero and modified iteratively. This property may be
1099-
different from `TangentVector.zero` because some tangent vectors depend on
1100-
instance properties of `self`, e.g. the `count` property in `Array`.
1101-
11021057
#### `Differentiable` conformances
11031058

11041059
Conforming a type to `Differentiable` tells Swift that changes in values of this
@@ -1146,13 +1101,6 @@ extension Array: Differentiable where Element: Differentiable {
11461101
self[i].move(along: Element.TangentVector(direction.elements[i]))
11471102
}
11481103
}
1149-
1150-
@noDerivative
1151-
public var zeroTangentVectorInitializer: () -> TangentVector {
1152-
{ [zeroInits = map(\.zeroTangentVectorInitializer)] in
1153-
TangentVector(zeroInits.map { $0() })
1154-
}
1155-
}
11561104
}
11571105

11581106
// struct Dictionary<Key: Hashable, Value>
@@ -1173,14 +1121,6 @@ extension Dictionary: Differentiable where Value: Differentiable {
11731121
self[i].move(along: Value.TangentVector(direction.elements[i]))
11741122
}
11751123
}
1176-
1177-
@noDerivative
1178-
public var zeroTangentVectorInitializer: () -> TangentVector {
1179-
{ [keys = self.keys] in
1180-
let pairs = zip(keys, sequence(first: .zero, next: {$0}))
1181-
return TangentVector(Dictionary(uniqueKeysWithValues: pairs))
1182-
}
1183-
}
11841124
}
11851125

11861126
// enum Optional<Wrapped>
@@ -1199,18 +1139,6 @@ extension Optional: Differentiable where Wrapped: Differentiable {
11991139
self?.move(along: value)
12001140
}
12011141
}
1202-
1203-
@noDerivative
1204-
public var zeroTangentVectorInitializer: () -> TangentVector {
1205-
switch self {
1206-
case nil:
1207-
return { TangentVector(nil) }
1208-
case let x?:
1209-
return { [zeroTanInit = x.zeroTangentVectorInitializer] in
1210-
TangentVector(zeroTanInit())
1211-
}
1212-
}
1213-
}
12141142
}
12151143
```
12161144

@@ -1261,13 +1189,12 @@ product manifold of the manifolds each differentiable variable's type
12611189
represents. Differentiable variables' types are required to conform to
12621190
`Differentiable` because the synthesized implementation needs to access each
12631191
differentiable variable's type's `TangentVector` associated type and invoke each
1264-
differentiable variable's implementation of `move(along:)` and
1265-
`zeroTangentVectorInitializer`. Because the synthesized implementation needs to
1266-
invoke `move(along:)` on each differentiable variable, the differentiable
1267-
variables must have a `move(along:)` which satisfies the protocol requirement
1268-
and can be invoked on the property. That is, the property must be either a
1269-
variable (`var`) or a constant (`let`) with a non-`mutating` implementation of
1270-
the `move(along:)` protocol requirement.
1192+
differentiable variable's implementation of `move(along:)`. Because the
1193+
synthesized implementation needs to invoke `move(along:)` on each differentiable
1194+
variable, the differentiable variables must have a `move(along:)` which satisfies the
1195+
protocol requirement and can be invoked on the property. That is, the property
1196+
must be either a variable (`var`) or a constant (`let`) with a non-`mutating`
1197+
implementation of the `move(along:)` protocol requirement.
12711198

12721199
The synthesized `TangentVector` has the same effective access level as the
12731200
original type declaration. Properties in the synthesized `TangentVector` have
@@ -1282,12 +1209,6 @@ example, synthesized `TangentVector`s always adopt the `AdditiveArithmetic` and
12821209
The synthesized `move(along:)` method calls `move(along:)` for each pair of a
12831210
differentiable variable and its corresponding property in `TangentVector`.
12841211

1285-
The synthesized `zeroTangentVectorInitializer` property returns a closure that
1286-
captures and calls each stored property's `zeroTangentVectorInitializer`
1287-
closure. When memberwise derivation is not possible (e.g. for custom
1288-
user-defined `TangentVector` types), `zeroTangentVectorInitializer` is
1289-
synthesized as a `{ TangentVector.zero }` closure.
1290-
12911212
```swift
12921213
struct Foo<T: Differentiable, U: Differentiable>: @memberwise Differentiable {
12931214
// `x` and `y` are the "differentiable variables".
@@ -1306,13 +1227,6 @@ struct Foo<T: Differentiable, U: Differentiable>: @memberwise Differentiable {
13061227
// x.move(along: direction.x)
13071228
// y.move(along: direction.y)
13081229
// }
1309-
//
1310-
// var zeroTangentVectorInitializer: () -> TangentVector {
1311-
// { [xTanInit = x.zeroTangentVectorInitializer,
1312-
// yTanInit = y.zeroTangentVectorInitializer] in
1313-
// TangentVector(x: xTanInit(), y: yTanInit())
1314-
// }
1315-
// }
13161230
}
13171231
```
13181232

@@ -1404,14 +1318,6 @@ struct Point<T: Real>: @memberwise Differentiable, @memberwise AdditiveArithmeti
14041318
// The compiler synthesizes:
14051319
//
14061320
// typealias TangentVector = Self
1407-
//
1408-
// @noDerivative
1409-
// var zeroTangentVectorInitializer: () -> TangentVector {
1410-
// { [xTanInit = x.zeroTangentVectorInitializer,
1411-
// yTanInit = y.zeroTangentVectorInitializer] in
1412-
// TangentVector(x: xTanInit(), y: yTanInit())
1413-
// }
1414-
// }
14151321
}
14161322
```
14171323

include/swift/AST/KnownIdentifiers.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ IDENTIFIER(move)
233233
IDENTIFIER(pullback)
234234
IDENTIFIER(TangentVector)
235235
IDENTIFIER(zero)
236-
IDENTIFIER(zeroTangentVectorInitializer)
237236

238237
#undef IDENTIFIER
239238
#undef IDENTIFIER_

0 commit comments

Comments
 (0)