Skip to content

Commit

Permalink
Fix for intermittent failure for multi term expressions. The cause is…
Browse files Browse the repository at this point in the history
… Dictionary is not Ordered and Terms must be evaluated in insertion order.
  • Loading branch information
rimim authored and compnerd committed Aug 26, 2023
1 parent fa976ee commit 655d2af
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ let cassowary = Package(
products: [
.library(name: "cassowary", type: .dynamic, targets: ["Cassowary"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections.git",
.upToNextMinor(from: "1.0.0")),
],
targets: [
.target(name: "Cassowary", dependencies: []),
.target(name: "Cassowary", dependencies: [
.product(name: "OrderedCollections", package: "swift-collections")
]),
.testTarget(name: "CassowaryTests", dependencies: ["Cassowary"]),
]
)
5 changes: 4 additions & 1 deletion Sources/Cassowary/Expression.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright © 2019 Saleem Abdulrasool <compnerd@compnerd.org>.
// SPDX-License-Identifier: BSD-3-Clause

@_implementationOnly
import OrderedCollections

public struct Expression {
public let terms: [Term]
public let constant: Double
Expand Down Expand Up @@ -38,7 +41,7 @@ extension Expression: Equatable {
}

internal func reduce(_ expression: Expression) -> Expression {
var vars: [Variable:Double] = [:]
var vars: OrderedDictionary<Variable, Double> = [:]
for term in expression.terms {
vars[term.variable] = vars[term.variable, default: 0.0] + term.coefficient
}
Expand Down
6 changes: 5 additions & 1 deletion Sources/Cassowary/Row.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// Copyright © 2019 Saleem Abdulrasool <compnerd@compnerd.org>.
// SPDX-License-Identifier: BSD-3-Clause

@_implementationOnly
import OrderedCollections

internal class Row {
public private(set) var cells: [Symbol:Double] = [:]
// Must be in insertion order
public private(set) var cells: OrderedDictionary<Symbol, Double> = [:]
public private(set) var constant: Double

public init() {
Expand Down
21 changes: 21 additions & 0 deletions Tests/CassowaryTests/CassowaryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,25 @@ final class CassowaryTests: XCTestCase {
XCTAssertEqual(x_l.value, 80)
XCTAssertEqual(x_r.value, 100)
}

// Terms must be evaluated in insertion order
func testMultiTermExpressionOrder() throws {
let solver: Solver = Solver()

let c: Variable = Variable("c")
let a: Variable = Variable("a")
let b: Variable = Variable("b")

try solver.add(variable: c, strength: .strong)
try solver.add(constraint: a >= 0, .strong)
try solver.add(constraint: b >= a, .strong)
try solver.add(constraint: b - a == c, .required)
try solver.suggest(value: 100, for: c)

solver.update()

XCTAssertEqual(a.value, 0)
XCTAssertEqual(b.value, 100)
XCTAssertEqual(c.value, 100)
}
}

0 comments on commit 655d2af

Please sign in to comment.