@Override
  public boolean collapse(AugmentedState state) {
    if (state.getInfo() != StateInfo.Forecast) {
      return false;
    }
    if (!isPositive(Q.diagonal().drop(0, 1))) {
      return false;
    }

    // update the state vector
    Matrix A = new Matrix(state.B());
    int d = A.getColumnsCount();
    Matrix S = new Matrix(a());
    LowerTriangularMatrix.rsolve(S, A.subMatrix().transpose());
    DataBlock D = b().deepClone();
    LowerTriangularMatrix.lsolve(S, D);
    for (int i = 0; i < d; ++i) {
      DataBlock col = A.column(i);
      state.a().addAY(-Q.get(d, i), col);
      state.P().addXaXt(1, col);
    }
    state.dropAllConstraints();
    return true;
  }
 private double c() {
   return Q.get(nd, nd);
 }
  // time-varying trading days
  // @Test
  public void demoTD() {
    TsData s = Data.X;
    CompositeResults rslts = TramoSeatsProcessingFactory.process(s, TramoSeatsSpecification.RSA5);
    PreprocessingModel regarima = rslts.get("preprocessing", PreprocessingModel.class);
    SeatsResults seats = rslts.get("decomposition", SeatsResults.class);
    assertTrue(seats != null && regarima != null);

    if (regarima.isMultiplicative()) {
      s = s.log();
    }
    int[] calPos =
        regarima.description.getRegressionVariablePositions(ComponentType.CalendarEffect);
    UcarimaModel ucm = seats.getUcarimaModel();
    // compute the full decomposition...
    SsfUcarima stoch = new SsfUcarima(ucm);
    ExtendedSsfData xdata = new ExtendedSsfData(new SsfData(s, null));
    xdata.setForecastsCount(s.getFrequency().intValue());
    Matrix x =
        regarima
            .description
            .buildRegressionVariables()
            .all()
            .matrix(new TsDomain(s.getStart(), xdata.getCount()));
    RegSsf xssf = new RegSsf(stoch, x.subMatrix());

    Filter filter = new Filter();
    filter.setInitializer(new DiffuseSquareRootInitializer());
    filter.setSsf(xssf);
    DiffuseFilteringResults fr = new DiffuseFilteringResults(true);
    fr.getVarianceFilter().setSavingP(true);
    fr.getFilteredData().setSavingA(true);
    filter.process(xdata, fr);
    Smoother smoother = new Smoother();
    smoother.setSsf(xssf);
    smoother.setCalcVar(true);
    SmoothingResults sm = new SmoothingResults();
    smoother.process(xdata, fr, sm);

    Smoother lsmoother = new Smoother();
    lsmoother.setSsf(stoch);
    lsmoother.setCalcVar(true);
    SmoothingResults lsm = new SmoothingResults();
    ExtendedSsfData xldata =
        new ExtendedSsfData(new SsfData(regarima.linearizedSeries(false), null));
    xldata.setForecastsCount(s.getFrequency().intValue());
    lsmoother.process(xldata, lsm);

    int spos = stoch.cmpPos(1);
    DataBlock Z = new DataBlock(xssf.getStateDim());
    double[] v = new double[xdata.getCount()];
    double[] c = new double[xdata.getCount()];
    double[] svar = sm.componentVar(spos);
    double[] slvar = lsm.componentVar(spos);
    int start = regarima.description.getRegressionVariablesStartingPosition();
    for (int i = 0; i < v.length; ++i) {
      Z.set(spos, 1);
      for (int j = 0; j < calPos.length; ++j) {
        Z.set(stoch.getStateDim() + calPos[j], x.get(i, calPos[j]));
      }
      v[i] = sm.zvariance(i, Z);
      Z.set(spos, 0);
      c[i] = sm.zvariance(i, Z);
      System.out.print(svar[i]);
      System.out.print('\t');
      System.out.print(slvar[i]);
      System.out.print('\t');
      System.out.print(c[i]);
      System.out.print('\t');
      System.out.println(v[i]);
    }
    System.out.println(sm.P(50));
    System.out.println(sm.P(svar.length - 1));
    System.out.println(regarima.estimation.getLikelihood().getBVar());
  }