I\'m working on an algorithm which goal is to find a minimum set of packages to install package \"X\".
I\'ll explain better with an example:
Since the graph consists of two different types of edges (AND and OR relationship), we can split the algorithm up into two parts: search all nodes that are required successors of a node and search all nodes from which we have to select one single node (OR).
Nodes hold a package, a list of nodes that must be successors of this node (AND), a list of list of nodes that can be successors of this node (OR) and a flag that marks on which step in the algorithm the node was visited.
define node: package p , list required , listlist optional ,
int visited[default=MAX_VALUE]
The main-routine translates the input into a graph and starts traversal at the starting node.
define searchMinimumP:
input: package start , string[] constraints
output: list
//generate a graph from the given constraint
//and save the node holding start as starting point
node r = getNode(generateGraph(constraints) , start)
//list all required nodes
return requiredNodes(r , 0)
requiredNodes
searches for all nodes that are required successors of a node (that are connected to n
via AND-relation over 1 or multiple edges).
define requiredNodes:
input: node n , int step
output: list
//generate a list of all nodes that MUST be part of the solution
list rNodes
list todo
add(todo , n)
while NOT isEmpty(todo)
node next = remove(0 , todo)
if NOT contains(rNodes , next) AND next.visited > step
add(rNodes , next)
next.visited = step
addAll(rNodes , optionalMin(rNodes , step + 1))
for node r in rNodes
r.visited = step
return rNodes
optimalMin
searches for the shortest solution among all possible solutions for optional neighbours (OR). This algorithm is brute-force (all possible selections for neighbours will be inspected.
define optionalMin:
input: list nodes , int step
output: list
//find all possible combinations for selectable packages
listlist optSeq
for node n in nodes
if NOT n.visited < step
for list opt in n.optional
add(optSeq , opt)
//iterate over all possible combinations of selectable packages
//for the given list of nodes and find the shortest solution
list shortest
int curLen = MAX_VALUE
//search through all possible solutions (combinations of nodes)
for list seq in sequences(optSeq)
list subseq
for node n in distinct(seq)
addAll(subseq , requiredNodes(n , step + 1))
if length(subseq) < curLen
//mark all nodes of the old solution as unvisited
for node n in shortest
n.visited = MAX_VALUE
curLen = length(subseq)
shortest = subseq
else
//mark all nodes in this possible solution as unvisited
//since they aren't used in the final solution (not at this place)
for node n in subseq
n.visited = MAX_VALUE
for node n in shorest
n.visited = step
return shortest
The basic idea would be the following: Start from the starting node and search for all nodes that must be part of the solution (nodes that can be reached from the starting node by only traversing AND-relationships). Now for all of these nodes, the algorithm searches for the combination of optional nodes (OR) with the fewest nodes required.
NOTE: so far this algorithm isn't much better than brute-force. I'll update as soon as i've found a better approach.