Skip to content

Commit

Permalink
Graph clean-up
Browse files Browse the repository at this point in the history
- Renamed ObjectGraph to GraphProtocol
- Added small Graph structure
- Changed topological sort to use all nodes and edges of a graph
- Removed Mutable Graph
- Removed neighbourhood selector
  • Loading branch information
Stiivi committed Nov 12, 2024
1 parent 52704f0 commit aaf2f01
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 289 deletions.
12 changes: 8 additions & 4 deletions Sources/PoieticCore/Constraints/Constraint+Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
//

public final class UniqueNeighbourRequirement: ConstraintRequirement {
public let selector: NeighborhoodSelector
public let predicate: Predicate
public let direction: EdgeDirection
public let isRequired: Bool

/// Creates a constraint for unique neighbour.
Expand All @@ -21,8 +22,9 @@ public final class UniqueNeighbourRequirement: ConstraintRequirement {
/// matching node
/// - required: Wether the unique neighbour is required.
///
public init(_ selector: NeighborhoodSelector, required: Bool=false) {
self.selector = selector
public init(_ predicate: Predicate, direction: EdgeDirection = .outgoing, required: Bool=false) {
self.predicate = predicate
self.direction = direction
self.isRequired = required
}

Expand All @@ -32,7 +34,9 @@ public final class UniqueNeighbourRequirement: ConstraintRequirement {
guard $0.structure.type == .node else {
return false
}
let hood = frame.hood($0.id, selector: self.selector)
let hood = frame.hood($0.id, direction: direction) { edge in
predicate.match(frame: frame, object: edge.snapshot)
}
let count = hood.edges.count

return count > 1 || (count == 0 && isRequired)
Expand Down
6 changes: 2 additions & 4 deletions Sources/PoieticCore/Constraints/Constraint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,8 @@ public struct ConstraintViolation: Error, CustomDebugStringConvertible {
/// name: "one_parameter_for_graphical_function",
/// match: IsTypePredicate(ObjectType.GraphicalFunction),
/// requirement: UniqueNeighbourRequirement(
/// NeighborhoodSelector(
/// predicate: IsTypePredicate(ObjectType.Parameter),
/// direction: .incoming
/// ),
/// IsTypePredicate(ObjectType.Parameter),
/// direction: .incoming,
/// required: false
/// )
/// )
Expand Down
18 changes: 1 addition & 17 deletions Sources/PoieticCore/Design/Frame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// Fame Base is a protocol for all version frame types: ``TransientFrame`` and
/// ``StableFrame``
///
public protocol Frame: ObjectGraph where Node == Snapshot, Edge == EdgeSnapshot {
public protocol Frame: GraphProtocol where Node == Snapshot, Edge == EdgeSnapshot {
associatedtype Snapshot: ObjectSnapshot
/// Design to which the frame belongs.
var design: Design { get }
Expand Down Expand Up @@ -303,22 +303,6 @@ extension Frame {
public func top() -> [Snapshot] {
self.filter { $0.parent == nil }
}

public func hood(_ nodeID: ObjectID, selector: NeighborhoodSelector) -> Neighborhood<Self> {
let edges: [Edge]
switch selector.direction {
case .incoming: edges = incoming(nodeID)
case .outgoing: edges = outgoing(nodeID)
}
let filtered: [Edge] = edges.filter {
selector.predicate.match(frame: self, object: $0.snapshot)
}

return Neighborhood(graph: self,
nodeID: nodeID,
direction: selector.direction,
edges: filtered)
}
}


Expand Down
27 changes: 27 additions & 0 deletions Sources/PoieticCore/Design/ObjectSnapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,30 @@ extension ObjectSnapshot {
return Array(refs)
}
}

// MARK: - Graph Protocol

// TODO: Find a more descriptive name.
/// Wrapper of an object snapshot presented as an edge.
///
public struct EdgeSnapshot: EdgeProtocol {
public typealias NodeID = ObjectID
public let snapshot: any ObjectSnapshot
public let origin: ObjectID
public let target: ObjectID

public init?(_ snapshot: any ObjectSnapshot) {
guard case let .edge(origin, target) = snapshot.structure else {
return nil
}

self.snapshot = snapshot
self.origin = origin
self.target = target
}

public var id: ObjectID { snapshot.id }
public var type: ObjectType { snapshot.type }
public var name: String? { snapshot.name }
}

3 changes: 1 addition & 2 deletions Sources/PoieticCore/Design/StableFrame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ public final class StableFrame: Frame {

/// Get an immutable graph view of the frame.
///
public var graph: any ObjectGraph {
public var graph: any GraphProtocol {
return self
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,13 @@
// Created by Stefan Urbanek on 21/08/2023.
//

/// Protocol
public protocol MutableGraph: ObjectGraph {
// Object creation
@discardableResult
func createNode(_ type: ObjectType, name: String?, attributes: [String:Variant]) -> MutableObject

@discardableResult
func createEdge(_ type: ObjectType, origin: ObjectID, target: ObjectID,
attributes: [String:Variant]) -> MutableObject

/// Remove all nodes and edges from the graph.
func removeAll()

/// Remove a node from the graph and return a list of edges that were
/// removed together with the node.
extension TransientFrame /* MutableGraph (no longer formally present) */ {
/// Convenience method to create an edge.
///
func remove(node nodeID: ObjectID)

/// Remove an edge from the graph.
/// If the object name is provided, then attribute `name` of the
/// object is set. Replaces `name` attribute in the `attributes` dictionary.
///
func remove(edge edgeID: ObjectID)
}

extension MutableGraph {
public func removeAll() {
for edge in edgeIDs {
remove(edge: edge)
}
for node in nodeIDs {
remove(node: node)
}
}
}


/// Graph contained within a mutable frame where the references to the nodes and
/// edges are not directly bound and are resolved at the time of querying.
extension TransientFrame: MutableGraph {
// Object creation
/// - SeeAlso: ``TransientFrame/create(_:id:snapshotID:structure:parent:children:attributes:components:)``
@discardableResult
public func createEdge(_ type: ObjectType,
origin: ObjectID,
Expand All @@ -58,22 +26,28 @@ extension TransientFrame: MutableGraph {
return snapshot
}

/// Convenience method to create an edge.
///
/// If the object name is provided, then attribute `name` of the
/// object is set. Replaces `name` attribute in the `attributes` dictionary.
///
/// - SeeAlso: ``TransientFrame/create(_:id:snapshotID:structure:parent:children:attributes:components:)``
@discardableResult
public func createEdge(_ type: ObjectType,
origin: any ObjectSnapshot,
target: any ObjectSnapshot,
attributes: [String:Variant] = [:]) -> MutableObject {
// FIXME: [WIP] Still needed?
return createEdge(type, origin: origin.id, target: target.id, attributes: attributes)
}


/// Creates a new node.
/// Convenience method to a new node.
///
/// - Parameters:
/// - type: Object type of the newly created node.
/// - name: Optional object name. See note below.
/// - attributes: Dictionary of attributes to set.
/// - components: List of components assigned with the node.
///
/// If the object name is provided, then attribute `name` of the
/// object is set. Replaces `name` attribute in the `attributes` dictionary.
Expand Down
17 changes: 5 additions & 12 deletions Sources/PoieticCore/Documentation.docc/Graphs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,12 @@ Graphs are views that comprise of nodes and edges – connections between nodes.

### Graph, Nodes and Edges

- ``ObjectGraph``
- ``MutableGraph``

- ``Node``
- ``Edge``
- ``EdgeType``
- ``EdgeDirection``

- ``topologicalSort(_:edges:)``

- ``GraphCycleError``
- ``GraphProtocol``
- ``Graph``
- ``EdgeSnapshot``
- ``EdgeProtocol``

### Neighbourhoods

- ``Neighborhood``
- ``NeighborhoodSelector``
- ``EdgeDirection``
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ examples see ``Constraint``.
- ``UniqueNeighbourRequirement``
- ``UniqueProperty``
- ``ConstraintRequirement``
- ``EdgeEndpointRequirement``

### Common Components and Types

Expand Down
Loading

0 comments on commit aaf2f01

Please sign in to comment.