示例#1
0
        public void DestroyLink(NetworkLink link)
        {
            //Console.WriteLine("Destroying link: " + link);

            int flowDeficit = link.flow;

            link.flow     = 0;
            link.capacity = 0;

            // if the link wasn't flowing in the first place, there are no further steps to take.
            if (flowDeficit == 0)
            {
                //Console.WriteLine("The flow this link is 0, so there are no more links to reduce.");
                return;
            }

            //Console.WriteLine("The following links will be reduced");

            // reduce the nodes in both the forward and backward directions recursively.
            ReduceNode(link.source, flowDeficit, false);
            ReduceNode(link.target, flowDeficit, true);

            // recalculate the maximum flow.
            maxFlow = target.GetFlow(false);

            //Console.WriteLine("Graph update complete. New max flow: " + maxFlow);
        }
示例#2
0
        // adds the passed node to the tables recursively
        static void AddNodeToTables(
            NetworkNode node,
            ref HashSet <NetworkNode> nodesAddedButNotRecorded,
            ref Dictionary <NetworkNode, NetworkLink> flowPathTable,
            ref Dictionary <NetworkNode, int> flowAmountTable,
            ref Stack <NetworkLink> cycleEdges
            )
        {
            nodesAddedButNotRecorded.Add(node);

            NetworkLink bestChoice = null;
            int         bestFlow   = 0;

            // search the outward links for the link which offers the best path to the target.
            foreach (NetworkLink link in node.linksOut)
            {
                // if the link cannot pass anymore flow, skip it.
                if (link.capacity - link.flow == 0)
                {
                    continue;
                }

                //	if the target of this link has been added already,
                //		and there is no entry for it in the flow path table,
                //		then this is a cycle edge. Don't evaluate it now.
                if (nodesAddedButNotRecorded.Contains(link.target))
                {
                    cycleEdges.Push(link);
                    continue;
                }
                else if (!flowPathTable.ContainsKey(link.target))
                {
                    AddNodeToTables(link.target, ref nodesAddedButNotRecorded, ref flowPathTable, ref flowAmountTable, ref cycleEdges);
                }

                //	if the minimum between the possible increase in flow on this link
                //		and the possible increase in flow for the path to the target
                //		following this edge is greater than that of the other links
                //		investigated so far, select this one as the best choice.
                int flow = Math.Min(link.capacity - link.flow, flowAmountTable[link.target]);
                if (flow > bestFlow)
                {
                    bestChoice = link;
                    bestFlow   = flow;
                }
            }

            //	add the best choice and best flow to the tables.
            //		if there were no outward links, or all of their (capacity - flow)s were 0, bestFlow will be 0.
            flowPathTable.Add(node, bestChoice);
            flowAmountTable.Add(node, bestFlow);

            nodesAddedButNotRecorded.Remove(node);
        }
