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

com.github.steveash.jg2p.align.PathXTable Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Steve Ash
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.steveash.jg2p.align;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import com.github.steveash.jg2p.util.MinHeap;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A memoisation table for calculating the best sequences for a given X.  For the X to Y case see PathXYTable
 *
 * @author Steve Ash
 */
public class PathXTable {

  private final List> table;
  private final AtomicInteger ids = new AtomicInteger(0);

  public static class Entry implements Comparable {

    public static Entry sample(double score, int xBackRef) {
      return new Entry(-1, score, xBackRef, -1);
    }

    public final int id;
    public double score;
    public int xBackRef;
    public int pathBackRef;

    private Entry(int id, double score, int xBackRef, int pathBackRef) {
      this.id = id;
      this.score = score;
      this.xBackRef = xBackRef;
      this.pathBackRef = pathBackRef;
    }

    @Override
    public int compareTo(Entry that) {
      return ComparisonChain.start()
          .compare(this.score, that.score)
          .compare(this.xBackRef, that.xBackRef)
          .compare(this.pathBackRef, that.pathBackRef)
          .result();
    }

    @Override
    public String toString() {
      return "Entry{" +
             "id=" + id +
             ", score=" + score +
             ", xBackRef=" + xBackRef +
             ", pathBackRef=" + pathBackRef +
             '}';
    }
  }

  public PathXTable(int xSize, int maxBestPath) {
    this.table = Lists.newArrayListWithCapacity(xSize);
    init(xSize, maxBestPath);
  }

  public Entry make(double score, int xBackRef, int pathBackRef) {
    return new Entry(ids.getAndIncrement(), score, xBackRef, pathBackRef);
  }

  public void offer(int x, Entry candidate) {
    MinHeap paths = table.get(x);
    if (!paths.isFull()) {
      paths.add(candidate);
      return;
    }
    Entry minEntry = paths.peek();
    if (minEntry.compareTo(candidate) < 0) {
      paths.remove();
      paths.add(candidate);
    }
  }

  /**
   * Extend the paths in the particular x,y location by constructing new ones based on the sample with the addative
   * score and back refs
   *
   * @param sample @return
   */
  public void extendPath(int newX, int oldX, final Entry sample) {
    Iterable newEntries = Iterables.transform(table.get(oldX), new Function() {
      @Override
      public Entry apply(Entry input) {
        return make(input.score + sample.score, sample.xBackRef, input.id);
      }
    });

    for (Entry newEntry : newEntries) {
      this.offer(newX, newEntry);
    }
  }

  public Iterable get(int x) {
    return table.get(x);
  }

  public Entry get(int x, int id) {
    Preconditions.checkArgument(id >= 0);
    for (Entry candidate : get(x)) {
      if (candidate.id == id) {
        return candidate;
      }
    }
    throw new IllegalStateException("Shouldn't be possible but somehow couldnt find " + id);
  }

  private void init(int xSize, int pathSize) {
    for (int i = 0; i < xSize; i++) {
      table.add(i, new MinHeap(pathSize));
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy