ruvnet/ruflo · error

Conformal factor is only defined for Poincare ball model

Error message

Conformal factor is only defined for Poincare ball model

What it means

HyperbolicSpace.conformalFactor() (hyperbolic.ts:1124) computes lambda_p = 2 / (1 - |c|*||p||^2), the conformal scaling factor that exists only for the conformal (angle-preserving) Poincare ball model. Lorentz, Klein, and half-space models are not conformal in this parametrization, so calling the method on any of them throws immediately.

Source

Thrown at v3/@claude-flow/plugins/src/integrations/ruvector/hyperbolic.ts:1124

   * @returns Point on geodesic
   */
  geodesic(a: number[], b: number[], t: number): number[] {
    const tangent = this.logMap(a, b);
    const scaledTangent = scale(tangent, t);
    return this.expMap(a, scaledTangent);
  }

  /**
   * Computes the conformal factor (lambda) at a point in Poincare ball.
   *
   * lambda_p = 2 / (1 - |c| * ||p||^2)
   *
   * @param point - Point in Poincare ball
   * @returns Conformal factor
   */
  conformalFactor(point: number[]): number {
    if (this.model !== 'poincare') {
      throw new Error('Conformal factor is only defined for Poincare ball model');
    }
    const c = Math.abs(this._curvature);
    const pSq = normSquared(point);
    return 2 / Math.max(1 - c * pSq, this.eps);
  }
}

// ============================================================================
// SQL Generation for RuVector PostgreSQL Functions
// ============================================================================

/**
 * SQL function call builder for RuVector hyperbolic operations.
 */
export class HyperbolicSQL {
  /**
   * Generates SQL for Poincare distance computation.
   *

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Use a Poincare space ('poincare') when you need conformal geometry
  2. Branch on space model before calling: only call conformalFactor when model === 'poincare'
  3. For Lorentz pipelines, replace conformal scaling with the Lorentzian norm-based weighting appropriate to that model

Example fix

// before
const space = new HyperbolicSpace('lorentz', -1);
const lambda = space.conformalFactor(p); // throws

// after
const space = new HyperbolicSpace('lorentz', -1);
const lambda = space.model === 'poincare' ? space.conformalFactor(p) : 1; // identity scaling for non-conformal models
Defensive patterns

Strategy: validation

Validate before calling

const lambda = space.model === 'poincare' ? space.conformalFactor(p) : 1; // identity for non-conformal models

Type guard

function isPoincareSpace(space: HyperbolicSpace): boolean {
  return space.model === 'poincare';
}

Try / catch

try {
  lambda = space.conformalFactor(p);
} catch (err) {
  if (err instanceof Error && err.message.includes('Conformal factor')) {
    lambda = 1; // not defined for this model; skip conformal scaling
  } else throw err;
}

Prevention

When it happens

Trigger: Constructing HyperbolicSpace with 'lorentz' or 'klein' and calling conformalFactor(point); generic metric code that enumerates all space methods regardless of model; porting Poincare-specific training tricks (conformal-factor-weighted gradients) to another model.

Common situations: Switching the embedding model for numerical-stability reasons while keeping Poincare-specific optimizer code; shared utility functions invoked across spaces built with different models.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/0ab00b6b15a022d8. Report an issue: GitHub.