Skip to content

Commit 655d2af

Browse files
rimimcompnerd
authored andcommitted
Fix for intermittent failure for multi term expressions. The cause is Dictionary is not Ordered and Terms must be evaluated in insertion order.
1 parent fa976ee commit 655d2af

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

Package.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ let cassowary = Package(
77
products: [
88
.library(name: "cassowary", type: .dynamic, targets: ["Cassowary"]),
99
],
10+
dependencies: [
11+
.package(url: "https://github.com/apple/swift-collections.git",
12+
.upToNextMinor(from: "1.0.0")),
13+
],
1014
targets: [
11-
.target(name: "Cassowary", dependencies: []),
15+
.target(name: "Cassowary", dependencies: [
16+
.product(name: "OrderedCollections", package: "swift-collections")
17+
]),
1218
.testTarget(name: "CassowaryTests", dependencies: ["Cassowary"]),
1319
]
1420
)

Sources/Cassowary/Expression.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright © 2019 Saleem Abdulrasool <[email protected]>.
22
// SPDX-License-Identifier: BSD-3-Clause
33

4+
@_implementationOnly
5+
import OrderedCollections
6+
47
public struct Expression {
58
public let terms: [Term]
69
public let constant: Double
@@ -38,7 +41,7 @@ extension Expression: Equatable {
3841
}
3942

4043
internal func reduce(_ expression: Expression) -> Expression {
41-
var vars: [Variable:Double] = [:]
44+
var vars: OrderedDictionary<Variable, Double> = [:]
4245
for term in expression.terms {
4346
vars[term.variable] = vars[term.variable, default: 0.0] + term.coefficient
4447
}

Sources/Cassowary/Row.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// Copyright © 2019 Saleem Abdulrasool <[email protected]>.
22
// SPDX-License-Identifier: BSD-3-Clause
33

4+
@_implementationOnly
5+
import OrderedCollections
6+
47
internal class Row {
5-
public private(set) var cells: [Symbol:Double] = [:]
8+
// Must be in insertion order
9+
public private(set) var cells: OrderedDictionary<Symbol, Double> = [:]
610
public private(set) var constant: Double
711

812
public init() {

Tests/CassowaryTests/CassowaryTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,25 @@ final class CassowaryTests: XCTestCase {
218218
XCTAssertEqual(x_l.value, 80)
219219
XCTAssertEqual(x_r.value, 100)
220220
}
221+
222+
// Terms must be evaluated in insertion order
223+
func testMultiTermExpressionOrder() throws {
224+
let solver: Solver = Solver()
225+
226+
let c: Variable = Variable("c")
227+
let a: Variable = Variable("a")
228+
let b: Variable = Variable("b")
229+
230+
try solver.add(variable: c, strength: .strong)
231+
try solver.add(constraint: a >= 0, .strong)
232+
try solver.add(constraint: b >= a, .strong)
233+
try solver.add(constraint: b - a == c, .required)
234+
try solver.suggest(value: 100, for: c)
235+
236+
solver.update()
237+
238+
XCTAssertEqual(a.value, 0)
239+
XCTAssertEqual(b.value, 100)
240+
XCTAssertEqual(c.value, 100)
241+
}
221242
}

0 commit comments

Comments
 (0)