fixes1
parent
43af7c4ae4
commit
0d41941cda
|
@ -11,20 +11,21 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
using MFAS::KeyPair;
|
|
||||||
using std::map;
|
using std::map;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using std::unordered_map;
|
using std::unordered_map;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
using std::unordered_set;
|
||||||
|
|
||||||
// A node in the graph.
|
// A node in the graph.
|
||||||
struct GraphNode {
|
struct GraphNode {
|
||||||
double inWeightSum; // Sum of absolute weights of incoming edges.
|
double inWeightSum; // Sum of absolute weights of incoming edges
|
||||||
double outWeightSum; // Sum of absolute weights of outgoing edges.
|
double outWeightSum; // Sum of absolute weights of outgoing edges
|
||||||
vector<Key> inNeighbors; // Nodes from which there is an incoming edge.
|
unordered_set<Key> inNeighbors; // Nodes from which there is an incoming edge
|
||||||
vector<Key> outNeighbors; // Nodes to which there is an outgoing edge.
|
unordered_set<Key> outNeighbors; // Nodes to which there is an outgoing edge
|
||||||
|
|
||||||
// Heuristic for the node that is to select nodes in MFAS.
|
// Heuristic for the node that is to select nodes in MFAS.
|
||||||
double heuristic() { return (outWeightSum + 1) / (inWeightSum + 1); }
|
double heuristic() { return (outWeightSum + 1) / (inWeightSum + 1); }
|
||||||
|
@ -33,24 +34,27 @@ struct GraphNode {
|
||||||
// A graph is a map from key to GraphNode. This function returns the graph from
|
// A graph is a map from key to GraphNode. This function returns the graph from
|
||||||
// the edgeWeights between keys.
|
// the edgeWeights between keys.
|
||||||
unordered_map<Key, GraphNode> graphFromEdges(
|
unordered_map<Key, GraphNode> graphFromEdges(
|
||||||
const map<KeyPair, double>& edgeWeights) {
|
const map<MFAS::KeyPair, double>& edgeWeights) {
|
||||||
unordered_map<Key, GraphNode> graph;
|
unordered_map<Key, GraphNode> graph;
|
||||||
|
|
||||||
for (const auto& [edge, weight] : edgeWeights) {
|
for (const auto& edgeWeight : edgeWeights) {
|
||||||
// The weights can be either negative or positive. The direction of the edge
|
// The weights can be either negative or positive. The direction of the edge
|
||||||
// is the direction of positive weight. This means that the edges is from
|
// is the direction of positive weight. This means that the edges is from
|
||||||
// edge.first -> edge.second if weight is positive and edge.second ->
|
// edge.first -> edge.second if weight is positive and edge.second ->
|
||||||
// edge.first if weight is negative.
|
// edge.first if weight is negative.
|
||||||
|
MFAS::KeyPair& edge = edgeWeight.first;
|
||||||
|
double& weight = edgeWeight.second;
|
||||||
|
|
||||||
Key edgeSource = weight >= 0 ? edge.first : edge.second;
|
Key edgeSource = weight >= 0 ? edge.first : edge.second;
|
||||||
Key edgeDest = weight >= 0 ? edge.second : edge.first;
|
Key edgeDest = weight >= 0 ? edge.second : edge.first;
|
||||||
|
|
||||||
// Update the in weight and neighbors for the destination.
|
// Update the in weight and neighbors for the destination.
|
||||||
graph[edgeDest].inWeightSum += std::abs(weight);
|
graph[edgeDest].inWeightSum += std::abs(weight);
|
||||||
graph[edgeDest].inNeighbors.push_back(edgeSource);
|
graph[edgeDest].inNeighbors.insert(edgeSource);
|
||||||
|
|
||||||
// Update the out weight and neighbors for the source.
|
// Update the out weight and neighbors for the source.
|
||||||
graph[edgeSource].outWeightSum += std::abs(weight);
|
graph[edgeSource].outWeightSum += std::abs(weight);
|
||||||
graph[edgeSource].outNeighbors.push_back(edgeDest);
|
graph[edgeSource].outNeighbors.insert(edgeDest);
|
||||||
}
|
}
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
@ -58,36 +62,37 @@ unordered_map<Key, GraphNode> graphFromEdges(
|
||||||
// Selects the next node in the ordering from the graph.
|
// Selects the next node in the ordering from the graph.
|
||||||
Key selectNextNodeInOrdering(const unordered_map<Key, GraphNode>& graph) {
|
Key selectNextNodeInOrdering(const unordered_map<Key, GraphNode>& graph) {
|
||||||
// Find the root nodes in the graph.
|
// Find the root nodes in the graph.
|
||||||
for (const auto& [key, node] : graph) {
|
for (const auto& keyNode : graph) {
|
||||||
// It is a root node if the inWeightSum is close to zero.
|
// It is a root node if the inWeightSum is close to zero.
|
||||||
if (node.inWeightSum < 1e-8) {
|
if (keyNode.second.inWeightSum < 1e-8) {
|
||||||
// TODO(akshay-krishnan) if there are multiple roots, it is better to
|
// TODO(akshay-krishnan) if there are multiple roots, it is better to
|
||||||
// choose the one with highest heuristic. This is missing in the 1dsfm
|
// choose the one with highest heuristic. This is missing in the 1dsfm
|
||||||
// solution.
|
// solution.
|
||||||
return key;
|
return keyNode.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If there are no root nodes, return the node with the highest heuristic.
|
// If there are no root nodes, return the node with the highest heuristic.
|
||||||
return std::max_element(graph.begin(), graph.end(),
|
return std::max_element(graph.begin(), graph.end(),
|
||||||
[](const std::pair<Key, GraphNode>& node1,
|
[](const std::pair<Key, GraphNode>& keyNode1,
|
||||||
const std::pair<Key, GraphNode>& node2) {
|
const std::pair<Key, GraphNode>& keyNode2) {
|
||||||
return node1.second.heuristic() <
|
return keyNode1.second.heuristic() <
|
||||||
node2.second.heuristic();
|
keyNode2.second.heuristic();
|
||||||
})
|
})
|
||||||
->first;
|
->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the absolute weight of the edge between node1 and node2.
|
// Returns the absolute weight of the edge between node1 and node2.
|
||||||
double absWeightOfEdge(const Key node1, const Key node2,
|
double absWeightOfEdge(const Key node1, const Key node2,
|
||||||
const map<KeyPair, double>& edgeWeights) {
|
const map<MFAS::KeyPair, double>& edgeWeights) {
|
||||||
// Check the direction of the edge before returning.
|
// Check the direction of the edge before returning.
|
||||||
return edgeWeights_.find(KeyPair(node1, node2)) != edgeWeights_.end()
|
return edgeWeights_.find(MFAS::KeyPair(node1, node2)) != edgeWeights_.end()
|
||||||
? std::abs(edgeWeights_.at(KeyPair(node1, node2)))
|
? std::abs(edgeWeights_.at(MFAS::KeyPair(node1, node2)))
|
||||||
: std::abs(edgeWeights_.at(KeyPair(node2, node1)));
|
: std::abs(edgeWeights_.at(MFAS::KeyPair(node2, node1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a node from the graph and updates edge weights of its neighbors.
|
// Removes a node from the graph and updates edge weights of its neighbors.
|
||||||
void removeNodeFromGraph(const Key node, const map<KeyPair, double> edgeWeights,
|
void removeNodeFromGraph(const Key node,
|
||||||
|
const map<MFAS::KeyPair, double> edgeWeights,
|
||||||
unordered_map<Key, GraphNode>& graph) {
|
unordered_map<Key, GraphNode>& graph) {
|
||||||
// Update the outweights and outNeighbors of node's inNeighbors
|
// Update the outweights and outNeighbors of node's inNeighbors
|
||||||
for (const Key neighbor : graph[node].inNeighbors) {
|
for (const Key neighbor : graph[node].inNeighbors) {
|
||||||
|
@ -95,12 +100,12 @@ void removeNodeFromGraph(const Key node, const map<KeyPair, double> edgeWeights,
|
||||||
// (choice, *it) with a negative weight
|
// (choice, *it) with a negative weight
|
||||||
graph[neighbor].outWeightSum -=
|
graph[neighbor].outWeightSum -=
|
||||||
absWeightOfEdge(node, neighbor, edgeWeights);
|
absWeightOfEdge(node, neighbor, edgeWeights);
|
||||||
graph[neighbor].outNeighbors.erase(graph[neighbor].outNeighbors.find(node));
|
graph[neighbor].outNeighbors.erase(node);
|
||||||
}
|
}
|
||||||
// Update the inWeights and inNeighbors of node's outNeighbors
|
// Update the inWeights and inNeighbors of node's outNeighbors
|
||||||
for (const Key neighbor : graph[node].outNeighbors) {
|
for (const Key neighbor : graph[node].outNeighbors) {
|
||||||
graph[neighbor].inWeightSum -= absWeightOfEdge(node, neighbor, edgeWeights);
|
graph[neighbor].inWeightSum -= absWeightOfEdge(node, neighbor, edgeWeights);
|
||||||
graph[neighbor].inNeighbors.erase(graph[neighbor].inNeighbors.find(node));
|
graph[neighbor].inNeighbors.erase(node);
|
||||||
}
|
}
|
||||||
// Erase node.
|
// Erase node.
|
||||||
graph.erase(node);
|
graph.erase(node);
|
||||||
|
@ -148,10 +153,10 @@ std::map<KeyPair, double> MFAS::computeOutlierWeights() const {
|
||||||
|
|
||||||
map<KeyPair, double> outlierWeights;
|
map<KeyPair, double> outlierWeights;
|
||||||
// Check if the direction of each edge is consistent with the ordering.
|
// Check if the direction of each edge is consistent with the ordering.
|
||||||
for (const auto& [edge, weight] : edgeWeights_) {
|
for (const auto& edgeWeight : edgeWeights_) {
|
||||||
// Find edge source and destination.
|
// Find edge source and destination.
|
||||||
Key source = edge.first;
|
Key source = edgeWeight.first.first;
|
||||||
Key dest = edge.second;
|
Key dest = edgeWeight.first.second;
|
||||||
if (weight < 0) {
|
if (weight < 0) {
|
||||||
std::swap(source, dest);
|
std::swap(source, dest);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +164,7 @@ std::map<KeyPair, double> MFAS::computeOutlierWeights() const {
|
||||||
// If the direction is not consistent with the ordering (i.e dest occurs
|
// If the direction is not consistent with the ordering (i.e dest occurs
|
||||||
// before src), it is an outlier edge, and has non-zero outlier weight.
|
// before src), it is an outlier edge, and has non-zero outlier weight.
|
||||||
if (orderingPositions.at(dest) < orderingPositions.at(source)) {
|
if (orderingPositions.at(dest) < orderingPositions.at(source)) {
|
||||||
outlierWeights[edge] = std::abs(weight);
|
outlierWeights[edge] = std::abs(edgeWeight.second);
|
||||||
} else {
|
} else {
|
||||||
outlierWeights[edge] = 0;
|
outlierWeights[edge] = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue