org.sonar.graph.MinimumFeedbackEdgeSetSolver Maven / Gradle / Ivy
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Sonar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.graph;
import java.util.*;
public class MinimumFeedbackEdgeSetSolver {
private final List feedbackCycles;
private Set feedbackEdges;
private int minimumFeedbackEdgesWeight = Integer.MAX_VALUE;
private final int cyclesNumber;
private final int maxNumberCyclesForSearchingMinimumFeedback;
private static final int DEFAULT_MAXIMUM_NUMBER_OF_LOOPS = 1000000;
private static final int MAXIMUM_NUMBER_OF_CYCLE_THAT_CAN_BE_HANDLED = 1500;
private final int maximumNumberOfLoops;
public int getNumberOfLoops() {
return numberOfLoops;
}
private int numberOfLoops = 0;
public MinimumFeedbackEdgeSetSolver(Set cycles, int maxCycles) {
this(cycles, DEFAULT_MAXIMUM_NUMBER_OF_LOOPS, maxCycles);
}
public MinimumFeedbackEdgeSetSolver(Set cycles) {
this(cycles, DEFAULT_MAXIMUM_NUMBER_OF_LOOPS, MAXIMUM_NUMBER_OF_CYCLE_THAT_CAN_BE_HANDLED);
}
public MinimumFeedbackEdgeSetSolver(Set cycles, int maximumNumberOfLoops, int maxNumberCyclesForSearchingMinimumFeedback) {
this.maximumNumberOfLoops = maximumNumberOfLoops;
this.feedbackCycles = FeedbackCycle.buildFeedbackCycles(cycles);
this.cyclesNumber = cycles.size();
this.maxNumberCyclesForSearchingMinimumFeedback = maxNumberCyclesForSearchingMinimumFeedback;
this.run();
}
public int getWeightOfFeedbackEdgeSet() {
return minimumFeedbackEdgesWeight;
}
/**
* Get edges tagged as feedback.
*/
public Set getEdges() {
Set edges = new HashSet();
for (FeedbackEdge fe : feedbackEdges) {
edges.add(fe.getEdge());
}
return edges;
}
private void run() {
Set pendingFeedbackEdges = new HashSet();
if (cyclesNumber < maxNumberCyclesForSearchingMinimumFeedback) {
searchFeedbackEdges(0, 0, pendingFeedbackEdges);
}
else {
lightResearchForFeedbackEdges();
}
}
private void lightResearchForFeedbackEdges() {
feedbackEdges = new HashSet();
for (FeedbackCycle cycle : feedbackCycles) {
for (FeedbackEdge edge : cycle) {
feedbackEdges.add(edge);
break;
}
}
minimumFeedbackEdgesWeight = 0;
for(FeedbackEdge edge : feedbackEdges) {
minimumFeedbackEdgesWeight += edge.getWeight();
}
}
private void searchFeedbackEdges(int level, int pendingWeight, Set pendingFeedbackEdges) {
if (numberOfLoops++ > maximumNumberOfLoops) {
return;
}
if (pendingWeight >= minimumFeedbackEdgesWeight) {
return;
}
if (level == cyclesNumber) {
minimumFeedbackEdgesWeight = pendingWeight;
feedbackEdges = new HashSet(pendingFeedbackEdges);
//System.out.println("Weight : " + minimumFeedbackEdgesWeight + " in " + numberOfLoops + " loops");
return;
}
FeedbackCycle feedbackCycle = feedbackCycles.get(level);
if (doesFeedbackEdgesContainAnEdgeOfTheCycle(pendingFeedbackEdges, feedbackCycle)) {
searchFeedbackEdges(level + 1, pendingWeight, pendingFeedbackEdges);
}
else {
boolean hasAnEdgeWithOccurrenceOfOneBeenUsed = false;
for (FeedbackEdge feedbackEdge : feedbackCycle) {
if (feedbackEdge.getOccurences() == 1) {
if (hasAnEdgeWithOccurrenceOfOneBeenUsed) {
continue;
}
else {
hasAnEdgeWithOccurrenceOfOneBeenUsed = true;
}
}
int edgeWeight = addNewEdge(feedbackEdge, pendingFeedbackEdges);
pendingWeight += edgeWeight;
searchFeedbackEdges(level + 1, pendingWeight, pendingFeedbackEdges);
pendingWeight -= edgeWeight;
pendingFeedbackEdges.remove(feedbackEdge);
}
}
}
private boolean doesFeedbackEdgesContainAnEdgeOfTheCycle(Set pendingFeedbackEdges, FeedbackCycle cycle) {
boolean contains = false;
for (FeedbackEdge feedbackEdge : cycle) {
if (pendingFeedbackEdges.contains(feedbackEdge)) {
contains = true;
break;
}
}
return contains;
}
private int addNewEdge(FeedbackEdge feedbackEdge, Set pendingFeedbackEdges) {
pendingFeedbackEdges.add(feedbackEdge);
return feedbackEdge.getWeight();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy