com.github.steveash.jg2p.align.PathXTable.java Source code

Java tutorial

Introduction

Here is the source code for com.github.steveash.jg2p.align.PathXTable.java

Source

/*
 * 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<MinHeap<Entry>> table;
    private final AtomicInteger ids = new AtomicInteger(0);

    public static class Entry implements Comparable<Entry> {

        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<Entry> 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<Entry> newEntries = Iterables.transform(table.get(oldX), new Function<Entry, Entry>() {
            @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<Entry> 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<Entry>(pathSize));
        }
    }
}