/// <summary> /// Processes the first available agent in a leaf node. /// </summary> /// <param name="l">Index of the leaf node to process.</param> /// <param name="state">State of the parallel loop.</param> /// <param name="doneTick">Whether or not the process cycle has been completed.</param> /// <returns>The doneTick variable.</returns> private long ProcessLeafSingle(int l, ParallelLoopState state, long toProcess) { // Get leaf LeafNode leaf = Leaves[l]; // If there is an agent to process if (leaf.Out.Count > 0) { // Get agent from node Agent a = leaf.Dequeue(); // Perform transaction between station and agent InteractTerm(leaf.Terminal, a); // Get node that agent will travel to next GraphNode exit = leaf.GetExit(a); // Move agent to node if available, otherwise put back onto leaf if (exit != null) { exit.Enqueue(a); } else { leaf.Enqueue(a); } // If there are more agents, then the tick isn't done if (leaf.Out.Count > 0) { toProcess++; } } return(toProcess); }
/// <summary> /// Generate a new graph for this object. /// </summary> /// <param name="rand">The random object to be used for generation.</param> /// <param name="total_remain">The total number of nodes in this graph.</param> /// <param name="max_children">The max number of children per node.</param> /// <param name="offset">The offset from the average.</param> public void GenTree(Random rand, int total_remain, int max_children, int offset, int leaf_chance) { int n_kids_tot, c_kids_tot, n_kids_max, n_kids_min, kids_remain, avg_kpn, real_kpn, tier, tier_index, min; GraphNode[] cur_tier; List <GraphNode> next_tier; RootNode root; List <BranchNode> branches; List <LeafNode> leaves; GraphNode current; List <int> tiers; bool isRoot; // Initialize branches and leaves; branches = new List <BranchNode>(); leaves = new List <LeafNode>(); tiers = new List <int>(); // Initialize the positioning variables tier = 0; tier_index = 0; // The head will have one neighbor n_kids_tot = 1; // Subtract the head and it's neighbor from the remaining total total_remain -= n_kids_tot + 1; // Initialize the head root = new RootNode(); root.Layout = new int[] { tier, tier_index }; tier_index++; // Insert head as only node of next tier of nodes to work on next_tier = new List <GraphNode>() { root }; // set first tier bool isRoot = true; while (n_kids_tot > 0) { // Set next tier as current tier and get new next tier cur_tier = next_tier.ToArray(); next_tier = new List <GraphNode>(); tier++; tiers.Add(tier_index); tier_index = 0; // Set next total to current tier and reset next total c_kids_tot = n_kids_tot; n_kids_tot = 0; // Get total possible nodes for next tier as multiple of nodes to generate times // the max number of children each node can have n_kids_max = c_kids_tot * max_children; // If possible total is larger than total remaining, clamp to later if (total_remain < n_kids_max) { kids_remain = total_remain; } // Otherwise set projected total for next tier as a random number between half // this tier and the possible total else { n_kids_min = c_kids_tot / 2 < 1 ? 1 : c_kids_tot / 2; kids_remain = rand.Next(n_kids_min, n_kids_max + 1); } // Subtract this tier's total from remaining total total_remain -= kids_remain; // Get the average number of children per node of this tier avg_kpn = kids_remain / c_kids_tot < 1 ? 1 : kids_remain / c_kids_tot; // For each node in this tier for (int i = 0; i < cur_tier.Length; i++) { // For each child of this node for (int j = isRoot ? 0 : 1; j < cur_tier[i].Neighbors.Length; j++) { // If the average is greater than what remains to be generated, then clamp to later if (kids_remain < avg_kpn) { real_kpn = kids_remain; } // Otherwise, random chance for leaf else if (n_kids_tot > 0 && rand.Next(100) < leaf_chance) { real_kpn = 0; } // Otherwise set real number of children to some random offset from the average // and clamp the value to max or the remaining children if necessary else { min = Math.Min(offset, avg_kpn); real_kpn = Math.Min(avg_kpn + rand.Next(offset + min) - min + 1, Math.Min(max_children, kids_remain)); if (real_kpn == 0) { return; } } // Subtract this node's children from remaining children kids_remain -= real_kpn; // Add to total of next tier n_kids_tot += real_kpn; // Generate a node with the calculated number of children if (real_kpn == 0) { current = new LeafNode(); leaves.Add((LeafNode)current); } else { current = new BranchNode(real_kpn + 1); branches.Add((BranchNode)current); next_tier.Add(current); } // Position current node current.Layout = new int[] { tier, tier_index }; tier_index++; // Add node to graph cur_tier[i].AddNeighbor(current); } } // Add back on any un-generated children total_remain += kids_remain; // turn off special head case bool if (isRoot) { isRoot = false; } } // Set all the finalized values Roots = new List <RootNode> { root }; Branches = branches; Leaves = leaves; Counts = tiers; }