示例#3
0
        //	Creates a directed network graph from a file. Automatically sets each link's capacity using an RNG.
        //	Generates a source and target node, connecting them at maximum flow to 'K' other nodes in the graph.
        //		fileName: name of the file containing the graph data.
        //		vertextCount: the number of verteces contained in the file.
        //		edgeCount: the number of edges contained in the file.
        //		minCapacity: the minimum capacity of the links in the graph. These will be randomly generated.
        //		maxCapacity: the maximum capacity of the links in the graph. These will be randomly generated.
        //		K: the number of edges that the generated source and target nodes will have going into, and out of, respectfully.
        //		SEED: the random number generator seed.
        public NetworkGraph(string fileName, int vertexCount, int edgeCount, int minCapacity, int maxCapacity, int K, int SEED)
        {
            Random random = new Random(SEED);

            vertices = new NetworkNode[vertexCount + 2];        // plus 2 for the source and target nodes that will be generated.
            edges    = new NetworkLink[edgeCount + 2 * K];      // plus 2 * K for the K edges going into and out of the source and target.
            maxFlow  = 0;

            // begin reading and parsing the file.
            using (Stream Stream = File.OpenRead(fileName))
                using (StreamReader reader = new StreamReader(Stream))
                {
                    string[] sepNodes = { "node [", "edge [" };
                    //Index 0 is everything before nodes, Don't need;
                    //Index nodes.Length is the edges, parsed after;
                    string[] arrayStrNodes = reader.ReadToEnd().Split(sepNodes, StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 1; i < arrayStrNodes.Length; i++)
                    {
                        string[] arrNode = arrayStrNodes[i].Split('\n');

                        bool   isEdge    = false;
                        int    id        = -1;
                        float  longitude = -1;
                        float  latitude  = -1;
                        string label     = "";
                        int    source    = -1;
                        int    target    = -1;

                        for (int j = 1; j < arrNode.Length; j++)
                        {
                            if (arrNode[j].Length > 4)
                            {
                                switch (arrNode[j][4])
                                {
                                case 'i':
                                    string strID = arrNode[j].Substring(7);
                                    if (strID.Length > 1 && strID[1] == 'e')//added length check for id 0 of nodes
                                    {
                                        isEdge = true;
                                        id     = Convert.ToInt32(strID.Substring(2, strID.Length - 4));
                                    }
                                    else
                                    {
                                        id = Convert.ToInt32(strID);
                                    }
                                    break;

                                case 'L':
                                    if (arrNode[j][5] == 'o')//Longitude
                                    {
                                        longitude = (float)Convert.ToDouble(arrNode[j].Substring(14));
                                    }
                                    else//Latitude
                                    {
                                        latitude = (float)Convert.ToDouble(arrNode[j].Substring(13));
                                    }
                                    break;

                                case 'l':
                                    label = arrNode[j].Substring(11, arrNode[j].Length - 13);
                                    break;

                                case 's':
                                    source = Convert.ToInt32(arrNode[j].Substring(10));
                                    break;

                                case 't':
                                    target = Convert.ToInt32(arrNode[j].Substring(10));
                                    break;
                                }
                            }
                        }
                        if (id > -1)
                        {
                            if (isEdge)
                            {
                                NetworkLink link = new NetworkLink(vertices[source], vertices[target]);
                                edges[id]     = link;
                                link.capacity = random.Next(minCapacity, maxCapacity + 1);
                            }
                            else
                            {
                                NetworkNode node = new NetworkNode(label, longitude, latitude);
                                vertices[id] = node;
                            }
                        }
                    }
                }

            //Declaring the source and target nodes
            //Doesn't really matter "where" they are
            source = new NetworkNode("source", 0, 0);
            target = new NetworkNode("target", 0, 0);

            vertices[vertexCount]     = source;
            vertices[vertexCount + 1] = target;

            Random rand = new Random(SEED);
            //List to keep track of the nodes that are conncected to by the source and target
            List <NetworkNode> sourceLinks = new List <NetworkNode>(K);
            List <NetworkNode> targetLinks = new List <NetworkNode>(K);
            //Index to keep track of where to add into the edges array
            int LinkIndex = 1;

            //generating the edges for source edges
            while (sourceLinks.Count < sourceLinks.Capacity)
            {
                int i = rand.Next(0, vertexCount);
                if (!sourceLinks.Contains(vertices[i]))
                {
                    sourceLinks.Add(vertices[i]);
                    edges[edgeCount - 1 + LinkIndex]          = new NetworkLink(source, vertices[i]);
                    edges[edgeCount - 1 + LinkIndex].capacity = 20;
                    LinkIndex++;
                }
            }
            //generating edges for target edges
            //Compares to make sure the target does not connect to any of the same nodes as the source.
            while (targetLinks.Count < targetLinks.Capacity)
            {
                int i = rand.Next(0, vertexCount);
                if (!sourceLinks.Contains(vertices[i]) && !targetLinks.Contains(vertices[i]))
                {
                    targetLinks.Add(vertices[i]);
                    edges[edgeCount - 1 + LinkIndex]          = new NetworkLink(vertices[i], target);
                    edges[edgeCount - 1 + LinkIndex].capacity = 20;
                    LinkIndex++;
                }
            }
            //Console.WriteLine("Built graph from " + fileName + ". Nodes: " + vertexCount + " Links: " + edgeCount + ".");
        }
示例#4
0
        static void ReduceNode(NetworkNode node, int deficit, bool forward)
        {
            // if the node has no more links to follow, just quit.
            if ((forward ? node.linksOut.Count : node.linksIn.Count) == 0)
            {
                return;
            }

            // try to find a link that is large enough to take the whole flow hit.
            // else, fill a list with links that have flow to add up to the deficit.
            NetworkLink        toReduce   = null;
            List <NetworkLink> reduceList = new List <NetworkLink>();

            foreach (NetworkLink link in (forward ? node.linksOut : node.linksIn))
            {
                if (link.flow == deficit)
                {
                    toReduce = link;
                    break;
                }
                else if (link.flow > deficit)
                {
                    toReduce = link;
                }
                else if (link.flow != 0 && toReduce == null)
                {
                    reduceList.Add(link);
                }
            }

            // if there is a link with an equal or greater flow than the deficit, simply reduce that one.
            if (toReduce != null)
            {
                //Console.WriteLine("\tReduced by " + deficit + ": " + toReduce);

                toReduce.flow -= deficit;
                ReduceNode((forward ? toReduce.target : toReduce.source), deficit, forward);
            }

            // otherwise, search through the reduce list for links that will add up their flows to the deficit and reduce each of them.
            else if (reduceList.Count > 0)
            {
                int i = 0;
                while (deficit != 0)
                {
                    int flowDeficit = reduceList[i].flow;
                    if (flowDeficit > deficit)
                    {
                        flowDeficit = deficit;
                    }
                    deficit -= flowDeficit;

                    //Console.WriteLine("\tReduced by " + flowDeficit + ": " + reduceList[i]);

                    reduceList[i].flow -= flowDeficit;
                    ReduceNode((forward ? reduceList[i].target : reduceList[i].source), flowDeficit, forward);

                    i++;
                }
            }
        }
 // adds the network link to the correct link list.
 public void AddLink(NetworkLink link)
 {
     (link.source == this ? linksOut : linksIn).Add(link);
 }