예제 #1
0
 public double tryRemoveFakeEdge(double temp, double currentEnergy) {
   if (fakeEdges.size() > 0) {
     PEdge<V, E> choice = fakeEdges.get(random.nextInt(fakeEdges.size()));
     ArrayList<PEdge<V, E>> toBeRemoved = new ArrayList<PEdge<V, E>>();
     if (Math.random() < 0.5) { // remove single edge
       toBeRemoved.add(choice);
     } else {
       for (PEdge<V, E> parent : choice.to.getParents()) {
         if (parent.isFake && !parent.from.isRoot) {
           toBeRemoved.add(parent);
         }
       }
     }
     ArrayList<Integer> positions = new ArrayList<Integer>(toBeRemoved.size());
     for (PEdge<V, E> fakeEdge : toBeRemoved) {
       int position = fakeEdge.from.getChildren().indexOf(fakeEdge);
       fakeEdge.from.getChildren().remove(position);
       positions.add(position);
       fakeEdge.to.removeParent(fakeEdge);
     }
     double newEnergy = getEnergy();
     if (acceptChange(currentEnergy, newEnergy, temp)) {
       fakeEdges.removeAll(toBeRemoved);
       return newEnergy;
     } else {
       for (int i = positions.size() - 1; i >= 0; i--) {
         PEdge<V, E> fakeEdge = toBeRemoved.get(i);
         fakeEdge.from.getChildren().add(positions.get(i), fakeEdge);
         fakeEdge.to.addParent(fakeEdge);
       }
       return currentEnergy;
     }
   }
   return currentEnergy;
 }
예제 #2
0
  public double runSimulatedAnnealing(int iterations) {
    if (!locked) lock();
    double temp = 1;
    double coolingFactor = Math.pow(0.001, 1d / iterations);
    double currentEnergy = getEnergy();
    if (nodes.isEmpty()) return currentEnergy;
    Collections.shuffle(nodesWithSeveralChildrenScaled, random);
    Collections.shuffle(sourceFakeEdges, random);

    while (temp > 0.001) {
      double action = random.nextDouble();
      if (action < 0.19) { // add fake edge
        currentEnergy = tryAddFakeEdge(temp, currentEnergy);
        assert currentEnergy == getEnergy();
      } else if (action
          < 0.36) { // remove fake edge (slightly higher probability - we don't want too many fake
        // edges) - update: apparently, that hypothesis is wrong
        currentEnergy = tryRemoveFakeEdge(temp, currentEnergy);
        assert currentEnergy == getEnergy();
      } else if (action < 0.7) { // swap two children of some node
        currentEnergy = trySwapChildren(temp, currentEnergy);
        assert currentEnergy == getEnergy();
      } else { // change where one of the sources is attached to
        currentEnergy = tryChangeSource(temp, currentEnergy);
        assert currentEnergy == getEnergy();
      }
      temp *= coolingFactor;
    }
    return currentEnergy;
  }
예제 #3
0
  public double tryAddFakeEdge(double temp, double currentEnergy) {
    // it's sufficient to only add fake edges from leaves to nodes with multiple parents
    if (nodesWithoutChildren.size() > 0 && nodesWithSeveralParents.size() > 0) {
      PNode<V, E> from = nodesWithoutChildren.get(random.nextInt(nodesWithoutChildren.size()));
      PNode<V, E> to = nodesWithSeveralParents.get(random.nextInt(nodesWithSeveralParents.size()));
      PEdge<V, E> fakeEdge = new PEdge<V, E>(from, to);
      from.addChild(fakeEdge);
      to.addParent(fakeEdge);

      if (!graphHasCycle(to)) {
        double newEnergy = getEnergy();
        if (acceptChange(currentEnergy, newEnergy, temp)) {
          fakeEdges.add(fakeEdge);
          return newEnergy;
        }
      }
      // otherwise undo changes
      from.removeChild(fakeEdge);
      to.removeParent(fakeEdge);
      return currentEnergy;
    }
    return currentEnergy;
  }
