docs: public TemporalDependencyMatrix calculateTemporalDistance(GroupElement groupElement) {
          // find the events
          List<Pattern> events = new ArrayList<Pattern>();
          selectAllEventPatterns( events,
                                  groupElement );
  
          final int size = events.size();
          if ( size >= 1 ) {
              // create the matrix
              Interval[][] source = new Interval[size][];
              for ( int row = 0; row < size; row++ ) {
                  source[row] = new Interval[size];
                  for ( int col = 0; col < size; col++ ) {
                      if ( row == col ) {
                          source[row][col] = new Interval( 0,
                                                           0 );
                      } else {
                          source[row][col] = new Interval( Interval.MIN,
                                                           Interval.MAX );
                      }
                  }
              }
  
              Interval[][] result;
              if ( size > 1 ) {
                  List<Declaration> declarations = new ArrayList<Declaration>();
                  int eventIndex = 0;
                  // populate the matrix
                  for ( Pattern event : events ) {
                      // references to other events are always backward references, so we can build the list as we go
                      declarations.add( event.getDeclaration() );
                      Map<Declaration, Interval> temporal = new HashMap<Declaration, Interval>();
                      gatherTemporalRelationships( event.getConstraints(),
                                                   temporal );
                      // intersects default values with the actual constrained intervals
                      for ( Map.Entry<Declaration, Interval> entry : temporal.entrySet() ) {
                          int targetIndex = declarations.indexOf( entry.getKey() );
                          Interval interval = entry.getValue();
                          source[targetIndex][eventIndex].intersect( interval );
                          Interval reverse = new Interval( interval.getUpperBound() == Long.MAX_VALUE ? Long.MIN_VALUE : -interval.getUpperBound(), 
                                                           interval.getLowerBound() == Long.MIN_VALUE ? Long.MAX_VALUE : -interval.getLowerBound() );
                          source[eventIndex][targetIndex].intersect( reverse );
                      }
                      eventIndex++;
                  }
                  result = TimeUtils.calculateTemporalDistance( source );
              } else {
                  result = source;
              }
              return new TemporalDependencyMatrix( result, events );
          }
          return null;
      }