added splitMinimumSpanningTree that uses DSF
parent
cc2e42aa15
commit
a647c84c16
16
.cproject
16
.cproject
|
@ -317,6 +317,7 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="clean" path="wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="clean" path="wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
|
<buildArguments/>
|
||||||
<buildTarget>clean</buildTarget>
|
<buildTarget>clean</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>true</useDefaultCommand>
|
<useDefaultCommand>true</useDefaultCommand>
|
||||||
|
@ -476,7 +477,6 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testBayesTree.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testBayesTree.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments/>
|
|
||||||
<buildTarget>testBayesTree.run</buildTarget>
|
<buildTarget>testBayesTree.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -484,6 +484,7 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testSymbolicBayesNet.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testSymbolicBayesNet.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
|
<buildArguments/>
|
||||||
<buildTarget>testSymbolicBayesNet.run</buildTarget>
|
<buildTarget>testSymbolicBayesNet.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -491,7 +492,6 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testSymbolicFactorGraph.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testSymbolicFactorGraph.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments/>
|
|
||||||
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
|
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -683,7 +683,6 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testGraph.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testGraph.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments/>
|
|
||||||
<buildTarget>testGraph.run</buildTarget>
|
<buildTarget>testGraph.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -739,6 +738,7 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testSimulated2D.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testSimulated2D.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
|
<buildArguments/>
|
||||||
<buildTarget>testSimulated2D.run</buildTarget>
|
<buildTarget>testSimulated2D.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -786,7 +786,6 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testErrors.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testErrors.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments/>
|
|
||||||
<buildTarget>testErrors.run</buildTarget>
|
<buildTarget>testErrors.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
@ -794,12 +793,19 @@
|
||||||
</target>
|
</target>
|
||||||
<target name="testDSF.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="testDSF.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments/>
|
|
||||||
<buildTarget>testDSF.run</buildTarget>
|
<buildTarget>testDSF.run</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>true</useDefaultCommand>
|
<useDefaultCommand>true</useDefaultCommand>
|
||||||
<runAllBuilders>true</runAllBuilders>
|
<runAllBuilders>true</runAllBuilders>
|
||||||
</target>
|
</target>
|
||||||
|
<target name="testFactorGraph.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
|
<buildCommand>make</buildCommand>
|
||||||
|
<buildArguments>-j2</buildArguments>
|
||||||
|
<buildTarget>testFactorGraph.run</buildTarget>
|
||||||
|
<stopOnError>true</stopOnError>
|
||||||
|
<useDefaultCommand>true</useDefaultCommand>
|
||||||
|
<runAllBuilders>true</runAllBuilders>
|
||||||
|
</target>
|
||||||
<target name="install" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="install" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments>-j2</buildArguments>
|
<buildArguments>-j2</buildArguments>
|
||||||
|
|
24
cpp/DSF.h
24
cpp/DSF.h
|
@ -37,16 +37,19 @@ namespace gtsam {
|
||||||
// constructor
|
// constructor
|
||||||
DSF(const Tree& tree) : Tree(tree) {}
|
DSF(const Tree& tree) : Tree(tree) {}
|
||||||
|
|
||||||
|
// constructor with a list of unconnected keys
|
||||||
|
DSF(const std::list<Key>& keys) : Tree() { BOOST_FOREACH(const Key& key, keys) *this = this->add(key, key); }
|
||||||
|
|
||||||
// create a new singleton, does nothing if already exists
|
// create a new singleton, does nothing if already exists
|
||||||
Self makeSet(const Key& key) const { if (mem(key)) return *this; else return add(key, key); }
|
Self makeSet(const Key& key) const { if (mem(key)) return *this; else return this->add(key, key); }
|
||||||
|
|
||||||
// find the label of the set in which {key} lives
|
// find the label of the set in which {key} lives
|
||||||
Label findSet(const Key& key) const {
|
Label findSet(const Key& key) const {
|
||||||
Key parent = find(key);
|
Key parent = this->find(key);
|
||||||
return parent == key ? key : findSet(parent); }
|
return parent == key ? key : findSet(parent); }
|
||||||
|
|
||||||
// return a new DSF where x and y are in the same set. Kai: the caml implementation is not const, and I followed
|
// return a new DSF where x and y are in the same set. Kai: the caml implementation is not const, and I followed
|
||||||
Self makeUnion(const Key& key1, const Key& key2) { return add(findSet_(key2), findSet_(key1)); }
|
Self makeUnion(const Key& key1, const Key& key2) { return this->add(findSet_(key2), findSet_(key1)); }
|
||||||
|
|
||||||
// create a new singleton with two connected keys
|
// create a new singleton with two connected keys
|
||||||
Self makePair(const Key& key1, const Key& key2) const { return makeSet(key1).makeSet(key2).makeUnion(key1, key2); }
|
Self makePair(const Key& key1, const Key& key2) const { return makeSet(key1).makeSet(key2).makeUnion(key1, key2); }
|
||||||
|
@ -71,7 +74,7 @@ namespace gtsam {
|
||||||
DSF map(boost::function<Key(const Key&)> func) const {
|
DSF map(boost::function<Key(const Key&)> func) const {
|
||||||
DSF t;
|
DSF t;
|
||||||
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
|
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
|
||||||
t.add(func(pair.first), func(pair.second));
|
t = t.add(func(pair.first), func(pair.second));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +108,15 @@ namespace gtsam {
|
||||||
/** equality */
|
/** equality */
|
||||||
bool operator==(const Self& t) const { return (Tree)*this == (Tree)t; }
|
bool operator==(const Self& t) const { return (Tree)*this == (Tree)t; }
|
||||||
|
|
||||||
|
/** inequality */
|
||||||
|
bool operator!=(const Self& t) const { return (Tree)*this != (Tree)t; }
|
||||||
|
|
||||||
// print the object
|
// print the object
|
||||||
void print(std::string& name = "DSF") const { Tree::print(name); }
|
void print(const std::string& name = "DSF") const {
|
||||||
|
std::cout << name << std::endl;
|
||||||
|
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
|
||||||
|
std::cout << (std::string)pair.first << " " << (std::string)pair.second << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -115,12 +125,12 @@ namespace gtsam {
|
||||||
* the root, each parent pointer is made to directly point to it
|
* the root, each parent pointer is made to directly point to it
|
||||||
*/
|
*/
|
||||||
Key findSet_(const Key& key) {
|
Key findSet_(const Key& key) {
|
||||||
Key parent = find(key);
|
Key parent = this->find(key);
|
||||||
if (parent == key)
|
if (parent == key)
|
||||||
return parent;
|
return parent;
|
||||||
else {
|
else {
|
||||||
Key label = findSet_(parent);
|
Key label = findSet_(parent);
|
||||||
*this = add(key, label);
|
*this = this->add(key, label);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "Ordering.h"
|
#include "Ordering.h"
|
||||||
#include "FactorGraph.h"
|
#include "FactorGraph.h"
|
||||||
#include "graph-inl.h"
|
#include "graph-inl.h"
|
||||||
|
#include "DSF.h"
|
||||||
|
|
||||||
#define INSTANTIATE_FACTOR_GRAPH(F) \
|
#define INSTANTIATE_FACTOR_GRAPH(F) \
|
||||||
template class FactorGraph<F>; \
|
template class FactorGraph<F>; \
|
||||||
|
@ -359,6 +360,37 @@ void FactorGraph<Factor>::split(const PredecessorMap<Key>& tree, FactorGraph<Fac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class Factor>
|
||||||
|
std::pair<FactorGraph<Factor>, FactorGraph<Factor> > FactorGraph<Factor>::splitMinimumSpanningTree() const {
|
||||||
|
// create an empty factor graph T (tree) and factor graph C (constraints)
|
||||||
|
FactorGraph<Factor> T;
|
||||||
|
FactorGraph<Factor> C;
|
||||||
|
DSF<Symbol> dsf(keys());
|
||||||
|
|
||||||
|
// while G is nonempty and T is not yet spanning
|
||||||
|
size_t m = nrFactors();
|
||||||
|
for (size_t i=0;i<m;i++) {
|
||||||
|
const sharedFactor& f = factors_[i];
|
||||||
|
|
||||||
|
// retrieve the labels of all the keys
|
||||||
|
set<Symbol> labels;
|
||||||
|
BOOST_FOREACH(const Symbol& key, f->keys())
|
||||||
|
labels.insert(dsf.findSet(key));
|
||||||
|
|
||||||
|
// if that factor connects two different trees, then add it to T
|
||||||
|
if (labels.size() > 1) {
|
||||||
|
T.push_back(f);
|
||||||
|
set<Symbol>::const_iterator it = labels.begin();
|
||||||
|
Symbol root = *it;
|
||||||
|
for (it++; it!=labels.end(); it++)
|
||||||
|
dsf = dsf.makeUnion(root, *it);
|
||||||
|
} else // otherwise add that factor to C
|
||||||
|
C.push_back(f);
|
||||||
|
}
|
||||||
|
return make_pair(T,C);
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/* find factors and remove them from the factor graph: O(n) */
|
/* find factors and remove them from the factor graph: O(n) */
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
@ -381,4 +413,5 @@ FactorGraph<Factor> combine(const FactorGraph<Factor>& fg1, const FactorGraph<Fa
|
||||||
|
|
||||||
return fg;
|
return fg;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // namespace gtsam
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace gtsam {
|
||||||
std::vector<sharedFactor> findAndRemoveFactors(const Symbol& key);
|
std::vector<sharedFactor> findAndRemoveFactors(const Symbol& key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find the minimum spanning tree.
|
* find the minimum spanning tree using boost graph library
|
||||||
*/
|
*/
|
||||||
template<class Key, class Factor2> PredecessorMap<Key> findMinimumSpanningTree() const;
|
template<class Key, class Factor2> PredecessorMap<Key> findMinimumSpanningTree() const;
|
||||||
|
|
||||||
|
@ -129,6 +129,11 @@ namespace gtsam {
|
||||||
template<class Key, class Factor2> void split(const PredecessorMap<Key>& tree,
|
template<class Key, class Factor2> void split(const PredecessorMap<Key>& tree,
|
||||||
FactorGraph<Factor>& Ab1, FactorGraph<Factor>& Ab2) const;
|
FactorGraph<Factor>& Ab1, FactorGraph<Factor>& Ab2) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find the minimum spanning tree using DSF
|
||||||
|
*/
|
||||||
|
std::pair<FactorGraph<Factor>, FactorGraph<Factor> > splitMinimumSpanningTree() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check consistency of the index map, useful for debugging
|
* Check consistency of the index map, useful for debugging
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -70,13 +70,13 @@ headers += BayesTree.h BayesTree-inl.h
|
||||||
headers += ISAM.h ISAM-inl.h GaussianISAM.h
|
headers += ISAM.h ISAM-inl.h GaussianISAM.h
|
||||||
headers += ISAM2.h ISAM2-inl.h GaussianISAM2.h
|
headers += ISAM2.h ISAM2-inl.h GaussianISAM2.h
|
||||||
sources += GaussianISAM.cpp GaussianISAM2.cpp
|
sources += GaussianISAM.cpp GaussianISAM2.cpp
|
||||||
check_PROGRAMS += testGraph testFactorgraph testInference testOrdering
|
check_PROGRAMS += testGraph testFactorGraph testInference testOrdering
|
||||||
check_PROGRAMS += testBayesTree testISAM testGaussianISAM testGaussianISAM2
|
check_PROGRAMS += testBayesTree testISAM testGaussianISAM testGaussianISAM2
|
||||||
testGraph_SOURCES = testGraph.cpp
|
testGraph_SOURCES = testGraph.cpp
|
||||||
testGraph_LDADD = libgtsam.la
|
testGraph_LDADD = libgtsam.la
|
||||||
testFactorgraph_SOURCES = testFactorgraph.cpp
|
testFactorGraph_SOURCES = testFactorgraph.cpp
|
||||||
testInference_SOURCES = testInference.cpp
|
testInference_SOURCES = testInference.cpp
|
||||||
testFactorgraph_LDADD = libgtsam.la
|
testFactorGraph_LDADD = libgtsam.la
|
||||||
testInference_LDADD = libgtsam.la
|
testInference_LDADD = libgtsam.la
|
||||||
testBayesTree_SOURCES = testBayesTree.cpp
|
testBayesTree_SOURCES = testBayesTree.cpp
|
||||||
testBayesTree_LDADD = libgtsam.la
|
testBayesTree_LDADD = libgtsam.la
|
||||||
|
|
|
@ -13,6 +13,7 @@ using namespace boost::assign;
|
||||||
#include <CppUnitLite/TestHarness.h>
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
|
||||||
#include "DSF.h"
|
#include "DSF.h"
|
||||||
|
#include "key.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
|
@ -191,10 +192,10 @@ TEST(DSF, map) {
|
||||||
|
|
||||||
DSFInt actual = dsf.map(&func);
|
DSFInt actual = dsf.map(&func);
|
||||||
DSFInt expected;
|
DSFInt expected;
|
||||||
dsf = dsf.makeSet(15);
|
expected = expected.makeSet(15);
|
||||||
dsf = dsf.makeSet(16);
|
expected = expected.makeSet(16);
|
||||||
dsf = dsf.makeSet(17);
|
expected = expected.makeSet(17);
|
||||||
dsf = dsf.makeUnion(15,16);
|
expected = expected.makeUnion(15,16);
|
||||||
CHECK(actual == expected);
|
CHECK(actual == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +217,26 @@ TEST(DSF, flatten) {
|
||||||
expected = expected.makePair(1, 7);
|
expected = expected.makePair(1, 7);
|
||||||
CHECK(actual == expected);
|
CHECK(actual == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSF, flatten2) {
|
||||||
|
Symbol x1('x',1);
|
||||||
|
Symbol x2('x',2), x3('x',3), x4('x',4);
|
||||||
|
list<Symbol> keys; keys += x1,x2,x3,x4;
|
||||||
|
DSFSymbol dsf(keys);
|
||||||
|
dsf = dsf.makeUnion(x1,x2);
|
||||||
|
dsf = dsf.makeUnion(x3,x4);
|
||||||
|
dsf = dsf.makeUnion(x1,x3);
|
||||||
|
|
||||||
|
CHECK(dsf != dsf.flatten());
|
||||||
|
|
||||||
|
DSFSymbol expected2;
|
||||||
|
expected2 = expected2.makePair(x1, x2);
|
||||||
|
expected2 = expected2.makePair(x1, x3);
|
||||||
|
expected2 = expected2.makePair(x1, x4);
|
||||||
|
CHECK(expected2 == dsf.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -19,31 +19,6 @@ using namespace gtsam;
|
||||||
|
|
||||||
typedef boost::shared_ptr<SymbolicFactorGraph> shared;
|
typedef boost::shared_ptr<SymbolicFactorGraph> shared;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
// This function is not done yet
|
|
||||||
// It needs a test to check whether a factor is in the same component
|
|
||||||
// This can be done with a disjoint-set data structure (Union&Find) to keep
|
|
||||||
// track of which vertices are in which components.
|
|
||||||
std::pair<shared, shared> splitMinimumSpanningTree(SymbolicFactorGraph& G) {
|
|
||||||
// create an empty factor graph T (tree) and factor graph C (constraints)
|
|
||||||
shared T(new SymbolicFactorGraph);
|
|
||||||
shared C(new SymbolicFactorGraph);
|
|
||||||
|
|
||||||
// while G is nonempty and T is not yet spanning
|
|
||||||
size_t m = G.nrFactors();
|
|
||||||
for (size_t i=0;i<m;i++) {
|
|
||||||
// remove an factor with minimum weight from G
|
|
||||||
const SymbolicFactorGraph::sharedFactor& f = G[i];
|
|
||||||
G.remove(i);
|
|
||||||
// if that factor connects two different trees, then add it to T
|
|
||||||
if (true) // TODO: test whether f is in the same component
|
|
||||||
T->push_back(f);
|
|
||||||
else // otherwise add that factor to C
|
|
||||||
C->push_back(f);
|
|
||||||
}
|
|
||||||
return std::pair<shared, shared>(T,C);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST( FactorGraph, splitMinimumSpanningTree )
|
TEST( FactorGraph, splitMinimumSpanningTree )
|
||||||
{
|
{
|
||||||
|
@ -55,18 +30,18 @@ TEST( FactorGraph, splitMinimumSpanningTree )
|
||||||
G.push_factor("x2", "x4");
|
G.push_factor("x2", "x4");
|
||||||
G.push_factor("x3", "x4");
|
G.push_factor("x3", "x4");
|
||||||
|
|
||||||
shared T, C;
|
SymbolicFactorGraph T, C;
|
||||||
boost::tie(T, C) = splitMinimumSpanningTree(G);
|
boost::tie(T, C) = G.splitMinimumSpanningTree();
|
||||||
|
|
||||||
SymbolicFactorGraph expectedT, expectedC;
|
SymbolicFactorGraph expectedT, expectedC;
|
||||||
expectedT.push_factor("x1", "x2");
|
expectedT.push_factor("x1", "x2");
|
||||||
expectedT.push_factor("x1", "x3");
|
expectedT.push_factor("x1", "x3");
|
||||||
expectedT.push_factor("x1", "x4");
|
expectedT.push_factor("x1", "x4");
|
||||||
expectedT.push_factor("x2", "x3");
|
expectedC.push_factor("x2", "x3");
|
||||||
expectedT.push_factor("x2", "x4");
|
expectedC.push_factor("x2", "x4");
|
||||||
expectedT.push_factor("x3", "x4");
|
expectedC.push_factor("x3", "x4");
|
||||||
CHECK(assert_equal(expectedT,*T));
|
CHECK(assert_equal(expectedT,T));
|
||||||
CHECK(assert_equal(expectedC,*C));
|
CHECK(assert_equal(expectedC,C));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
Loading…
Reference in New Issue