예제 #4
0
 public double trySwapChildren(double temp, double currentEnergy) {
   if (nodesWithSeveralChildrenScaled.size() > 0) {
     PNode<V, E> parent =
         nodesWithSeveralChildrenScaled.get(
             quadraticRandint(nodesWithSeveralChildrenScaled.size()));
     nodesWithSeveralChildrenScaled.remove(parent);
     nodesWithSeveralChildrenScaled.add(
         parent); // move it to the end - less likely to be picked again in near future
     int numberOfChildren = parent.getChildren().size();
     int i1 = random.nextInt(numberOfChildren);
     int i2 = random.nextInt(numberOfChildren - 1);
     i2 = i2 >= i1 ? i2 + 1 : i2;
     parent.swapChildren(i1, i2);
     double newEnergy = getEnergy();
     if (acceptChange(currentEnergy, newEnergy, temp)) {
       return newEnergy;
     } else {
       parent.swapChildren(i1, i2); // swap back
       return currentEnergy;
     }
   }
   return currentEnergy;
 }
예제 #5
0
  public double tryChangeSource(double temp, double currentEnergy) {
    PEdge<V, E> fakeEdge = sourceFakeEdges.get(random.nextInt(sourceFakeEdges.size()));
    PNode<V, E> child = fakeEdge.to;
    int oldIndex = fakeEdge.from.getChildren().indexOf(fakeEdge);
    child.removeParent(fakeEdge);
    fakeEdge.from.removeChild(fakeEdge);
    PEdge<V, E> fakeEdge2;

    int fakeEdge2Swap = -1;

    if (fakeEdge.from.isRoot || random.nextDouble() < 0.4) { // try attaching it somewhere else
      PNode<V, E> parent;
      if (Math.random() < 0.5
          || nodesWithSeveralChildrenScaled.size() == 0) { // try some completely random node
        parent = nodes.get(random.nextInt(nodes.size()));
      } else {
        parent =
            nodesWithSeveralChildrenScaled.get(
                random.nextInt(nodesWithSeveralChildrenScaled.size()));
      }
      fakeEdge2 = new PEdge<V, E>(parent, child);
      parent.addChild(fakeEdge2);
      if (parent.getChildren().size() > 1) {
        fakeEdge2Swap = random.nextInt(parent.getChildren().size() - 1);
        parent.swapChildren(parent.getChildren().size() - 1, fakeEdge2Swap);
      }
      child.addParent(fakeEdge2);
    } else { // try attaching it back to root.
      fakeEdge2 = new PEdge<V, E>(root, child);
      root.addChild(fakeEdge2);
      if (root.getChildren().size() > 1) {
        fakeEdge2Swap = random.nextInt(root.getChildren().size() - 1);
        root.swapChildren(root.getChildren().size() - 1, fakeEdge2Swap);
      }
      child.addParent(fakeEdge2);
    }
    if (!graphHasCycle(fakeEdge2.to)) {
      double newEnergy = getEnergy();
      if (acceptChange(currentEnergy, newEnergy, temp)) {
        sourceFakeEdges.remove(fakeEdge);
        sourceFakeEdges.add(fakeEdge2);
        return newEnergy;
      }
    }

    fakeEdge2.from.removeChild(fakeEdge2);
    child.removeParent(fakeEdge2);
    if (fakeEdge2Swap != -1) {
      PEdge<V, E> e = fakeEdge2.from.getChildren().get(fakeEdge2.from.getChildren().size() - 1);
      fakeEdge2.from.getChildren().remove(fakeEdge2.from.getChildren().size() - 1);
      fakeEdge2.from.getChildren().add(fakeEdge2Swap, e);
    }
    // fakeEdge.from.addChild(fakeEdge);
    fakeEdge.from.getChildren().add(oldIndex, fakeEdge);
    child.addParent(fakeEdge);
    return currentEnergy;
  }
예제 #6
0
 public static int quadraticRandint(int limit) {
   // return (int)(random.nextDouble() * limit);
   return (int) (random.nextDouble() * random.nextDouble() * limit);
   // return 0;
 }