Dependencies

On the Home tab, in the Setup group: Select Dependencies to setup dependencies between the tasks of the schedule.

In the Equipment Source Path, topic, we looked at how to build a Source Path. An advanced extension of Source Paths is the use of Dependencies, which is a logical application of "Don't do this until you've done this". A Dependency pairs Predecessors (do this before) and Successors (do this after).

There are different types of Dependencies as listed below:

  • Process Order

  • A Process Order Dependency is used to set dependencies between different processes, for example Bogging waits on Drilling. Any model with more than one Process should normally have a Process Order Dependency. Add multiple entries to set up the hierarchy and use Ranges if it changes in different regions.

  • Offset

  • Offset Dependencies look at each available Leaf and Create Predecessors to that Leaf by offsetting the Index of one or more Positions. That means that if an Offset is set to 0, it means "same", an Offset of 1 means "next position" and an Offset of * means "all positions".

    Through the tunnel generation process an automatic internal offset dependency is created. This rule uses each level positioning at 0, apart from the Sequence (last level) at -1, meaning that for each unique tunnel, the offset dependency will connect each cut in the direction of the mining (centreline direction).

  • Field Offset

  • Field Offset dependencies allow you to define complex patterns in your dependencies by using Field positions rather than Level positions. To offset dependencies by mining stage, you might decide to add a Stage attribute field to your Table Data, for example.

  • Range

  • A Range Dependency is used to set dependencies between ranges of tasks by explicitly defining Predecessor and Successor pairs. Range dependencies are commonly used to create Chain Dependencies which allow a large number of dependencies to be set, based on a specified orientation and/or sequence of scheduled solids.

    Conversely, range dependencies can also be created by using Chain Dependencies. A range dependency can also be modified interactively through Modify Range Dependency By Animation.

  • Geometric

  • A Geometric Dependency is used to set dependencies between solids by defining spatial rules: Commonly to define rules between solids that are not on the exact same level or elevation. Geometric dependencies allow you to select which position in the range to connect From and To. A spatial rule can be applied from a first cut, last cut, or all cuts, to the closest, median, furthest, or all intersections. The tool will create a dependency when the rule spatially intersects the predecessor and the successor.

  • Development Sequence

  • Development Sequence dependencies are generated from all internal dependencies in the Development Network Layer, based on their Cut, and are case-specific.

  • Development Intersection

  • Development Intersection dependencies are generated from the intersections of internal dependencies in the Development Network Layer and are case-specific.

As you can see each Dependency type has a "common" use but they can be flexible depending on your requirements and understanding of how they work. To fully understand Dependencies, additional concepts are detailed in: Dependencies: When and Where?.

Released vs Unreleased

The key terminology to be aware of is Released (no Dependency on this Task) and Unreleased (Waiting on Dependency). This will become useful in the Snapshot Viewer and how it can help diagnose issues with Source Paths and Dependencies.

Pairing (Range Dependencies)

Each dependency entry in a Range dependency can contain more than a single predecessor or successor solid. An important concept is to know how wildcard and spans can be applied in each entry. For example, we might want to include all stopes from a particular area as a predecessor, before mining the first stope in an adjacent level. In this case, we might have:

Predecessor: Stope/RL100/D1/OP/A-F
Successor: Stope/RL200/D1/OP/A

The rule above would be interpreted as all stopes, from A to F, in RL100, orebody D1, cost OP must be completed before mining stope A, in RL200, orebody D1, cost OP.

Key Concept: No Leaf inside the Successor pair can be worked until EVERY Leaf inside in the Predecessor pair is 100% worked.

It is important to note that each range entry by default is set to ALL processes in the predecessor and successor.

A typical use case might involve creating a stope sequence using a range dependency, but the user may want this rule applied solely to production drilling. Alternatively, they might want to exclude drilling entirely from the sequence. Both cases are presented below:

Drilling only entry:

Predecessor: Stope/RL100/D1/OP/A-F Predecessor Process: Prod Drilling
Successor: Stope/RL200/D1/OP/A Successor Process: Prod Drilling

In the example above, stopes A to F in D1, RL100, OP would have to be drilled before drilling can commence on stope A in D1, RL200, OP.

All other Stoping Processes except Drilling:

Predecessor: Stope/RL100/D1/OP/A-F Predecessor Process: Bogging, Paste Filling
Successor: Stope/RL200/D1/OP/A Successor Process: Bogging, Paste Filling

In the example above, stopes A to F in D1, RL100, OP would have to be bogged and filled before bogging or filling can commence on stope A in D1, RL200, OP.

The following expression would create a circular reference.

Predecessor: Stope/RL100/D1/5/A-F
Successor: Stope/RL100/D1/5/B-G INCORRECT

In this example, there is an overlap between the groups which means that Stope/RL100/D1/5/C is waiting on Stope/RL100/D1/5/B (intended) but the opposite is also true (Stope/RL100/D1/5/B is waiting on Stope/RL100/D1/5/C) which will bring everything to a grinding halt (a circular reference).

Arrays (Range Dependencies)

However, in many/most examples you're going to want that explicit Node to Node pairing, so in order to pair only Predecessor Stope A with Successor Stope B etc. You could get this behaviour by writing individual dependencies per line, as in the following example:

Predecessor: Stope/RL100/D1/5/A Successor: Stope/RL100/D1/5/B
Predecessor: Stope/RL100/D1/5/B Successor: Stope/RL100/D1/5/C
Predecessor: Stope/RL100/D1/5/C Successor: Stope/RL100/D1/5/D
Predecessor: Stope/RL100/D1/5/D Successor: Stope/RL100/D1/5/E 
etc

You can usually address this more succinctly by using Arrays, which are also described in the Source Path topic (Path Arrays).

Predecessor: Stope/RL100/D1/5/{A;B;C;D;E;F}
Successor: Stope/RL100/D1/5/{B;C;D;E;F;G}

By writing your Dependency with an array, you are defining your pairs explicitly and therefore Stope A will pair with Stope B etc.

Multi-Dimensional Arrays (Range Dependencies)

It doesn't really matter what number you give each array, as long as each array pair has the same length. Predecessor Array {1:} needs to match Successor Array {1:} in length and so on.

@Position, ..ArraySpan and #Jump (Range Dependencies)

Because of the pairing above, explicitly pairing items in Arrays is an important concept and the following tools will assist in pairing your predecessor and successors.

  • @Position: Uses the Index (rather than the Name) of a Position. @0 indicates the first item (zero indexed) and @-1 indicates the last (@-2 second last etc)
  • ..ArraySpan: Use this option instead of individual semi-colin delimited objects to Span multiple Positions. E.g. */*/*/*/{D..G} is the same as */*/*/*/D;E;F;G
  • #Jump: Use this option in conjunction with an ArraySpan to Jump more than one position at a time. E.g. */*/*/*/{D..G#2} is the same as */*/*/*/D;F

Example: The earlier array

Predecessor: Stope/RL100/D1/5/{A;B;C;D;E;F}

Can now be written as

Predecessor: Stope/RL100/D1/5/{@0..@-1}