All Downloads are FREE. Search and download functionalities are using the official Maven repository.

epic.parser.projections.ProjectionIndexer.scala Maven / Gradle / Ivy

The newest version!
package epic.parser
package projections

import breeze.util.{Encoder, Index}
import collection.mutable.ArrayBuffer
import scala.reflect.ClassTag

/**
 * For computing projections from a fine grammar to a coarse grammar.
 * 
 * There are two indexes maintained for the fine symbols: a globally unique
 * id, and a local per-symbol id (in the range 0...numRefinements(coarseSym).
 *
 * Yuck.
 * 
 * @author dlwh
 */
@SerialVersionUID(1)
final class ProjectionIndexer[C, F] private (val coarseIndex: Index[C],
                                                 val fineIndex:Index[F],
                                                 indexedProjections: Array[Int]) extends (Int=>Int) with Serializable {

  val coarseEncoder = Encoder.fromIndex(coarseIndex)

  // coarseSymbolIndex -> localizedFineSymbol -> globalizedFineSymbolIndex
  val globalRefinements: Array[Array[Int]] = {
    val result = Encoder.fromIndex(coarseIndex).fillArray(new ArrayBuffer[Int])
    for( (coarse, fine) <- indexedProjections.zipWithIndex if coarse != -1) {
      result(coarse) += fine
    }
    result.map(arr => (arr.toArray))
  }

  // globaleRefined -> localRefined
  val localizationArray = new Array[Int](indexedProjections.length)
  // just coarseSymbolIndex -> (0 until numGlobalRefinements(coarseSymbolIndex))
  val perSymbolRefinements = globalRefinements.map { arr =>
    for( (global,local) <- arr.zipWithIndex) {
      localizationArray(global) = local
    }
    Array.range(0, arr.length)
  }

  def localize(f: Int):Int =  localizationArray(f)
  def globalize(c: Int, f: Int):Int = globalRefinements(c)(f)
  def globalize(c: C, f: Int):F = fineIndex.get(globalRefinements(coarseIndex(c))(f))
  def indexAndLocalize(f: F):(Int, Int) = {
    val glob = fineIndex(f)
    if(glob < 0) (-1, -1)
    else project(glob) -> localize(glob)
  }


  def localize(f: F):(C, Int) = {
    val i = fineIndex(f)
    if(i < 0) throw new RuntimeException(s"Not in fine index: $f")
    coarseIndex.get(indexedProjections(i)) -> localizationArray(i)
  }

  def refinementsOf(c: Int):Array[Int] = globalRefinements(c)
  def localRefinements(c: Int):Array[Int] = perSymbolRefinements(c)

  def numRefinements(c: Int): Int = perSymbolRefinements(c).length

  def refinementsOf(c: C):IndexedSeq[F] = {
    val ci = coarseIndex(c)
    if(ci < 0) throw new RuntimeException("Not a coarse symbol: " + c)
    globalRefinements(ci).map(fineIndex.get _)
  }

  /**
   * Computes the projection of the indexed fine label f to an indexed coarse label.
   */
  def project(f: Int):Int = indexedProjections(f)

  def project(f: F):C = coarseIndex.get(project(fineIndex(f)))

  def coarseSymbol(f: Int) = coarseIndex.get(project(f))

  /**
   * Same as project(f)
   */
  def apply(f: Int) = project(f)

  /**
   *  From a PI[C, F] and a PI[F, F2], makes a PI[C, F2]
   */
  def compose[F2](finerProjections: ProjectionIndexer[F, F2]) = {
    ProjectionIndexer(coarseIndex, finerProjections.fineIndex, {finerProjections.project(_ : F2)} andThen {project(_ : F)})
  }

  override def toString() = {
    coarseIndex.map(x => x -> refinementsOf(x)).mkString("ProjectionIndexer(", ", ", ")")
  }


  def localizeArray[T:ClassTag](array: Array[T]):Array[Array[T]] = {
    require(array.length == fineIndex.size)
    Array.tabulate(coarseIndex.size) { c =>
      val refs = refinementsOf(c)
      Array.tabulate(refs.length)(r => array(r))
    }
  }
}

object ProjectionIndexer {
  def simple[L](index: Index[L]) = ProjectionIndexer(index, index, identity[L] _)

  def apply[C, F](coarseIndex: Index[C], fineIndex: Index[F], proj: F=>C, skipMissingCoarse: Boolean = false) = {
    val indexedProjections = Encoder.fromIndex(fineIndex).fillArray(-1)
    for( (l, idx) <- fineIndex.zipWithIndex) {
      val projectedIdx = coarseIndex(proj(l))
      if(projectedIdx < 0) {
        if(!skipMissingCoarse)
        throw new RuntimeException("error while indexing" + l + " to " + proj(l) + fineIndex(l))
      } else {
        indexedProjections(idx) = projectedIdx
      }
    }
    new ProjectionIndexer(coarseIndex, fineIndex, indexedProjections)
  }

  def fromSplitter[C, F](coarseIndex: Index[C], fineIndex: Index[F], split: C=>Seq[F]) = {
    val indexedProjections = Encoder.fromIndex(fineIndex).fillArray(-1)
    for( (c, cf) <- coarseIndex.zipWithIndex; f <- split(c)) {
      try {
        indexedProjections(fineIndex(f)) = cf
      } catch {
        case e: Throwable => throw e
      }
    }
    new ProjectionIndexer(coarseIndex, fineIndex, indexedProjections)

  }

  def fromSplitter[C, F](coarseIndex: Index[C], split: C=>Seq[F]) = {
    val fineIndex = Index[F]()
    val indexedProjections = new ArrayBuffer[Int]()
    for( (c, cf) <- coarseIndex.zipWithIndex; f <- split(c)) {
      val i = fineIndex.index(f)
      indexedProjections += cf
    }
    new ProjectionIndexer(coarseIndex, fineIndex, indexedProjections.toArray)

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy