Skip to content
Snippets Groups Projects
Nloc.java 17.2 KiB
Newer Older
package nloc;

import java.util.List;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.concurrent.ThreadLocalRandom;

public class Nloc {
Peter Wagenhuber's avatar
Peter Wagenhuber committed
  public static final int MIN_TIMEDIFF = 0;
  private List<Channel> chanlist;
  private List<Droplet> dropletList;

  public Nloc (List<Channel> chanlist) {
    this.chanlist = chanlist;
    this.dropletList = new ArrayList<Droplet>();
  }

  public List<Droplet> getShortestSequence(String[] modulesToVisit) {
    List<List<SequenceTuple>> possibleSequences;
    List<Droplet> dropletSequence = null;
    try {
      possibleSequences = getPossibleSequences(modulesToVisit);
      // sort the list of possible sequences according to the sequences length
      possibleSequences.sort((a,b) -> a.size() - b.size());

      do {

        pump.removeAllDroplets();
        currentSeq = possibleSequences.remove(0);
        //System.out.println("Working on sequence");
        //for (SequenceTuple stup: currentSeq) {
        //  if (currentSeq.indexOf(stup) == (currentSeq.size() - 1)) {
        //    System.out.print(stup.getDroplet().getName() + ": " + stup.getMinPos() + ":" + stup.getMaxPos() + " : " + stup.getPath().get(1).getName());
        //  } else { 
        //    System.out.print(stup.getDroplet().getName() + ": " + stup.getMinPos() + ":" + stup.getMaxPos() + " : " + stup.getPath().get(1).getName() + " -> ");
        //  }
        //}
        //System.out.println("\n");

        int min = 0, max = 0;
        for (SequenceTuple stl: currentSeq) {
          int tmp = stl.getMinPos();
          if (tmp > max) max = tmp;
          if (tmp < min) min = tmp;
        }
        int span = max - min;
        pump.setSteps(span);

        currentSeq = setTuplePumpoffsetToPumpPosition(currentSeq, min);

        dropletSequence = generateDropletListRecursive(new ArrayList<Droplet>(), currentSeq, currentSeq.get(0).getMinPos());

        currentSeq = resetPayloadDropletPosition(currentSeq);
          !(dropletSequence.size() == currentSeq.size() &&
            this.sequenceFunctional()));

      if (dropletSequence.size() != currentSeq.size()) {
    } catch(NoSuchModuleException nsme) {
      System.out.println(nsme.getMessage());
  public void setDropletList(List<Droplet> dropletList) {
    this.dropletList = dropletList;
  }

  public List<SequenceTuple> resetPayloadDropletPosition(
      List<SequenceTuple> currentSequence) {

    for (SequenceTuple stup: currentSequence) {
      if (stup.getDroplet().getType() == DropletType.PAYLOAD) {
        stup.setMinPos(0);
        stup.setMaxPos(0);
      }
    }
    return currentSequence;
  }

  public List<SequenceTuple> setTuplePumpoffsetToPumpPosition(
      List<SequenceTuple> currentSequence, int minOffset) {

    for (SequenceTuple stup: currentSequence) {
      int pumpOffsetMin = stup.getMinPos();
      stup.setMinPos(pumpOffsetMin + Math.abs(minOffset));

      int pumpOffsetMax = stup.getMaxPos();
      stup.setMaxPos(pumpOffsetMax + Math.abs(minOffset));
    }
  public List<Droplet> generateDropletListRecursive(
      List<Droplet> dropletList, List<SequenceTuple> currentSequence, 
      int currentPos) {

    if (dropletList.size() == currentSequence.size()) {
      return dropletList;
    } else {

      if (dropletList.isEmpty() || 
          !Position.isOccupied(dropletList, currentPos)) {

        SequenceTuple tmpTup = currentSequence.get(dropletList.size());
        Droplet tmpDr = tmpTup.getDroplet();

        tmpDr.setPosition(new Position(this.getPump(), currentPos));
        Channel pumpOutlet = tmpTup.getPumpOutlet();
        tmpDr.setPumpOutlet(pumpOutlet);

        dropletList.add(tmpDr);
        // set current pos to minimum of the following sequence tuple
        if (dropletList.size() < currentSequence.size()) {
          currentPos = 
            currentSequence.get(dropletList.size()).getMinPos();
        }

        return generateDropletListRecursive(dropletList, currentSequence,
            currentPos);
      } else {
        SequenceTuple tmpTup = currentSequence.get(dropletList.size());
        if (currentPos < tmpTup.getMaxPos()) {
          currentPos++;
          return generateDropletListRecursive(dropletList, currentSequence,
              currentPos);
        } else {
          ListIterator<Droplet> revIter = dropletList.listIterator(
              dropletList.size());

          boolean found = false;
          while (!found && revIter.hasPrevious()) {
            Droplet tmpDr = revIter.previous();
            SequenceTuple tmpTup1 = currentSequence.get(dropletList.size() - 1);

            if (tmpDr.getPosition().getSteps() == currentPos &&
                currentPos < tmpTup1.getMaxPos()) {
              found = true;
            }
          }
          if (found) {
            currentPos++;
            return generateDropletListRecursive(dropletList, currentSequence,
                currentPos);
          } else {
            return dropletList;
          }
  public List<List<SequenceTuple>> getPossibleSequences(
    String[] modulesToVisit) throws NoSuchModuleException {

    Droplet payloadDroplet = new Droplet(DropletType.PAYLOAD,"p");

    List<List<SequenceTuple>> sequences = new ArrayList<List<SequenceTuple>>();

    List<List<Channel>> pathlist = this.getAllPaths();
    try {
      // Create initial list of possilbe sequences
      List<Channel> moduleChanList = 
        this.getModulesByName(Arrays.asList(modulesToVisit));
      List<Channel> payloadPath = this.getDesiredPath(moduleChanList, pathlist);

      SequenceTuple plt = new SequenceTuple(payloadDroplet,payloadPath,0,0);
Peter Wagenhuber's avatar
Peter Wagenhuber committed
      Channel previousBifurcation = plt.getPreviousBifurcation();
      plt.setCurrentBifurcation(previousBifurcation);
      List<SequenceTuple> s1 = new ArrayList<SequenceTuple>();
      s1.add(plt);

      sequences.add(s1);

Peter Wagenhuber's avatar
Peter Wagenhuber committed
      List<List<SequenceTuple>> oldsequences;
      do {
        oldsequences = new ArrayList<List<SequenceTuple>>(sequences);
        List<List<SequenceTuple>> tmpSeqs = new ArrayList<List<SequenceTuple>>();
        for (List<SequenceTuple> stl: sequences) {
          tmpSeqs.addAll(
Peter Wagenhuber's avatar
Peter Wagenhuber committed
              this.computeSequences(stl));
Peter Wagenhuber's avatar
Peter Wagenhuber committed
      } while (sequences.size() != oldsequences.size());
    } catch (Exception e) {
      System.out.println( e.getMessage());
    }
  public void addChannel(Channel chan) {
    chanlist.add(chan);
  }

  public Sink getSink() {
    Sink sink = null;
    for (Channel chan : chanlist) {
      if (chan instanceof Sink) sink = (Sink)chan;
    }
    return sink;
  }

  public Pump getPump() {
    Pump pump = null;
    for (Channel chan : chanlist) {
      if (chan instanceof Pump) pump = (Pump)chan;
    }
    return pump;
  }

  public boolean sequenceFunctional() {
      try {
        this.moveDroplets();
      } catch (CoalescedDropletException e) {
        works = false;
        //System.out.println("Coalesce! Droplet: " + e.getDroplet().getName() + " Position: " + e.getDroplet().getPosition().getChannel().getName());
  public List<Droplet> getDropletList() {
    return dropletList;
  }

  public void moveDroplets() throws CoalescedDropletException {
    Droplet[] drArr = this.dropletList.toArray(new Droplet[dropletList.size()]);
    for (Droplet dr : drArr) {
    for (Droplet dr: drArr) {
      if (dr.coalesce()) {
        throw new CoalescedDropletException(dr);
      }
  public List<Channel> getBifurcationList(List<Channel> desiredPath) {
    List<Channel> bfList = new ArrayList<Channel>();

    for (Channel ch: desiredPath) {
      if (ch.isBifurcation()) {
  public static int getPayloadPathlength(List<Channel> path) {
    int len = 0;
    for (Channel ch: path) {
      len += ch.getPSteps(); 
    }
    return len;
  }

  public static int getHeaderPathlength(List<Channel> path) {
    int len = 0;
    for (Channel ch: path) {
      len += ch.getHSteps(); 
    }
    return len;
  }

  public boolean allDropletsInSink() {
    boolean allInSink = true;
    for (Droplet dr : dropletList) {
      allInSink &= dr.isInSink();
    }
    return allInSink;
  public List<Channel> getDesiredPath(List<Channel> modules,
      List<List<Channel>> pathlist) throws NlocStructureException {

    List<Channel> found = new ArrayList<Channel>();

    for (List<Channel> path : pathlist) {

      List<Channel> modlist = new ArrayList<Channel>();

      for (Channel ch: path) {
        if (ch instanceof Module) {
          modlist.add(ch);
        }
      }

      if (modules.equals(modlist) && found.isEmpty()) {
        found = path;
      } else if (modules.equals(modlist) && !found.isEmpty()) {
        throw new NlocStructureException("Paths are not unique!");
      }
      
    if (found.isEmpty()) {
      throw new NlocStructureException("No path found that covers all given Modules");
  public Channel getModuleByName(String name) throws NoSuchModuleException {
    Channel found = null;
    for (Channel ch: chanlist) {
      if (ch.getName().equals(name)) {
        found = ch;
      } 
    }
    if (found == null) throw new NoSuchModuleException(name);
  public List<Channel> getModulesByName(List<String> names) 
    throws NoSuchModuleException {

    List<Channel> ret = new ArrayList<Channel>();
    for (String name : names) {
      Channel ch = getModuleByName(name);
      if (name != null) {
        ret.add(ch);
  public List<List<Channel>> getAllPathsFromTo(Channel from, Channel to) {
    List<List<Channel>> pl = new ArrayList<List<Channel>>();
    List<Channel> path = new ArrayList<Channel>();
    getAllPathsRecursive(from, to, path, pl);
    return pl;
  }

  public List<List<Channel>> getAllPaths() {
    List<List<Channel>> pl = new ArrayList<List<Channel>>();
    List<Channel> path = new ArrayList<Channel>();
    getAllPathsRecursive(this.getPump(), this.getSink(), path, pl);
  private void getAllPathsRecursive(Channel chan, Channel end, List<Channel> path, List<List<Channel>> pathlist) {
      pathlist.add(path);
    } else {
      for (Channel ch : chan.getChildrenList()) {
        getAllPathsRecursive(ch, end, new ArrayList<Channel>(path), pathlist);
Peter Wagenhuber's avatar
Peter Wagenhuber committed
  public List<List<SequenceTuple>> computeSequences(List<SequenceTuple> seqTup){
    List<List<SequenceTuple>> seqTupList = new ArrayList<List<SequenceTuple>>();
    //SequenceTuple currentSeqTup = seqTup.get(0);
    getSequencesAtBifurcationRecursive(seqTup, 0, seqTupList);
    //System.out.println("returning " + seqTupList);
Peter Wagenhuber's avatar
Peter Wagenhuber committed
  }

  private void getSequencesAtBifurcationRecursive(
      List<SequenceTuple> seqTupList, int currentSeqTupIndex, 
Peter Wagenhuber's avatar
Peter Wagenhuber committed
      List<List<SequenceTuple>> possibleSequences) {

    SequenceTuple currentSeqTup = seqTupList.get(currentSeqTupIndex);
Peter Wagenhuber's avatar
Peter Wagenhuber committed
    Channel currentBifurcation = currentSeqTup.getCurrentBifurcation();

    List<Channel> dropletPath = currentSeqTup.getPath();
    Channel bifurcSuccessor  = 
      dropletPath.get(dropletPath.indexOf(currentBifurcation) + 1);

    // bifurcation priority: prio = 0 if default channel; prio >= 1 if not 
    // default and threrfore header droplet needed
    int prio = currentBifurcation.getChildrenList().indexOf(bifurcSuccessor);

    if (currentSeqTup.equals(seqTupList.get(seqTupList.size() - 1))) {

      // if at last sequence tuple add another header droplet tuple if needed
      // and add the list of sequence tuples to the possible sequences list

      if (dropletPath.contains(currentBifurcation) && prio > 0 &&
          !(currentBifurcation instanceof Pump)) {

        // cirst check all possible paths of header droplets
        Channel defaultChan = currentBifurcation.getChildrenList().get(0);
          this.getAllPathsFromTo(dropletPath.get(0), defaultChan);
        currentSeqTup.
          setCurrentBifurcation(currentSeqTup.getPreviousBifurcation());
          List<SequenceTuple> tmp = new ArrayList<SequenceTuple>();
          for (SequenceTuple stup: seqTupList) {
            tmp.add(new SequenceTuple(stup));
          }
          String randHeaderName = 
            "h-" + ThreadLocalRandom.current().nextInt(1000, 10000);
            new SequenceTuple(new Droplet(DropletType.HEADER,randHeaderName),
                path, currentBifurcation);
Peter Wagenhuber's avatar
Peter Wagenhuber committed

          tmpTuple.setCurrentBifurcation(tmpTuple.getPreviousBifurcation());
          int minPos = currentSeqTup.getMinPos();
          int maxPos = currentSeqTup.getMaxPos();

          List<Channel> pathToCurrentBifurcation =
            dropletPath.subList(0,dropletPath.indexOf(currentBifurcation) + 1);

          int pathLenCurrDroplet = 0;
          if (currentSeqTup.getDroplet().getType() == DropletType.HEADER) {
            pathLenCurrDroplet = getHeaderPathlength(pathToCurrentBifurcation);
          } else {
            pathLenCurrDroplet = getPayloadPathlength(pathToCurrentBifurcation);
          }

          int maxPathLenNewDroplet = getHeaderPathlength(path);
          int minPathLenNewDroplet = 
            maxPathLenNewDroplet - defaultChan.getHSteps() + 1;

          int newTupleMinPos = 
            minPos - (pathLenCurrDroplet - minPathLenNewDroplet);
          int newTupleMaxPos = 
            maxPos - (pathLenCurrDroplet - maxPathLenNewDroplet);

          tmpTuple.setMinPos(newTupleMinPos);
          tmpTuple.setMaxPos(newTupleMaxPos);
      } else if (!(currentBifurcation instanceof Pump)) {
        // we still have some bifurcations to check
        currentSeqTup.
          setCurrentBifurcation(currentSeqTup.getPreviousBifurcation());
        getSequencesAtBifurcationRecursive(seqTupList, currentSeqTupIndex,
            possibleSequences);
Peter Wagenhuber's avatar
Peter Wagenhuber committed
    } else {
        //possibleSequences.add(seqTupList);
      if (dropletPath.contains(currentBifurcation) && prio > 0 &&
          !(currentBifurcation instanceof Pump)) {
        // we need header droplet 

        // cirst check all possible paths of header droplets
        Channel defaultChan = currentBifurcation.getChildrenList().get(0);
        List<List<Channel>> pathList = 
          this.getAllPathsFromTo(dropletPath.get(0), defaultChan);
        currentSeqTup.
          setCurrentBifurcation(currentSeqTup.getPreviousBifurcation());

        for (List<Channel> path: pathList) {
          List<SequenceTuple> tmp = new ArrayList<SequenceTuple>();
          for (SequenceTuple stup: seqTupList) {
            tmp.add(new SequenceTuple(stup));
          }
          String randHeaderName = 
            "h-" + ThreadLocalRandom.current().nextInt(1000, 10000);
            new SequenceTuple(new Droplet(DropletType.HEADER,randHeaderName),
                path, currentBifurcation);

          tmpTuple.setCurrentBifurcation(tmpTuple.getPreviousBifurcation());

          tmp.add(seqTupList.indexOf(currentSeqTup) + 1, tmpTuple);

          // calculate and set pump offsets
          int minPos = currentSeqTup.getMinPos();
          int maxPos = currentSeqTup.getMaxPos();

          List<Channel> pathToCurrentBifurcation =
            dropletPath.subList(0,dropletPath.indexOf(currentBifurcation) + 1);

          int pathLenCurrDroplet = 0;
          if (currentSeqTup.getDroplet().getType() == DropletType.HEADER) {
            pathLenCurrDroplet = getHeaderPathlength(pathToCurrentBifurcation);
          } else {
            pathLenCurrDroplet = getPayloadPathlength(pathToCurrentBifurcation);
          }

          int maxPathLenNewDroplet = getHeaderPathlength(path);
          int minPathLenNewDroplet = 
            maxPathLenNewDroplet - defaultChan.getHSteps() + 1;

          int newTupleMinPos = 
            minPos - (pathLenCurrDroplet - minPathLenNewDroplet);
          int newTupleMaxPos = 
            maxPos - (pathLenCurrDroplet - maxPathLenNewDroplet);

          tmpTuple.setMinPos(newTupleMinPos);
          tmpTuple.setMaxPos(newTupleMaxPos);

          getSequencesAtBifurcationRecursive(tmp, currentSeqTupIndex + 1, 
              possibleSequences); 
        }
      } else if (!(currentBifurcation instanceof Pump)) {
        // we still have some bifurcations to check
        currentSeqTup.
          setCurrentBifurcation(currentSeqTup.getPreviousBifurcation());
        getSequencesAtBifurcationRecursive(seqTupList, currentSeqTupIndex,
            possibleSequences);
      } else {
        getSequencesAtBifurcationRecursive(seqTupList, currentSeqTupIndex + 1, 
            possibleSequences); 

      }