{"record":{"id":"3bab188e78c2aac0","repo":"moeru-ai/airi","slug":"singularmessage","errorCode":null,"errorMessage":"${singularMessage}","messagePattern":"\\$\\{singularMessage\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/motion-driver-magic/src/shared/numeric.ts","lineNumber":43,"sourceCode":"    for (let outputIndex = 0; outputIndex < outputCount; outputIndex++)\n      prediction[outputIndex] += feature[featureIndex] * coefficients[featureIndex][outputIndex]\n  }\n  return prediction\n}\n\n/** Computes the lower-triangular Cholesky factor of a positive-definite matrix. */\nexport function cholesky(matrix: readonly number[][], singularMessage: string): number[][] {\n  const size = matrix.length\n  const lower = Array.from({ length: size }, () => Array.from<number>({ length: size }).fill(0))\n  for (let row = 0; row < size; row++) {\n    for (let column = 0; column <= row; column++) {\n      let value = matrix[row][column]\n      for (let index = 0; index < column; index++)\n        value -= lower[row][index] * lower[column][index]\n\n      if (row === column) {\n        if (value <= 1e-12)\n          throw new Error(singularMessage)\n        lower[row][column] = Math.sqrt(value)\n      }\n      else {\n        lower[row][column] = value / lower[column][column]\n      }\n    }\n  }\n  return lower\n}\n\n/** Solves a positive-definite linear system for one or more target columns. */\nexport function solvePositiveDefinite(\n  matrix: readonly number[][],\n  targets: readonly number[][],\n  singularMessage: string,\n): number[][] {\n  const lower = cholesky(matrix, singularMessage)\n  const size = matrix.length","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/moeru-ai/airi/blob/9c213115f8bd0fff9e6eabab02b077ac32da21be/packages/motion-driver-magic/src/shared/numeric.ts#L25-L61","documentation":"Cholesky decomposition requires a symmetric positive-definite matrix; a diagonal pivot `value <= 1e-12` means the matrix is singular (or numerically degenerate), so factorization cannot proceed. This typically surfaces when a covariance matrix estimated during AR-HMM fitting collapses to rank-deficient — e.g. a state assigned too few frames or constant-valued channels.","triggerScenarios":"Indirectly triggered via AR-HMM fitting (`createArHmmModel`) when a covariance matrix becomes singular: a hidden state receives almost no assigned frames, or some channels are constant/linearly dependent. Called from `states`/`lower` during parameter updates.","commonSituations":"Very short training sequences causing empty state assignments; duplicate or frozen motion channels (all-zero or identical columns); stateCount too high for the data so some states get degenerate covariance; exact-duplicate frames in the sequence.","solutions":["Increase the amount of training data so every state receives enough frames.","Reduce `stateCount` so each cluster has sufficient assigned data.","Remove constant or duplicated channels from the motion sequence before fitting.","Add a small ridge/regularization term to covariance estimates if the API exposes it.","Pre-validate the sequence: drop channels with near-zero variance before fitting."],"exampleFix":"// before\ncreateArHmmModel(rawSequence, { stateCount: 20, order: 3 })\n// after\nconst usable = dropConstantChannels(rawSequence)\ncreateArHmmModel(usable, { stateCount: 4, order: 3 })","handlingStrategy":"try-catch","validationCode":"function hasDegenerateChannels(seq: TrainingSequence): boolean {\n  const dim = seq.frames[0]?.length ?? 0\n  for (let c = 0; c < dim; c++) {\n    const first = seq.frames[0]?.[c]\n    if (seq.frames.every(f => f[c] === first)) return true\n  }\n  return false\n}","typeGuard":null,"tryCatchPattern":"try {\n  const model = createArHmmModel(seq, options)\n} catch (error) {\n  if (error instanceof Error && /singular/i.test(error.message)) {\n    const cleaned = dropConstantChannels(seq)\n    return createArHmmModel(cleaned, { ...options, stateCount: Math.min(options.stateCount, 4) })\n  }\n  throw error\n}","preventionTips":["Drop constant/duplicate channels before fitting.","Keep stateCount modest relative to available data so no state starves.","Ensure enough training frames that every cluster gets assignments.","Prefer ridge/regularized fitting when sequences are short or noisy."],"tags":["numerical","singular-matrix","linear-algebra","ar-hmm"],"backgroundTag":"singular-matrix","analyzedSha":"9c213115f8bd0fff9e6eabab02b077ac32da21be","analyzedAt":"2026-09-02T04:27:24.639Z","contentChangedAt":"2026-09-02T04:27:24.639Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}