// compute the flows on the routing table, based on the selected // flow-computation algorithm. There are two algorithms that // can be used, "simplex" and "propagate", although in this version // of the program only "propagate" is implemented. *operation* void compute_flows(RoutingTable* rtable) *traverse* *from* FlowAlg *to* {Propagate} *wrapper* Propagate (@ rtable->compute_propagate_flows(); @) // this is the "propagate" algorithm for the computation of the // flows in the routing table. *operation* void compute_propagate_flows() *traverse* *from* RoutingTable *through* -> *, dag, *, -> *, neighbors, * *to* DagNeighbor *carry* *in* Dag* dag = (@ this @) *along* *from* Dag *through* -> *, neighbors, * *to* DagNeighbor *carry* *in* VNode* source_vnode = (@ get_source() @), *in* double traffic = (@ get_traffic()->get_val() @) *along* *from* DagAdjacency *through* -> *, neighbors, * *to* DagNeighbor *wrapper* DagNeighbor (@ if (*get_shortcut() == 1) get_flow()->set_val(0); else { double prob = get_prob()->get_val(); double flow = traffic * prob + dag->compute_flow(source_vnode, get_neighbor()); get_flow()->set_val(flow); } @) // calculate the total incoming flow to virtual node "to_vnode" in // a DAG. *operation* double incoming_flow(VNode* to_vnode) *init* (@ 0.0 @) *traverse* *from* Dag *through* -> *, neighbors, * *to* DagNeighbor *wrapper* DagNeighbor (@ if (get_neighbor() == to_vnode) return_val += *get_flow(); @) // compute the flow on link (from_vnode, to_vnode) in the corresponfing // DAG. Special provision is taken for shortcut links. *operation* double compute_flow(VNode* from_vnode, VNode* to_vnode) *init* (@ 0.0 @) *traverse* *from* Dag *through* -> *, neighbors, * *to* DagNeighbor *carry* *in* Dag* dag = (@ this @) *along* *from* Dag *through* -> *, neighbors, * *to* DagNeighbor *carry* *in* VNode* source_vnode = (@ get_source() @) *along* *from* DagAdjacency *through* -> *, neighbors, * *to* DagNeighbor *wrapper* DagAdjacency *prefix* (@ if (source_vnode->get_phys_node() == from_vnode->get_phys_node()) { @) *wrapper* DagAdjacency *suffix* (@ } @) *wrapper* DagNeighbor (@ if (get_neighbor() == to_vnode) return_val += dag->incoming_flow(source_vnode) * (*get_prob()); @) // compute the total flows on the ring, based on the values of the flows // in the routing table. For each link on the ring, sum the flows for // all the destinations (DAGs). *operation* void compute_total_flows(RoutingTable* rtable) *traverse* *from* Ring *through* -> *, jumps, * // we don't need the shortcuts, because // the total flow on a shortcut link is // always 0. *to* VirtualNeighbor *carry* *in* Ring* ring = (@ this @) *along* *from* Ring *through* -> *, jumps, * *to* VirtualNeighbor *carry* *in* VNode* source_vnode = (@ get_source() @) *along* *from* VirtualAdjacency *through* -> *, jumps, * *to* VirtualNeighbor *wrapper* VirtualAdjacency (@ VNode* next_vnode = ring->get_nextdefault(this)->get_source(); double total_flow = rtable->total_flow(source_vnode, next_vnode); get_next_total_flow()->set_val(total_flow); @) *wrapper* VirtualNeighbor (@ double total_flow = rtable->total_flow(source_vnode, get_neighbor()); get_total_flow()->set_val(total_flow); @) // compute the total flow on the link (vnode1, vnode2) on the // routing table. *operation* double total_flow(VNode* vnode1, VNode* vnode2) *init* (@ 0.0 @) *traverse* *from* RoutingTable *through* -> *, dag, * *to* DagNeighbor *wrapper* DagAdjacency *prefix* (@ if (get_source() == vnode1) { @) *wrapper* DagAdjacency *suffix* (@ } @) *wrapper* DagNeighbor (@ if (get_neighbor() == vnode2) return_val += *get_flow(); @) // search the ring, to find the maximum total flow (congestion) *operation* double congestion() *init* (@ 0.0 @) *traverse* *from* Ring *through* -> *, jumps, * *to* VirtualNeighbor *wrapper* VirtualAdjacency (@ double total_flow = *get_next_total_flow(); if (total_flow > return_val) return_val = total_flow; @) *wrapper* VirtualNeighbor (@ double total_flow = *get_total_flow(); if (total_flow > return_val) return_val = total_flow; @)