Package net.fortytwo.ripple.libs.stream.ranking

Source Code of net.fortytwo.ripple.libs.stream.ranking.RankingEvaluatorHelper

package net.fortytwo.ripple.libs.stream.ranking;

import net.fortytwo.flow.Sink;
import net.fortytwo.ripple.ListMemoizer;
import net.fortytwo.ripple.RippleException;
import net.fortytwo.ripple.model.Closure;
import net.fortytwo.ripple.model.ModelConnection;
import net.fortytwo.ripple.model.Operator;
import net.fortytwo.ripple.model.RippleList;
import net.fortytwo.ripple.model.RippleValue;
import net.fortytwo.ripple.model.RippleValueComparator;
import net.fortytwo.ripple.model.StackMapping;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.logging.Logger;

/**
* Note: for synchronous evaluation only.
*
* @author Joshua Shinavier (http://fortytwo.net)
*/
public class RankingEvaluatorHelper {
    private static final Logger logger = Logger.getLogger(RankingEvaluatorHelper.class.getName());

    // A prioritized queue of active (still-to-be-reduced) stacks
    private final PriorityQueue<RankingContext> queue;

    // A ranked list of intermediate results
    private final List<RankingContext> resultList;

    // A set of intermediate results.
    private final ListMemoizer<RippleValue, RankingContext> resultMemos;

    public RankingEvaluatorHelper(final RippleList arg,
                                  final ModelConnection mc) {
        queue = new PriorityQueue<RankingContext>(1, comparator);

        resultList = new LinkedList<RankingContext>();
        resultMemos = new ListMemoizer<RippleValue, RankingContext>(
                new RippleValueComparator(mc));

        handleOutput(new RankingContext(arg, mc));
    }

    /**
     * Spends one computational step on improving the ranking.
     *
     * @return whether it is possible to take further steps
     * @throws RippleException if the ranking can't be computed
     */
    public boolean reduceOnce(final ModelConnection mc) throws RippleException {
        //System.out.println("\treduceOnce()");
        if (!queue.isEmpty()) {
            //System.out.println("\t\tqueue NOT empty");
            //inputSink.put(queue.poll());
            reduce(queue.poll().getStack(), mc);

            return !queue.isEmpty();
        } else {
            //System.out.println("\t\tqueue is empty");
            return false;
        }
    }

    /**
     * @return an ordered list of ranking results
     */
    public List<RankingContext> getResults() {
        Collections.sort(resultList, comparator);
        //for (RankingContext c : resultList) {
        //    System.out.println("\tresult: " + c);
        //}
        return resultList;
    }

    private void handleOutput(final RankingContext c) {
        //System.out.println("adding intermediate: " + c.getStack());
        if (c.getStack().isNil() || null == c.getStack().getFirst().getMapping()) {
            RankingContext other = resultMemos.get(c.getStack());

            if (null == other) {
                resultMemos.put(c.getStack(), c);
                resultList.add(c);
            } else {
                other.setPriority(other.getPriority() + c.getPriority());
            }
        } else {
            queue.add(c);
        }
    }

    private final Comparator<RankingContext> comparator = new Comparator<RankingContext>() {
        public int compare(final RankingContext first,
                           final RankingContext second) {
            // This orders items from highest to lowest priority.
            return ((Double) second.getPriority()).compareTo(first.getPriority());
        }
    };

    private final Sink<RippleList> outputSink = new Sink<RippleList>() {
        public void put(final RippleList c) throws RippleException {
            //System.out.println("got this output: " + c.getStack());
            // TODO
            /*
            if (c instanceof RankingContext) {
                handleOutput((RankingContext) c);
            } */
        }
    };

    private void reduce(final RippleList arg,
                        final ModelConnection mc) throws RippleException {
        RippleList stack = arg;
        RippleList ops = mc.list();

        while (true) {
            RippleValue first = stack.getFirst();

            if (stack.isNil() || null == first.getMapping()) {
                if (ops.isNil()) {
                    outputSink.put(stack);
                    return;
                } else {
                    Closure c = new Closure(ops.getFirst().getMapping(), first);
                    stack = stack.getRest().push(new Operator(c));
                    ops = ops.getRest();
                }
            } else {
                StackMapping f = first.getMapping();

                if (0 == f.arity()) {
                    try {
                        if (ops.isNil()) {
                            f.apply(stack.getRest(), outputSink, mc);
                        } else {
                            f.apply(stack.getRest(), new SpecialSink(ops, mc), mc);
                        }
                    } catch (Throwable t) {
                        // To keep things simple, just eat any errors.
                        logger.severe("error in expression reduction: " + t.getMessage());
                    }
                    return;
                } else {
                    ops = ops.push(first);
                    stack = stack.getRest();
                }
            }
        }
    }

    private class SpecialSink implements Sink<RippleList> {
        private final RippleList ops;
        private final ModelConnection mc;

        public SpecialSink(final RippleList ops,
                           final ModelConnection mc) {
            this.ops = ops;
            this.mc = mc;
        }

        public void put(final RippleList arg) throws RippleException {
            RippleList stack = arg;

            RippleList cur = ops;
            while (!cur.isNil()) {
                stack = stack.push(cur.getFirst());
                cur = cur.getRest();
            }

            reduce(stack, mc);
        }
    }
}
TOP

Related Classes of net.fortytwo.ripple.libs.stream.ranking.RankingEvaluatorHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.