docs: public void consistencyCheck() {
          for (int iRow = 0; iRow < 9; iRow++) {
              for (int iCol = 0; iCol < 9; iCol++) {
                  Cell cell = cells[iRow][iCol];
                  Integer value = cell.getValue();
                  if (value != null) {
                      if (! cell.getFree().isEmpty()) {
                          throw new IllegalStateException("free not empty");
                      }
                      // any containing group
                      for (Cell other: cell.getExCells()) {
                          // must not occur in any of the other cells
                          if (value.equals(other.getValue())) {
                              throw new IllegalStateException("duplicate");
                          }
                          // must not occur in the permissibles of any of the other cells
                          if (other.getFree().contains(value)) {
                              throw new IllegalStateException("not eliminated");
                          }
                      }
                  }
              }
          }
          
          for (int i = 0; i < rows.length; i++) {
              Set<Integer> aSet = new HashSet<Integer>();
              for (int j = 0; j < rows[i].getCells().size(); j++) {
                  Cell cell = rows[i].getCells().get(j);
                  Integer value = cell.getValue();
                  if (value != null) {
                      aSet.add(value);
                  } else {
                      aSet.addAll(cell.getFree());
                  }
              }
              if (! aSet.equals(CellGroup.ALL_NINE)) {
                  throw new IllegalStateException("deficit in row");
              }
          }
          
          for (int i = 0; i < cols.length; i++) {
              Set<Integer> aSet = new HashSet<Integer>();
              for (int j = 0; j < cols[i].getCells().size(); j++) {
                  Cell cell = cols[i].getCells().get(j);
                  Integer value = cell.getValue();
                  if (value != null) {
                      aSet.add(value);
                  } else {
                      aSet.addAll(cell.getFree());
                  }
              }
              if (! aSet.equals(CellGroup.ALL_NINE)) {
                  throw new IllegalStateException("deficit in column");
              }
          }
  
          for (int ir = 0; ir < sqrs.length; ir++) {
              for (int ic = 0; ic < sqrs[ir] .length; ic++) {
                  Set<Integer> aSet = new HashSet<Integer>();
                  for (int j = 0; j < sqrs[ir][ic].getCells().size(); j++) {
                      Cell cell = sqrs[ir][ic].getCells().get(j);
                      Integer value = cell.getValue();
                      if (value != null) {
                          aSet.add(value);
                      } else {
                          aSet.addAll(cell.getFree());
                      }
                  }
                  if (! aSet.equals(CellGroup.ALL_NINE)) {
                      throw new IllegalStateException("deficit in square");
                  }
              }
          }
          System.out.println("+++ check OK +++");
      }