コード例 #1
0
Array * page_rank(Table * inbound, unsigned int order, float alpha, float convergence, unsigned int max_times)
{
        register int t = 0, k, i;
        register float norm2 = 1.0, prod_scalar, x;
        unsigned int total_size = order;
        Array * vector = initial(total_size);
        Array * new_vector = initial(total_size);
        Array * tmp;



        x = 1.0 - alpha;

        while (t < max_times && norm2 >= convergence) {
                t++;
                norm2 = 0.0;
                prod_scalar = 0.0;

                for (k = 0; k < total_size; k++) {
                        if (is_sink(inbound, k))
                                prod_scalar += array_get(vector, k) * alpha;
                }
                prod_scalar += x;

                for (k = 0; k < total_size; k++) {
                        array_set(new_vector, k, prod_scalar);
                        if (!is_sink(inbound, k)) {
                                tmp = table_get(inbound, k);
                                for (i = 0; i < array_len(tmp); i++) {
                                        array_incr(new_vector, k,
                                                   array_get(vector,
                                                             (int)array_get(tmp, i)) *
                                                   alpha);
                                }
                        }
                        norm2 += (array_get(new_vector, k) - array_get(vector, k)) *
                                (array_get(new_vector, k) - array_get(vector, k));
                }

                t++;

                norm2 = sqrt((double)norm2) / total_size;

                array_copy(vector, new_vector);
        }

        array_delete(new_vector);
        return normalize(vector);
}
コード例 #2
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Print the graph
*
* Print the graph. Useful for debugging.
*
* @warning The format in which this function prints a graph is not the same
* 			as the DAG string format used by the XSocket API. To obtain a 
*			string version of the DAG for use with the XSocket API, use
*			Graph::dag_string() instead.
*/
void
Graph::print_graph() const
{
	for (std::size_t i = 0; i < nodes_.size(); i++)
	{
		if (is_source(i))
			printf("[SRC] ");
		else
			printf("      ");

		printf("Node %zu: [%s] ", i, nodes_[i].type_string().c_str());
		//printf("%20s", nodes_[i].id());
		for (std::size_t j = 0; j < Node::ID_LEN; j++)
			printf("%02x", nodes_[i].id()[j]);
		bool first = true;
		for (std::size_t j = 0; j < out_edges_[i].size(); j++)
		{
			if (first)
			{
				first = false;
				printf(" ->");
			}
			printf(" Node %zu", out_edges_[i][j]);
		}
		if (is_sink(i))
			printf(" [SNK]");
		printf("\n");
	}
}
コード例 #3
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
Graph&
Graph::operator*=(const Graph& r)
{
	std::vector<std::size_t> sinks;
	std::vector<std::size_t> sources;

	for (std::size_t i = 0; i < nodes_.size(); i++)
		if (is_sink(i))
			sinks.push_back(i);

	for (std::size_t i = 0; i < r.nodes_.size(); i++)
		if (r.is_source(i))
		{
			if (r.nodes_[i].type() == Node::XID_TYPE_DUMMY_SOURCE)
			{
				for (std::vector<std::size_t>::const_iterator it = r.out_edges_[i].begin(); it != r.out_edges_[i].end(); ++it)
					vector_push_back_unique(sources, *it);
			}
			else
			{
				sources.push_back(i);
			}
		}

	std::vector<std::size_t> node_mapping_r;
	merge_graph(r, node_mapping_r, true);

	for (std::vector<std::size_t>::const_iterator it_sink = sinks.begin(); it_sink != sinks.end(); ++it_sink)
		for (std::vector<std::size_t>::const_iterator it_source = sources.begin(); it_source != sources.end(); ++it_source)
			add_edge(*it_sink, node_mapping_r[*it_source]);

	return *this;
}
コード例 #4
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Test if a node is the final intent
*
* Check whether or not the supplied Node is the final intent of the DAG
*
* @param n The node to check
*
* @return true if n is the final intent, false otherwise
*/
bool
Graph::is_final_intent(const Node& n)
{
	for (std::size_t i = 0; i < nodes_.size(); i++)
	{
		if (nodes_[i] == n) return is_sink(i);
	}
	
	printf("Warning: is_final_intent: supplied node not found in DAG: %s\n", n.id_string().c_str());
	return false;
}
コード例 #5
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Get the index of the final intent node
*
* Get the index of the final intent node. This method returns the index of the
* first sink node it finds.
*
* @return The index of the DAG's final intent node.
*/
std::size_t
Graph::final_intent_index() const
{
	for (std::size_t i = 0; i < nodes_.size(); i++)
	{
		if (is_sink(i)) return i;
	}

	printf("Warning: source_index: no sink node found\n");
	return -1;
}
コード例 #6
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Get a node from the DAG
*
* Get a Node from the graph at the specified index. The sink node will always
* be returned last (that is, it has index num_nodes()-1).
*
* @note This function skips the starting node
*
* @param i The index of the node to return
*
* @return The node at index i
*/
Node 
Graph::get_node(int i) const
{
	std::size_t src_index, sink_index;
	for (std::size_t j = 0; j < nodes_.size(); j++)
	{
		if (is_source(j)) src_index = j;
		if (is_sink(j)) sink_index = j;
	}

	return nodes_[index_from_dag_string_index(i, src_index, sink_index)];
}
コード例 #7
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Return the graph in string form
*
* Get the DAG string representation of the graph. This string is suitable for
* use with the XSocket API.
*
* @return The graph in DAG string form.
*/
std::string
Graph::dag_string() const
{
	// TODO: check DAG first (one source, one sink, actually a DAG)
	std::string dag_string;
	int sink_index = -1, source_index = -1;

	// Find source and sink
	for (std::size_t i = 0; i < nodes_.size(); i++)
	{
		if (is_source(i)) 
			source_index = i;

		if (is_sink(i))
			sink_index = i;
	}

	if (sink_index >= 0 && source_index >= 0)
	{
		// Add source first
		dag_string += "DAG";
		dag_string += out_edges_for_index(source_index, source_index, sink_index);
		dag_string += " - \n";

		// Add intermediate nodes
		for (std::size_t i = 0; i < nodes_.size(); i++)
		{
			if (i == source_index || i == sink_index)
				continue;

			// add XID type
			dag_string += nodes_[i].type_string() + ":";

			// add XID
			dag_string += nodes_[i].id_string();

			// add out edges
			dag_string += out_edges_for_index(i, source_index, sink_index);
			dag_string += " - \n";
		}

		// Add sink last
		dag_string += nodes_[sink_index].type_string() + ":";
		dag_string += nodes_[sink_index].id_string();
	}
	else
	{
		printf("WARNING: dag_string(): could not find source and/or sink. Returning empty string.\n");
	}


	return dag_string;
}
コード例 #8
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Get the out edges for a node
*
* Get the out edges for a node at index i
*
* @note This function skips the starting node. Use index -1 to get the
* starting node's outgoing edges.
*
* @param i The index of the node
*
* @return The out edges of node i
*/
std::vector<std::size_t>
Graph::get_out_edges(int i) const
{
	std::size_t src_index, sink_index;
	for (std::size_t j = 0; j < nodes_.size(); j++)
	{
		if (is_source(j)) src_index = j;
		if (is_sink(j)) sink_index = j;
	}

	std::size_t real_index;
	if (i == -1) 
		real_index = src_index;
	else
		real_index = index_from_dag_string_index(i, src_index, sink_index);

	std::vector<std::size_t> out_edges;
	for (std::size_t j = 0; j < out_edges_[real_index].size(); j++)
	{
		out_edges.push_back(index_in_dag_string(out_edges_[real_index][j], src_index, sink_index));
	}

	return out_edges;
}
コード例 #9
0
ファイル: dagaddr.cpp プロジェクト: ElRevo/xia-core
/**
* @brief Get the next "intent unit" in the DAG starting at the supplied node
*
* Get the next "intent unit" in the DAG starting at the supplied node. An 
* intent node is a node that can be reached by following the highest priority
* out edge of each node beginning with the source. An intent unit is an intent
* node along with its fallbacks. In the new DAG, the previous intent unit
* becomes the source node.
*
* @param n The node from which to find the next intent unit. n must be an
* 		   intent node.
*
* @return The next intent unit (as a Graph)
*/
Graph
Graph::next_hop(const Node& n)
{
	// first find n and make sure it's an intent unit
	std::size_t nIndex = -1;
	std::size_t curIndex = source_index();
	while (nIndex == -1) {
		if (nodes_[curIndex] == n) {
			nIndex = curIndex;
		} else {
			if (is_sink(curIndex)) {
				printf("Warning: next_hop: n not found or is not an intent node\n");
				return Graph();
			} else {
				curIndex = out_edges_[curIndex][0];
			}
		}
	}
	
	// if n is the DAG's sink, there is no next hop
	if (is_sink(nIndex))
	{
		printf("Warning: next_hop: n is the final intent; no next hop\n");
		return Graph();
	}


	// find the next intent node (the final intent of the new DAG)
	// for now, we we'll only consider CIDs and SIDs to be intent nodes
	std::size_t intentIndex = nIndex;
	while (intentIndex == nIndex || (nodes_[intentIndex].type() != Node::XID_TYPE_CID && nodes_[intentIndex].type() != Node::XID_TYPE_SID))
	{
		if (is_sink(intentIndex)) {
			break;
		}
		intentIndex = out_edges_[intentIndex][0];

	}

	Graph g = Graph();

	// make copies of all the nodes we need in the new Graph with BFS
	std::vector<std::size_t> to_process;
	std::map<std::size_t, std::size_t> old_to_new_map;

	vector_push_back_unique(to_process, nIndex);
	while (to_process.size() > 0)
	{
		curIndex = to_process.back();
		to_process.pop_back();

		// copy this node to the new graph and the mapping
		Node new_node;
		if (curIndex != nIndex) // the start node, n, should be replaced with a dummy source
		{
			new_node = Node(nodes_[curIndex]);
		}
		std::size_t newIndex = g.add_node(new_node);
		old_to_new_map[curIndex] = newIndex;


		// prepare to process its children
		if (curIndex == intentIndex) continue; // but if we've gotten to the new intent node, stop
		for (int i = 0; i < out_edges_[curIndex].size(); i++)
		{
			vector_push_back_unique(to_process, out_edges_[curIndex][i]);
		}
	}
	
	// add edges to the new graph
	for (std::map<std::size_t, std::size_t>::const_iterator it = old_to_new_map.begin(); it != old_to_new_map.end(); ++it)
	{
		std::size_t old_index = (*it).first;
		std::size_t new_index = (*it).second;

		if (old_index == intentIndex) continue; // the new final intent has no out edges

		for (int i = 0; i < out_edges_[old_index].size(); i++)
		{
			g.add_edge(new_index, old_to_new_map[out_edges_[old_index][i]]);
		}
	}

	return g;
}