Merge remote-tracking branch 'svn/trunk' into NLO

Conflicts:
	examples/Pose2SLAMExample_advanced.cpp
release/4.3a0
Richard Roberts 2012-05-14 18:35:15 +00:00
commit 88f5e3d9b6
205 changed files with 14499 additions and 1517 deletions

393
.cproject
View File

@ -362,6 +362,14 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testGaussianFactor.run" path="linear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testGaussianFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -388,7 +396,6 @@
</target>
<target name="tests/testBayesTree.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testBayesTree.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -396,7 +403,6 @@
</target>
<target name="testBinaryBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testBinaryBayesNet.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -444,7 +450,6 @@
</target>
<target name="testSymbolicBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicBayesNet.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -452,7 +457,6 @@
</target>
<target name="tests/testSymbolicFactor.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testSymbolicFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -460,7 +464,6 @@
</target>
<target name="testSymbolicFactorGraph.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -476,20 +479,11 @@
</target>
<target name="tests/testBayesTree" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testBayesTree</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testGaussianFactor.run" path="linear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testGaussianFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -516,6 +510,7 @@
</target>
<target name="testGraph.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testGraph.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -587,6 +582,7 @@
</target>
<target name="testInference.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testInference.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -594,6 +590,7 @@
</target>
<target name="testGaussianFactor.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testGaussianFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -601,6 +598,7 @@
</target>
<target name="testJunctionTree.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testJunctionTree.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -608,6 +606,7 @@
</target>
<target name="testSymbolicBayesNet.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicBayesNet.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -615,6 +614,7 @@
</target>
<target name="testSymbolicFactorGraph.run" path="tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -684,22 +684,6 @@
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose2.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose3.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="CppUnitLite" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -716,6 +700,22 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose2.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose3.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="spqr_mini" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -740,26 +740,18 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="nonlinear.testValues.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>all</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>nonlinear.testValues.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="nonlinear.testOrdering.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>nonlinear.testOrdering.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -796,18 +788,26 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="nonlinear.testValues.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="all" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>nonlinear.testValues.run</buildTarget>
<buildArguments>-j2</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="nonlinear.testOrdering.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>nonlinear.testOrdering.run</buildTarget>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -844,30 +844,14 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="install" path="wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check" path="build/gtsam/discrete" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>install</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildArguments>-j5</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="vSFMexample.run" path="build/examples/vSLAMexample" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -1044,14 +1028,6 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="SimpleRotation.run" path="examples" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>SimpleRotation.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="linear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -1142,7 +1118,6 @@
</target>
<target name="testErrors.run" path="linear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testErrors.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1598,6 +1573,7 @@
</target>
<target name="testSimulated2DOriented.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated2DOriented.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1637,6 +1613,7 @@
</target>
<target name="testSimulated2D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated2D.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1644,6 +1621,7 @@
</target>
<target name="testSimulated3D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated3D.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1657,6 +1635,14 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testVector.run" path="build/gtsam/base" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testVector.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testVectorValues.run" path="build/gtsam/linear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -1817,6 +1803,14 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="UGM_small.run" path="build/examples" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>UGM_small.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="build/slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -1827,6 +1821,7 @@
</target>
<target name="tests/testGaussianISAM2" path="build/slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testGaussianISAM2</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1848,6 +1843,102 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="timeRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>timeRot3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCal3_S2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCal3_S2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testSimpleCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testSimpleCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testHomography2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testHomography2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCalibratedCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCalibratedCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPoint2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPoint2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="install" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -2031,98 +2122,134 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="wrap_gtsam" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot3.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap_gtsam</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="verbose wrap_gtsam" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot2.run</buildTarget>
<buildArguments>VERBOSE=1</buildArguments>
<buildTarget>wrap_gtsam</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="Generate DEB Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildTarget>-G DEB</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="Generate RPM Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildTarget>-G RPM</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="Generate TGZ Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildTarget>-G TGZ</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="Generate TGZ Source Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildTarget>--config CPackSourceConfig.cmake</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check.discrete" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>check.discrete</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="wrap_gtsam_unstable" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose3.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap_gtsam_unstable</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="timeRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.wrap" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>timeRot3.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.dynamics_unstable" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.dynamics_unstable</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCal3_S2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.slam_unstable" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCal3_S2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.slam_unstable</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testSimpleCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.base_unstable" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testSimpleCamera.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.base_unstable</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testHomography2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testSpirit.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testHomography2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testSpirit.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCalibratedCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testWrap.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCalibratedCamera.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testWrap.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="wrap_gtsam" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap_gtsam</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPoint2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPoint2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -2166,46 +2293,6 @@
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap.testSpirit.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap.testSpirit.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap.testWrap.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap.testWrap.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check.wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>check.wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap_gtsam" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap_gtsam</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cproject>

View File

@ -7,10 +7,10 @@ set (GTSAM_VERSION_MINOR 9)
set (GTSAM_VERSION_PATCH 0)
# Set the default install path to home
set (CMAKE_INSTALL_PREFIX ${HOME} CACHE DOCSTRING "Install prefix for library")
#set (CMAKE_INSTALL_PREFIX ${HOME} CACHE PATH "Install prefix for library")
# Use macros for creating tests/timing scripts
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake")
include(GtsamTesting)
include(GtsamPrinting)
@ -19,12 +19,8 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
endif()
# Default to Debug mode
if(NOT FIRST_PASS_DONE AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
"Choose the type of build, options are: None Debug Release Timing Profiling RelWithDebInfo."
FORCE)
endif()
# Load build type flags and default to Debug mode
include(GtsamBuildTypes)
# Check build types
if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 2.8 OR ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_EQUAL 2.8)
@ -41,33 +37,29 @@ if( NOT cmake_build_type_tolower STREQUAL ""
message(FATAL_ERROR "Unknown build type \"${CMAKE_BUILD_TYPE}\". Allowed values are None, Debug, Release, Timing, Profiling, RelWithDebInfo (case-insensitive).")
endif()
# Add debugging flags but only on the first pass
if(NOT FIRST_PASS_DONE)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-inline -Wall" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-inline -Wall" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -fno-inline -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -fno-inline -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during relwithdebinfo builds." FORCE)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall" CACHE STRING "Flags used by the compiler during release builds." FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall" CACHE STRING "Flags used by the compiler during release builds." FORCE)
set(CMAKE_C_FLAGS_TIMING "${CMAKE_C_FLAGS_RELEASE} -DENABLE_TIMING" CACHE STRING "Flags used by the compiler during timing builds." FORCE)
set(CMAKE_CXX_FLAGS_TIMING "${CMAKE_CXX_FLAGS_RELEASE} -DENABLE_TIMING" CACHE STRING "Flags used by the compiler during timing builds." FORCE)
mark_as_advanced(CMAKE_C_FLAGS_TIMING CMAKE_CXX_FLAGS_TIMING)
set(CMAKE_C_FLAGS_PROFILING "-g -O2 -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during profiling builds." FORCE)
set(CMAKE_CXX_FLAGS_PROFILING "-g -O2 -Wall -DNDEBUG" CACHE STRING "Flags used by the compiler during profiling builds." FORCE)
mark_as_advanced(CMAKE_C_FLAGS_PROFILING CMAKE_CXX_FLAGS_PROFILING)
endif()
# Configurable Options
option(GTSAM_BUILD_TESTS "Enable/Disable building of tests" ON)
option(GTSAM_BUILD_TIMING "Enable/Disable building of timing scripts" ON)
option(GTSAM_BUILD_EXAMPLES "Enable/Disable building of examples" ON)
option(GTSAM_BUILD_WRAP "Enable/Disable building of matlab wrap utility (necessary for matlab interface)" ON)
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices" OFF)
option(GTSAM_BUILD_TESTS "Enable/Disable building of tests" ON)
option(GTSAM_BUILD_TIMING "Enable/Disable building of timing scripts" ON)
option(GTSAM_BUILD_EXAMPLES "Enable/Disable building of examples" ON)
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" OFF)
option(GTSAM_BUILD_WRAP "Enable/Disable building of matlab wrap utility (necessary for matlab interface)" ON)
option(GTSAM_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam" ON)
option(GTSAM_BUILD_STATIC_LIBRARY "Enable/Disable building of a static version of gtsam" ON)
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices" OFF)
option(GTSAM_BUILD_CONVENIENCE_LIBRARIES "Enable/Disable use of convenience libraries for faster development rebuilds, but slower install" ON)
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" ON)
option(GTSAM_INSTALL_MATLAB_EXAMPLES "Enable/Disable installation of matlab examples" ON)
option(GTSAM_INSTALL_MATLAB_TESTS "Enable/Disable installation of matlab tests" ON)
option(GTSAM_INSTALL_WRAP "Enable/Disable installation of wrap utility" ON)
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" ON)
option(GTSAM_INSTALL_MATLAB_EXAMPLES "Enable/Disable installation of matlab examples" ON)
option(GTSAM_INSTALL_MATLAB_TESTS "Enable/Disable installation of matlab tests" ON)
option(GTSAM_INSTALL_WRAP "Enable/Disable installation of wrap utility" ON)
# Flags for choosing default packaging tools
set(CPACK_SOURCE_GENERATOR "TGZ" CACHE STRING "CPack Default Source Generator")
set(CPACK_GENERATOR "TGZ" CACHE STRING "CPack Default Binary Generator")
# Sanity check building of libraries
if (NOT GTSAM_BUILD_SHARED_LIBRARY AND NOT GTSAM_BUILD_STATIC_LIBRARY)
message(FATAL_ERROR "Both shared and static version of GTSAM library disabled - need to choose at least one!")
endif()
# Add the Quaternion Build Flag if requested
if (GTSAM_USE_QUATERNIONS)
@ -80,6 +72,10 @@ endif(GTSAM_USE_QUATERNIONS)
# FIXME: can't add install dependencies, so libraries never get built
#set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)
# Alternative version to keep tests from building during make install
# Use the EXCLUDE_FROM_ALL property on test executables
option(GTSAM_ENABLE_INSTALL_TEST_FIX "Enable/Disable fix to remove dependency of tests on 'all' target" ON)
# Pull in infrastructure
if (GTSAM_BUILD_TESTS)
enable_testing()
@ -87,10 +83,6 @@ if (GTSAM_BUILD_TESTS)
include(CTest)
endif()
# Enable make check (http://www.cmake.org/Wiki/CMakeEmulateMakeCheck)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
add_custom_target(timing)
# Find boost
find_package(Boost 1.40 COMPONENTS serialization REQUIRED)
@ -122,24 +114,52 @@ if (GTSAM_BUILD_EXAMPLES)
add_subdirectory(examples)
endif(GTSAM_BUILD_EXAMPLES)
# Mark that first pass is done
set(FIRST_PASS_DONE true CACHE BOOL "Internally used to mark whether cmake has been run multiple times")
mark_as_advanced(FIRST_PASS_DONE)
# Build gtsam_unstable
if (GTSAM_BUILD_UNSTABLE)
add_subdirectory(gtsam_unstable)
endif(GTSAM_BUILD_UNSTABLE)
# Set up CPack
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GTSAM")
set(CPACK_PACKAGE_VENDOR "Frank Dellaert, Georgia Institute of Technology")
set(CPACK_PACKAGE_CONTACT "Frank Dellaert, dellaert@cc.gatech.edu")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR ${GTSAM_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${GTSAM_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${GTSAM_VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
set(CPACK_INSTALLED_DIRECTORIES "doc;.") # Include doc directory
set(CPACK_SOURCE_IGNORE_FILES "/build;/\\\\.;/makedoc.sh$")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}")
#set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-aspn${GTSAM_VERSION_PATCH}") # Used for creating ASPN tarballs
# Record the root dir for gtsam - needed during external builds, e.g., ROS
set(GTSAM_SOURCE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
message(STATUS "GTSAM_SOURCE_ROOT_DIR: [${GTSAM_SOURCE_ROOT_DIR}]")
# print configuration variables
message(STATUS "===============================================================")
message(STATUS "================ Configuration Options ======================")
message(STATUS "Build flags ")
print_config_flag(${GTSAM_BUILD_TIMING} "Build Timing scripts ")
print_config_flag(${GTSAM_BUILD_EXAMPLES} "Build Examples ")
print_config_flag(${GTSAM_BUILD_TESTS} "Build Tests ")
print_config_flag(${GTSAM_BUILD_WRAP} "Build Wrap ")
print_config_flag(${GTSAM_BUILD_CONVENIENCE_LIBRARIES} "Build Convenience Libraries")
print_config_flag(${GTSAM_BUILD_TIMING} "Build Timing scripts ")
print_config_flag(${GTSAM_BUILD_EXAMPLES} "Build Examples ")
print_config_flag(${GTSAM_BUILD_TESTS} "Build Tests ")
print_config_flag(${GTSAM_BUILD_WRAP} "Build Wrap ")
print_config_flag(${GTSAM_BUILD_SHARED_LIBRARY} "Build shared GTSAM Library ")
print_config_flag(${GTSAM_BUILD_STATIC_LIBRARY} "Build static GTSAM Library ")
print_config_flag(${GTSAM_BUILD_CONVENIENCE_LIBRARIES} "Build Convenience Libraries ")
print_config_flag(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable ")
print_config_flag(${GTSAM_ENABLE_INSTALL_TEST_FIX} "Tests excluded from all target ")
string(TOUPPER "${CMAKE_BUILD_TYPE}" cmake_build_type_toupper)
message(STATUS " Build type : ${CMAKE_BUILD_TYPE}")
message(STATUS " C compilation flags : ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${cmake_build_type_toupper}}")
message(STATUS " C++ compilation flags : ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${cmake_build_type_toupper}}")
message(STATUS "Packaging flags ")
message(STATUS " CPack Source Generator : ${CPACK_SOURCE_GENERATOR}")
message(STATUS " CPack Generator : ${CPACK_GENERATOR}")
message(STATUS "GTSAM flags ")
print_config_flag(${GTSAM_USE_QUATERNIONS} "Quaternions as default Rot3")
@ -150,19 +170,5 @@ print_config_flag(${GTSAM_INSTALL_MATLAB_TESTS} "Install matlab tests
print_config_flag(${GTSAM_INSTALL_WRAP} "Install wrap utility ")
message(STATUS "===============================================================")
# Set up CPack
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GTSAM")
set(CPACK_PACKAGE_VENDOR "Frank Dellaert, Georgia Institute of Technology")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR ${GTSAM_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${GTSAM_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${GTSAM_VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
set(CPACK_INSTALLED_DIRECTORIES "doc" ".") # Include doc directory
set(CPACK_SOURCE_IGNORE_FILES "/build;/\\\\.;/makedoc.sh$")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}")
#set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-aspn${GTSAM_VERSION_PATCH}") # Used for creating ASPN tarballs
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_GENERATOR "TGZ")
# Include CPack *after* all flags
include(CPack)

View File

@ -102,7 +102,7 @@ SimpleString StringFrom (long value)
SimpleString StringFrom (double value)
{
char buffer [DEFAULT_SIZE];
sprintf (buffer, "%lf", value);
sprintf (buffer, "%lg", value);
return SimpleString(buffer);
}

View File

@ -32,7 +32,7 @@ PROJECT_NAME = gtsam
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.9.3
PROJECT_NUMBER = 1.9.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
@ -641,10 +641,15 @@ WARN_LOGFILE =
INPUT = gtsam/base \
gtsam/geometry \
gtsam/inference \
gtsam/discrete \
gtsam/linear \
gtsam/nonlinear \
gtsam/slam \
gtsam
gtsam \
gtsam_unstable/slam \
gtsam_unstable/base \
gtsam_unstable/geometry \
gtsam_unstable/dynamics \
gtsam_unstable
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

41
README
View File

@ -11,7 +11,10 @@ What is GTSAM ?
GTSAM is not (yet) open source: See COPYING & LICENSE
Please see USAGE for an example on how to use GTSAM.
The code is organized according to the following directory structure:
The core GTSAM code within the folder gtsam, with source, headers, and
unit tests. After building, this will generate a single library "libgtsam"
The libgtsam code is organized according to the following directory structure:
3rdparty local copies of third party libraries - Eigen3 and CCOLAMD
base provides some base Math and data structures, as well as test-related utilities
@ -20,7 +23,13 @@ The code is organized according to the following directory structure:
linear inference specialized to Gaussian linear case, GaussianFactorGraph etc...
nonlinear non-linear factor graphs and non-linear optimization
slam SLAM and visual SLAM application code
Additionally, in the SVN development version of GTSAM, there is an area for
unstable code directly under development in the folder gtsam_unstable, which contains
a directory structuring mirroring the libgtsam structure as necessary. This section produces
a single library "libgtsam_unstable". Building of gtsam_unstable is disabled by default, see
CMake configuration options for information on enabling building.
This library contains unchanged copies of two third party libraries, with documentation
of licensing in LICENSE and as follows:
- CCOLAMD 2.73: Tim Davis' constrained column approximate minimum degree ordering library
@ -28,11 +37,10 @@ of licensing in LICENSE and as follows:
- Licenced under LGPL v2.1, provided in gtsam/3rdparty/CCOLAMD/Doc/lesser.txt
- Eigen 3.0.5: General C++ matrix and linear algebra library
- Licenced under LGPL v3, provided in gtsam/3rdparty/Eigen/COPYING.LGPL
All of the above contain code and tests, and produce a single library libgtsam.
After this is built, you can also run the more involved tests, which test the entire library:
tests more involved tests that depend on slam
tests More involved unit tests that depend on slam
examples Demo applications as a tutorial for using gtsam
cmake CMake scripts used within the library, as well as for finding GTSAM by dependent projects
@ -158,6 +166,16 @@ $] cmake -DGTSAM_BUILD_CONVENIENCE_LIBRARIES:OPTION=ON ..
link all of the tests at once. This option is best for users of GTSAM,
as it avoids rebuilding the entirety of gtsam an extra time.
GTSAM_BUILD_UNSTABLE: Enable build and install for libgtsam_unstable library.
Set with the command line as follows:
$] cmake -DGTSAM_BUILD_UNSTABLE:OPTION=ON ..
ON When enabled, libgtsam_unstable will be built and installed with the
same options as libgtsam. In addition, if tests are enabled, the
unit tests will be built as well. The Matlab toolbox will also
be generated if the matlab toolbox is enabled, installing into a
folder called "gtsam_unstable".
OFF (Default) If disabled, no gtsam_unstable code will be included in build or install.
CMAKE_BUILD_TYPE: We support several build configurations for GTSAM (case insensitive)
Debug (default) All error checking options on, no optimization. Use for development.
Release Optimizations turned on, no debug symbols.
@ -176,12 +194,13 @@ Running "make install" will install the library to the prefix location.
Check
As with autotools, "make check" will build and run all of the tests. You can also
run "make timing" to build all of the timing scripts. To run check on a particular
subsection, there is a convention of "make check.[subfolder]", so to run just the
geometry tests, run "make check.geometry". Individual tests can be run by
appending ".run" to the name of the test, for example, to run testMatrix,
run "make testMatrix.run".
As with autotools, "make check" will build and run all of the tests. Note that the
tests will only be built when using the "check" targets, to prevent "make install" from
building the tests unnecessarily. You can also run "make timing" to build all of
the timing scripts. To run check on a particular subsection, there is a convention
of "make check.[subfolder]", so to run just the geometry tests,
run "make check.geometry". Individual tests can be run by appending ".run" to the
name of the test, for example, to run testMatrix, run "make testMatrix.run".
The make target "wrap" will build the wrap binary, and the "wrap_gtsam" target will
generate code for the toolbox. By default, the toolbox will be created and installed

View File

@ -65,16 +65,16 @@ int main(int argc, char** argv) {
Ordering::shared_ptr ordering = graph->orderingCOLAMD(*initial);
/* 4.2.2 set up solver and optimize */
LevenbergMarquardtParams params;
params.relativeErrorTol = 1e-15;
params.absoluteErrorTol = 1e-15;
pose2SLAM::Values result = *LevenbergMarquardtOptimizer(graph, initial, params, ordering).optimized();
NonlinearOptimizationParameters::shared_ptr params = NonlinearOptimizationParameters::newDecreaseThresholds(1e-15, 1e-15);
Optimizer optimizer(graph, initial, ordering, params);
Optimizer optimizer_result = optimizer.levenbergMarquardt();
pose2SLAM::Values result = *optimizer_result.values();
result.print("final result");
/* Get covariances */
GaussianMultifrontalSolver solver(*graph->linearize(result, *ordering));
Matrix covariance1 = solver.marginalCovariance(ordering->at(PoseKey(1)));
Matrix covariance2 = solver.marginalCovariance(ordering->at(PoseKey(1)));
Matrix covariance1 = optimizer_result.marginalCovariance(PoseKey(1));
Matrix covariance2 = optimizer_result.marginalCovariance(PoseKey(2));
print(covariance1, "Covariance1");
print(covariance2, "Covariance2");

View File

@ -26,4 +26,10 @@ Visual SLAM
The directory vSLAMexample includes 2 simple examples using GTSAM:
- vSFMexample using visualSLAM in for structure-from-motion (SFM), and
- vISAMexample using visualSLAM and ISAM for incremental SLAM updates
See the separate README file there.
See the separate README file there.
Undirected Graphical Models (UGM)
=================================
The best representation for a Markov Random Field is a factor graph :-)
This is illustrated with some discrete examples from the UGM MATLAB toolbox, which
can be found at http://www.di.ens.fr/~mschmidt/Software/UGM

74
examples/UGM_small.cpp Normal file
View File

@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file small.cpp
* @brief UGM (undirected graphical model) examples: small
* @author Frank Dellaert
*
* See http://www.di.ens.fr/~mschmidt/Software/UGM/small.html
*/
#include <gtsam/discrete/DiscreteFactorGraph.h>
#include <gtsam/discrete/DiscreteSequentialSolver.h>
using namespace std;
using namespace gtsam;
int main(int argc, char** argv) {
// We will assume 2-state variables, where, to conform to the "small" example
// we have 0 == "right answer" and 1 == "wrong answer"
size_t nrStates = 2;
// define variables
DiscreteKey Cathy(1, nrStates), Heather(2, nrStates), Mark(3, nrStates),
Allison(4, nrStates);
// create graph
DiscreteFactorGraph graph;
// add node potentials
graph.add(Cathy, "1 3");
graph.add(Heather, "9 1");
graph.add(Mark, "1 3");
graph.add(Allison, "9 1");
// add edge potentials
graph.add(Cathy & Heather, "2 1 1 2");
graph.add(Heather & Mark, "2 1 1 2");
graph.add(Mark & Allison, "2 1 1 2");
// Print the UGM distribution
cout << "\nUGM distribution:" << endl;
for (size_t a = 0; a < nrStates; a++)
for (size_t m = 0; m < nrStates; m++)
for (size_t h = 0; h < nrStates; h++)
for (size_t c = 0; c < nrStates; c++) {
DiscreteFactor::Values values;
values[1] = c;
values[2] = h;
values[3] = m;
values[4] = a;
double prodPot = graph(values);
cout << c << " " << h << " " << m << " " << a << " :\t"
<< prodPot << "\t" << prodPot/3790 << endl;
}
// "Decoding", i.e., configuration with largest value
// We use sequential variable elimination
DiscreteSequentialSolver solver(graph);
DiscreteFactor::sharedValues optimalDecoding = solver.optimize();
optimalDecoding->print("\noptimalDecoding");
return 0;
}

View File

@ -32,6 +32,9 @@
* Namespace usage
* - Namespaces can be specified for classes in arguments and return values
* - In each case, the namespace must be fully specified, e.g., "namespace1::namespace2::ClassName"
* Using namespace
* - To use a namespace (e.g., generate a "using namespace x" line in cpp files), add "using namespace x;"
* - This declaration applies to all classes *after* the declaration, regardless of brackets
* Methods must start with a lowercase letter
* Static methods must start with a letter (upper or lowercase) and use the "static" keyword
* Includes in C++ wrappers

View File

@ -1,10 +1,10 @@
# install CCOLAMD headers
install(FILES CCOLAMD/Include/ccolamd.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/gtsam/3rdparty/CCOLAMD)
install(FILES UFconfig/UFconfig.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/gtsam/3rdparty/UFconfig)
install(FILES CCOLAMD/Include/ccolamd.h DESTINATION include/gtsam/3rdparty/CCOLAMD)
install(FILES UFconfig/UFconfig.h DESTINATION include/gtsam/3rdparty/UFconfig)
# install Eigen - only the headers
install(DIRECTORY Eigen/Eigen
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/gtsam/3rdparty/Eigen
DESTINATION include/gtsam/3rdparty/Eigen
FILES_MATCHING PATTERN "*.h")
file(GLOB eigen_dir_headers_all "Eigen/Eigen/*")
@ -12,6 +12,6 @@ file(GLOB eigen_dir_headers_all "Eigen/Eigen/*")
foreach(eigen_dir ${eigen_dir_headers_all})
get_filename_component(filename ${eigen_dir} NAME)
if (NOT ((${filename} MATCHES "CMakeLists.txt") OR (${filename} MATCHES "src") OR (${filename} MATCHES ".svn")))
install(FILES Eigen/Eigen/${filename} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/gtsam/3rdparty/Eigen/Eigen)
install(FILES Eigen/Eigen/${filename} DESTINATION include/gtsam/3rdparty/Eigen/Eigen)
endif()
endforeach(eigen_dir)

View File

@ -4,6 +4,7 @@ set (gtsam_subdirs
base
geometry
inference
discrete
linear
nonlinear
slam
@ -25,10 +26,24 @@ if (GTSAM_BUILD_CONVENIENCE_LIBRARIES)
add_library(ccolamd STATIC ${3rdparty_srcs})
endif()
# Sources to remove from builds
set (excluded_sources
"${CMAKE_CURRENT_SOURCE_DIR}/discrete/TypedDiscreteFactor.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/discrete/TypedDiscreteFactorGraph.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/discrete/parseUAI.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/discrete/PotentialTable.cpp")
if(GTSAM_USE_QUATERNIONS)
set(excluded_sources ${excluded_sources} "${CMAKE_CURRENT_SOURCE_DIR}/geometry/Rot3M.cpp")
else()
set(excluded_sources ${excluded_sources} "${CMAKE_CURRENT_SOURCE_DIR}/geometry/Rot3Q.cpp")
endif()
# assemble core libaries
foreach(subdir ${gtsam_subdirs})
# Build convenience libraries
file(GLOB subdir_srcs "${subdir}/*.cpp")
list(REMOVE_ITEM subdir_srcs ${excluded_sources})
set(${subdir}_srcs ${subdir_srcs})
if (GTSAM_BUILD_CONVENIENCE_LIBRARIES)
message(STATUS "Building Convenience Library: ${subdir}")
@ -46,13 +61,12 @@ set(gtsam_srcs
${base_srcs}
${geometry_srcs}
${inference_srcs}
${discrete_srcs}
${linear_srcs}
${nonlinear_srcs}
${slam_srcs}
)
option (GTSAM_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam" ON)
# Versions
set(gtsam_version ${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH})
set(gtsam_soversion ${GTSAM_VERSION_MAJOR})
@ -60,14 +74,16 @@ message(STATUS "GTSAM Version: ${gtsam_version}")
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
# build shared and static versions of the library
message(STATUS "Building GTSAM - static")
add_library(gtsam-static STATIC ${gtsam_srcs})
set_target_properties(gtsam-static PROPERTIES
OUTPUT_NAME gtsam
CLEAN_DIRECT_OUTPUT 1
VERSION ${gtsam_version}
SOVERSION ${gtsam_soversion})
install(TARGETS gtsam-static ARCHIVE DESTINATION lib)
if (GTSAM_BUILD_STATIC_LIBRARY)
message(STATUS "Building GTSAM - static")
add_library(gtsam-static STATIC ${gtsam_srcs})
set_target_properties(gtsam-static PROPERTIES
OUTPUT_NAME gtsam
CLEAN_DIRECT_OUTPUT 1
VERSION ${gtsam_version}
SOVERSION ${gtsam_soversion})
install(TARGETS gtsam-static ARCHIVE DESTINATION lib)
endif (GTSAM_BUILD_STATIC_LIBRARY)
if (GTSAM_BUILD_SHARED_LIBRARY)
message(STATUS "Building GTSAM - shared")

View File

@ -1,97 +0,0 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file DSFVector.cpp
* @date Jun 25, 2010
* @author Kai Ni
* @brief a faster implementation for DSF, which uses vector rather than btree.
*/
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#include <gtsam/base/DSFVector.h>
using namespace std;
namespace gtsam {
/* ************************************************************************* */
DSFVector::DSFVector (const size_t numNodes) {
v_ = boost::make_shared<V>(numNodes);
int index = 0;
keys_.reserve(numNodes);
for(V::iterator it = v_->begin(); it!=v_->end(); it++, index++) {
*it = index;
keys_.push_back(index);
}
}
/* ************************************************************************* */
DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys) : keys_(keys) {
v_ = v_in;
BOOST_FOREACH(const size_t key, keys)
(*v_)[key] = key;
}
/* ************************************************************************* */
bool DSFVector::isSingleton(const Label& label) const {
bool result = false;
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); ++it) {
if(findSet(*it) == label) {
if (!result) // find the first occurrence
result = true;
else
return false;
}
}
return result;
}
/* ************************************************************************* */
std::set<size_t> DSFVector::set(const Label& label) const {
std::set<size_t> set;
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
if (findSet(*it) == label)
set.insert(*it);
}
return set;
}
/* ************************************************************************* */
std::map<DSFVector::Label, std::set<size_t> > DSFVector::sets() const {
std::map<Label, std::set<size_t> > sets;
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
sets[findSet(*it)].insert(*it);
}
return sets;
}
/* ************************************************************************* */
std::map<DSFVector::Label, std::vector<size_t> > DSFVector::arrays() const {
std::map<Label, std::vector<size_t> > arrays;
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
arrays[findSet(*it)].push_back(*it);
}
return arrays;
}
/* ************************************************************************* */
void DSFVector::makeUnionInPlace(const size_t& i1, const size_t& i2) {
(*v_)[findSet(i2)] = findSet(i1);
}
} // namespace

View File

@ -105,7 +105,7 @@ struct FastSetTestableHelper {
typename Set::const_iterator it2 = set2.begin();
while (it1 != set1.end()) {
if (it2 == set2.end() ||
fabs((double)(*it1) - (double)(*it2) > tol))
fabs((double)(*it1) - (double)(*it2)) > tol)
return false;
++it1;
++it2;

View File

@ -34,6 +34,10 @@ struct LieVector : public Vector, public DerivedValue<LieVector> {
/** initialize from a normal vector */
LieVector(const Vector& v) : Vector(v) {}
/** initialize from a fixed size normal vector */
template<int N>
LieVector(const Eigen::Matrix<double, N, 1>& v) : Vector(v) {}
/** wrap a double */
LieVector(double d) : Vector(Vector_(1, d)) {}

View File

@ -541,12 +541,12 @@ Matrix vector_scale(const Matrix& A, const Vector& v, bool inf_mask) {
}
/* ************************************************************************* */
Matrix skewSymmetric(double wx, double wy, double wz)
Matrix3 skewSymmetric(double wx, double wy, double wz)
{
return Matrix_(3,3,
return (Matrix3() <<
0.0, -wz, +wy,
+wz, 0.0, -wx,
-wy, +wx, 0.0);
-wy, +wx, 0.0).finished();
}
/* ************************************************************************* */

View File

@ -37,6 +37,10 @@ namespace gtsam {
typedef Eigen::MatrixXd Matrix;
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatrixRowMajor;
typedef Eigen::Matrix3d Matrix3;
typedef Eigen::Matrix4d Matrix4;
typedef Eigen::Matrix<double,6,6> Matrix6;
// Matrix expressions for accessing parts of matrices
typedef Eigen::Block<Matrix> SubMatrix;
typedef Eigen::Block<const Matrix> ConstSubMatrix;
@ -393,8 +397,8 @@ Matrix vector_scale(const Matrix& A, const Vector& v, bool inf_mask = false); //
* @param wz
* @return a 3*3 skew symmetric matrix
*/
Matrix skewSymmetric(double wx, double wy, double wz);
inline Matrix skewSymmetric(const Vector& w) { return skewSymmetric(w(0),w(1),w(2));}
Matrix3 skewSymmetric(double wx, double wy, double wz);
inline Matrix3 skewSymmetric(const Vector& w) { return skewSymmetric(w(0),w(1),w(2));}
/** Use SVD to calculate inverse square root of a matrix */
Matrix inverse_square_root(const Matrix& A);

View File

@ -38,6 +38,8 @@
using namespace std;
boost::minstd_rand generator(42u);
namespace gtsam {
/* ************************************************************************* */
@ -197,6 +199,15 @@ bool assert_equal(const Vector& expected, const Vector& actual, double tol) {
return false;
}
/* ************************************************************************* */
bool assert_inequal(const Vector& expected, const Vector& actual, double tol) {
if (!equal_with_abs_tol(expected,actual,tol)) return true;
cout << "Erroneously equal:" << endl;
print(expected, "expected");
print(actual, "actual");
return false;
}
/* ************************************************************************* */
bool assert_equal(const SubVector& expected, const SubVector& actual, double tol) {
if (equal_with_abs_tol(expected,actual,tol)) return true;

View File

@ -25,14 +25,27 @@
#include <gtsam/3rdparty/Eigen/Eigen/Core>
#include <boost/random/linear_congruential.hpp>
// Vector is just a typedef of the Eigen dynamic vector type
// TODO: make a version that works for matlab wrapping
/**
* Static random number generator - needs to maintain a state
* over time, hence the static generator. Be careful in
* cases where multiple processes (as is frequently the case with
* multi-robot scenarios) are using the sample() facilities
* in NoiseModel, as they will each have the same seed.
*/
// FIXME: make this go away - use the Sampler class instead
extern boost::minstd_rand generator;
namespace gtsam {
// Vector is just a typedef of the Eigen dynamic vector type
// Typedef arbitary length vector
typedef Eigen::VectorXd Vector;
// Commonly used fixed size vectors
typedef Eigen::Vector3d Vector3;
typedef Eigen::Matrix<double, 6, 1> Vector6;
typedef Eigen::VectorBlock<Vector> SubVector;
typedef Eigen::VectorBlock<const Vector> ConstSubVector;
@ -156,6 +169,15 @@ inline bool equal(const Vector& vec1, const Vector& vec2) {
*/
bool assert_equal(const Vector& vec1, const Vector& vec2, double tol=1e-9);
/**
* Not the same, prints if error
* @param vec1 Vector
* @param vec2 Vector
* @param tol 1e-9
* @return bool
*/
bool assert_inequal(const Vector& vec1, const Vector& vec2, double tol=1e-9);
/**
* Same, prints if error
* @param vec1 Vector
@ -340,12 +362,17 @@ Vector concatVectors(size_t nrVectors, ...);
*/
Vector rand_vector_norm(size_t dim, double mean = 0, double sigma = 1);
/**
* Sets the generator to use a different seed value.
* Default argument resets the RNG
* @param seed is the new seed
*/
inline void seedRNG(unsigned int seed = 42u) {
generator.seed(seed);
}
} // namespace gtsam
// FIXME: make this go away - use the Sampler class instead
static boost::minstd_rand generator(42u);
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_free.hpp>

View File

@ -160,6 +160,55 @@ TEST(cholesky, ldlPartial2) {
EXPECT(assert_equal(IexpectedR, p.transpose()*I));
}
/* ************************************************************************* */
TEST(cholesky, BadScalingCholesky) {
Matrix A = Matrix_(2,2,
1e-40, 0.0,
0.0, 1.0);
Matrix R(A.transpose() * A);
choleskyPartial(R, 2);
double expectedSqrtCondition = 1e-40;
double actualSqrtCondition = R(0,0) / R(1,1);
DOUBLES_EQUAL(expectedSqrtCondition, actualSqrtCondition, 1e-41);
}
/* ************************************************************************* */
TEST(cholesky, BadScalingLDL) {
Matrix A = Matrix_(2,2,
1.0, 0.0,
0.0, 1e-40);
Matrix R(A.transpose() * A);
Eigen::LDLT<Matrix>::TranspositionType permutation = ldlPartial(R, 2);
EXPECT(permutation.indices()(0) == 0);
EXPECT(permutation.indices()(1) == 1);
double expectedCondition = 1e40;
double actualCondition = R(0,0) / R(1,1);
DOUBLES_EQUAL(expectedCondition, actualCondition, 1e-41);
}
/* ************************************************************************* */
TEST(cholesky, BadScalingSVD) {
Matrix A = Matrix_(2,2,
1.0, 0.0,
0.0, 1e-40);
Matrix U, V;
Vector S;
gtsam::svd(A, U, S, V);
double expectedCondition = 1e40;
double actualCondition = S(0) / S(1);
DOUBLES_EQUAL(expectedCondition, actualCondition, 1e-41);
}
/* ************************************************************************* */
int main() {
TestResult tr;

View File

@ -1,87 +0,0 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file testFixedVector.cpp
* @author Alex Cunningham
*/
#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/FixedVector.h>
using namespace gtsam;
typedef FixedVector<5> Vector5;
typedef FixedVector<3> Vector3;
static const double tol = 1e-9;
/* ************************************************************************* */
TEST( testFixedVector, conversions ) {
double data1[] = {1.0, 2.0, 3.0};
Vector v1 = Vector_(3, data1);
Vector3 fv1(v1), fv2(data1);
Vector actFv2(fv2);
CHECK(assert_equal(v1, actFv2));
}
/* ************************************************************************* */
TEST( testFixedVector, variable_constructor ) {
Vector3 act(3, 1.0, 2.0, 3.0);
DOUBLES_EQUAL(1.0, act(0), tol);
DOUBLES_EQUAL(2.0, act(1), tol);
DOUBLES_EQUAL(3.0, act(2), tol);
}
/* ************************************************************************* */
TEST( testFixedVector, equals ) {
Vector3 vec1(3, 1.0, 2.0, 3.0), vec2(3, 1.0, 2.0, 3.0), vec3(3, 2.0, 3.0, 4.0);
Vector5 vec4(5, 1.0, 2.0, 3.0, 4.0, 5.0);
CHECK(assert_equal(vec1, vec1, tol));
CHECK(assert_equal(vec1, vec2, tol));
CHECK(assert_equal(vec2, vec1, tol));
CHECK(!vec1.equals(vec3, tol));
CHECK(!vec3.equals(vec1, tol));
CHECK(!vec1.equals(vec4, tol));
CHECK(!vec4.equals(vec1, tol));
}
/* ************************************************************************* */
TEST( testFixedVector, static_constructors ) {
Vector3 actZero = Vector3::zero();
Vector3 expZero(3, 0.0, 0.0, 0.0);
CHECK(assert_equal(expZero, actZero, tol));
Vector3 actOnes = Vector3::ones();
Vector3 expOnes(3, 1.0, 1.0, 1.0);
CHECK(assert_equal(expOnes, actOnes, tol));
Vector3 actRepeat = Vector3::repeat(2.3);
Vector3 expRepeat(3, 2.3, 2.3, 2.3);
CHECK(assert_equal(expRepeat, actRepeat, tol));
Vector3 actBasis = Vector3::basis(1);
Vector3 expBasis(3, 0.0, 1.0, 0.0);
CHECK(assert_equal(expBasis, actBasis, tol));
Vector3 actDelta = Vector3::delta(1, 2.3);
Vector3 expDelta(3, 0.0, 2.3, 0.0);
CHECK(assert_equal(expDelta, actDelta, tol));
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */

View File

@ -297,6 +297,27 @@ TEST( TestVector, linear_dependent3 )
EXPECT(!linear_dependent(v1, v2));
}
/* ************************************************************************* */
TEST( TestVector, random )
{
// Assumes seed not previously reset during this test
seedRNG();
Vector v1_42 = rand_vector_norm(5);
// verify that resetting the RNG produces the same value
seedRNG();
Vector v2_42 = rand_vector_norm(5);
EXPECT(assert_equal(v1_42, v2_42, 1e-6));
// verify that different seed produces a different value
seedRNG(41u);
Vector v3_41 = rand_vector_norm(5);
EXPECT(assert_inequal(v1_42, v3_41, 1e-6));
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */

View File

@ -0,0 +1,134 @@
/*
* @file AlgebraicDecisionTree.h
* @brief Algebraic Decision Trees
* @author Frank Dellaert
* @date Mar 14, 2011
*/
#pragma once
#include <gtsam/discrete/DecisionTree-inl.h>
namespace gtsam {
/**
* Algebraic Decision Trees fix the range to double
* Just has some nice constructors and some syntactic sugar
* TODO: consider eliminating this class altogether?
*/
template<typename L>
class AlgebraicDecisionTree: public DecisionTree<L, double> {
public:
typedef DecisionTree<L, double> Super;
/** The Real ring with addition and multiplication */
struct Ring {
static inline double zero() {
return 0.0;
}
static inline double one() {
return 1.0;
}
static inline double add(const double& a, const double& b) {
return a + b;
}
static inline double max(const double& a, const double& b) {
return std::max(a, b);
}
static inline double mul(const double& a, const double& b) {
return a * b;
}
static inline double div(const double& a, const double& b) {
return a / b;
}
static inline double id(const double& x) {
return x;
}
};
AlgebraicDecisionTree() :
Super(1.0) {
}
AlgebraicDecisionTree(const Super& add) :
Super(add) {
}
/** Create a new leaf function splitting on a variable */
AlgebraicDecisionTree(const L& label, double y1, double y2) :
Super(label, y1, y2) {
}
/** Create a new leaf function splitting on a variable */
AlgebraicDecisionTree(const typename Super::LabelC& labelC, double y1, double y2) :
Super(labelC, y1, y2) {
}
/** Create from keys and vector table */
AlgebraicDecisionTree //
(const std::vector<typename Super::LabelC>& labelCs, const std::vector<double>& ys) {
this->root_ = Super::create(labelCs.begin(), labelCs.end(), ys.begin(),
ys.end());
}
/** Create from keys and string table */
AlgebraicDecisionTree //
(const std::vector<typename Super::LabelC>& labelCs, const std::string& table) {
// Convert string to doubles
std::vector<double> ys;
std::istringstream iss(table);
std::copy(std::istream_iterator<double>(iss),
std::istream_iterator<double>(), std::back_inserter(ys));
// now call recursive Create
this->root_ = Super::create(labelCs.begin(), labelCs.end(), ys.begin(),
ys.end());
}
/** Create a new function splitting on a variable */
template<typename Iterator>
AlgebraicDecisionTree(Iterator begin, Iterator end, const L& label) :
Super(NULL) {
this->root_ = compose(begin, end, label);
}
/** Convert */
template<typename M>
AlgebraicDecisionTree(const AlgebraicDecisionTree<M>& other,
const std::map<M, L>& map) {
this->root_ = this->template convert<M, double>(other.root_, map,
Ring::id);
}
/** sum */
AlgebraicDecisionTree operator+(const AlgebraicDecisionTree& g) const {
return this->apply(g, &Ring::add);
}
/** product */
AlgebraicDecisionTree operator*(const AlgebraicDecisionTree& g) const {
return this->apply(g, &Ring::mul);
}
/** division */
AlgebraicDecisionTree operator/(const AlgebraicDecisionTree& g) const {
return this->apply(g, &Ring::div);
}
/** sum out variable */
AlgebraicDecisionTree sum(const L& label, size_t cardinality) const {
return this->combine(label, cardinality, &Ring::add);
}
/** sum out variable */
AlgebraicDecisionTree sum(const typename Super::LabelC& labelC) const {
return this->combine(labelC, &Ring::add);
}
};
// AlgebraicDecisionTree
}
// namespace gtsam

110
gtsam/discrete/AllDiff.cpp Normal file
View File

@ -0,0 +1,110 @@
/*
* AllDiff.cpp
* @brief General "all-different" constraint
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/Domain.h>
#include <gtsam/discrete/AllDiff.h>
#include <gtsam/base/Testable.h>
#include <boost/make_shared.hpp>
namespace gtsam {
/* ************************************************************************* */
AllDiff::AllDiff(const DiscreteKeys& dkeys) :
DiscreteFactor(dkeys.indices()) {
BOOST_FOREACH(const DiscreteKey& dkey, dkeys)
cardinalities_.insert(dkey);
}
/* ************************************************************************* */
void AllDiff::print(const std::string& s) const {
std::cout << s << ": AllDiff on ";
BOOST_FOREACH (Index dkey, keys_)
std::cout << dkey << " ";
std::cout << std::endl;
}
/* ************************************************************************* */
double AllDiff::operator()(const Values& values) const {
std::set < size_t > taken; // record values taken by keys
BOOST_FOREACH(Index dkey, keys_) {
size_t value = values.at(dkey); // get the value for that key
if (taken.count(value)) return 0.0;// check if value alreday taken
taken.insert(value);// if not, record it as taken and keep checking
}
return 1.0;
}
/* ************************************************************************* */
AllDiff::operator DecisionTreeFactor() const {
// We will do this by converting the allDif into many BinaryAllDiff constraints
DecisionTreeFactor converted;
size_t nrKeys = keys_.size();
for (size_t i1 = 0; i1 < nrKeys; i1++)
for (size_t i2 = i1 + 1; i2 < nrKeys; i2++) {
BinaryAllDiff binary12(discreteKey(i1),discreteKey(i2));
converted = converted * binary12;
}
return converted;
}
/* ************************************************************************* */
DecisionTreeFactor AllDiff::operator*(const DecisionTreeFactor& f) const {
// TODO: can we do this more efficiently?
return DecisionTreeFactor(*this) * f;
}
/* ************************************************************************* */
bool AllDiff::ensureArcConsistency(size_t j, std::vector<Domain>& domains) const {
// Though strictly not part of allDiff, we check for
// a value in domains[j] that does not occur in any other connected domain.
// If found, we make this a singleton...
// TODO: make a new constraint where this really is true
Domain& Dj = domains[j];
if (Dj.checkAllDiff(keys_, domains)) return true;
// Check all other domains for singletons and erase corresponding values
// This is the same as arc-consistency on the equivalent binary constraints
bool changed = false;
BOOST_FOREACH(Index k, keys_)
if (k != j) {
const Domain& Dk = domains[k];
if (Dk.isSingleton()) { // check if singleton
size_t value = Dk.firstValue();
if (Dj.contains(value)) {
Dj.erase(value); // erase value if true
changed = true;
}
}
}
return changed;
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr AllDiff::partiallyApply(const Values& values) const {
DiscreteKeys newKeys;
// loop over keys and add them only if they do not appear in values
BOOST_FOREACH(Index k, keys_)
if (values.find(k) == values.end()) {
newKeys.push_back(DiscreteKey(k,cardinalities_.at(k)));
}
return boost::make_shared<AllDiff>(newKeys);
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr AllDiff::partiallyApply(
const std::vector<Domain>& domains) const {
DiscreteFactor::Values known;
BOOST_FOREACH(Index k, keys_) {
const Domain& Dk = domains[k];
if (Dk.isSingleton())
known[k] = Dk.firstValue();
}
return partiallyApply(known);
}
/* ************************************************************************* */
} // namespace gtsam

64
gtsam/discrete/AllDiff.h Normal file
View File

@ -0,0 +1,64 @@
/*
* AllDiff.h
* @brief General "all-different" constraint
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/DiscreteKey.h>
#include <gtsam/discrete/BinaryAllDiff.h>
namespace gtsam {
/**
* General AllDiff constraint
* Returns 1 if values for all keys are different, 0 otherwise
* DiscreteFactors are all awkward in that they have to store two types of keys:
* for each variable we have a Index and an Index. In this factor, we
* keep the Indices locally, and the Indices are stored in IndexFactor.
*/
class AllDiff: public DiscreteFactor {
std::map<Index,size_t> cardinalities_;
DiscreteKey discreteKey(size_t i) const {
Index j = keys_[i];
return DiscreteKey(j,cardinalities_.at(j));
}
public:
/// Constructor
AllDiff(const DiscreteKeys& dkeys);
// print
virtual void print(const std::string& s = "") const;
/// Calculate value = expensive !
virtual double operator()(const Values& values) const;
/// Convert into a decisiontree, can be *very* expensive !
virtual operator DecisionTreeFactor() const;
/// Multiply into a decisiontree
virtual DecisionTreeFactor operator*(const DecisionTreeFactor& f) const;
/*
* Ensure Arc-consistency
* Arc-consistency involves creating binaryAllDiff constraints
* In which case the combinatorial hyper-arc explosion disappears.
* @param j domain to be checked
* @param domains all other domains
*/
bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const;
/// Partially apply known values
virtual DiscreteFactor::shared_ptr partiallyApply(const Values&) const;
/// Partially apply known values, domain version
virtual DiscreteFactor::shared_ptr partiallyApply(const std::vector<Domain>&) const;
};
} // namespace gtsam

View File

@ -0,0 +1,36 @@
/*
* @file Assignment.h
* @brief An assignment from labels to a discrete value index (size_t)
* @author Frank Dellaert
* @date Feb 5, 2012
*/
#pragma once
#include <boost/foreach.hpp>
#include <iostream>
#include <map>
namespace gtsam {
/**
* An assignment from labels to value index (size_t).
* Assigns to each label a value. Implemented as a simple map.
* A discrete factor takes an Assignment and returns a value.
*/
template <class L>
class Assignment: public std::map<L, size_t> {
public:
void print(const std::string& s = "Assignment: ") const {
std::cout << s << ": ";
BOOST_FOREACH(const typename Assignment::value_type& keyValue, *this)
std::cout << "(" << keyValue.first << ", " << keyValue.second << ")";
std::cout << std::endl;
}
bool equals(const Assignment& other, double tol = 1e-9) const {
return (*this == other);
}
};
} // namespace gtsam

View File

@ -0,0 +1,87 @@
/*
* BinaryAllDiff.h
* @brief Binary "all-different" constraint
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/DecisionTreeFactor.h>
namespace gtsam {
/**
* Binary AllDiff constraint
* Returns 1 if values for two keys are different, 0 otherwise
* DiscreteFactors are all awkward in that they have to store two types of keys:
* for each variable we have a Index and an Index. In this factor, we
* keep the Indices locally, and the Indices are stored in IndexFactor.
*/
class BinaryAllDiff: public DiscreteFactor {
size_t cardinality0_, cardinality1_; /// cardinality
public:
/// Constructor
BinaryAllDiff(const DiscreteKey& key1, const DiscreteKey& key2) :
DiscreteFactor(key1.first, key2.first),
cardinality0_(key1.second), cardinality1_(key2.second) {
}
// print
virtual void print(const std::string& s = "") const {
std::cout << s << ": BinaryAllDiff on " << keys_[0] << " and " << keys_[1]
<< std::endl;
}
/// Calculate value
virtual double operator()(const Values& values) const {
return (double) (values.at(keys_[0]) != values.at(keys_[1]));
}
/// Convert into a decisiontree
virtual operator DecisionTreeFactor() const {
DiscreteKeys keys;
keys.push_back(DiscreteKey(keys_[0],cardinality0_));
keys.push_back(DiscreteKey(keys_[1],cardinality1_));
std::vector<double> table;
for (size_t i1 = 0; i1 < cardinality0_; i1++)
for (size_t i2 = 0; i2 < cardinality1_; i2++)
table.push_back(i1 != i2);
DecisionTreeFactor converted(keys, table);
return converted;
}
/// Multiply into a decisiontree
virtual DecisionTreeFactor operator*(const DecisionTreeFactor& f) const {
// TODO: can we do this more efficiently?
return DecisionTreeFactor(*this) * f;
}
/*
* Ensure Arc-consistency
* @param j domain to be checked
* @param domains all other domains
*/
///
bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const {
// throw std::runtime_error(
// "BinaryAllDiff::ensureArcConsistency not implemented");
return false;
}
/// Partially apply known values
virtual DiscreteFactor::shared_ptr partiallyApply(const Values&) const {
throw std::runtime_error("BinaryAllDiff::partiallyApply not implemented");
}
/// Partially apply known values, domain version
virtual DiscreteFactor::shared_ptr partiallyApply(
const std::vector<Domain>&) const {
throw std::runtime_error("BinaryAllDiff::partiallyApply not implemented");
}
};
} // namespace gtsam

View File

@ -0,0 +1,38 @@
# Install headers
set(subdir discrete)
file(GLOB discrete_headers "*.h")
# FIXME: exclude headers
install(FILES ${discrete_headers} DESTINATION include/gtsam/discrete)
# Set up library dependencies
set (discrete_local_libs
discrete
inference
base
ccolamd
)
# Exclude tests that don't work
set (discrete_excluded_tests
"${CMAKE_CURRENT_SOURCE_DIR}/tests/testTypedDiscreteFactor.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/tests/testTypedDiscreteFactorGraph.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/tests/testPotentialTable.cpp")
# Add all tests
if (GTSAM_BUILD_TESTS)
gtsam_add_subdir_tests(discrete "${discrete_local_libs}" "gtsam-static" "${discrete_excluded_tests}")
endif()
# add examples
foreach(example schedulingExample schedulingQuals12)
add_executable(${example} "examples/${example}.cpp")
add_dependencies(${example} gtsam-static)
target_link_libraries(${example} gtsam-static)
add_custom_target(${example}.run ${EXECUTABLE_OUTPUT_PATH}${example} ${ARGN})
endforeach(example)
# Build timing scripts
#if (GTSAM_BUILD_TIMING)
# gtsam_add_timing(discrete "${discrete_local_libs}")
#endif(GTSAM_BUILD_TIMING)

94
gtsam/discrete/CSP.cpp Normal file
View File

@ -0,0 +1,94 @@
/*
* CSP.cpp
* @brief Constraint Satisfaction Problem class
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/Domain.h>
#include <gtsam/discrete/CSP.h>
#include <gtsam/discrete/DiscreteSequentialSolver.h>
#include <gtsam/base/Testable.h>
#include <boost/foreach.hpp>
namespace gtsam {
/// Find the best total assignment - can be expensive
CSP::sharedValues CSP::optimalAssignment() const {
DiscreteSequentialSolver solver(*this);
DiscreteBayesNet::shared_ptr chordal = solver.eliminate();
sharedValues mpe = optimize(*chordal);
return mpe;
}
void CSP::runArcConsistency(size_t cardinality, size_t nrIterations, bool print) const {
// Create VariableIndex
VariableIndex index(*this);
// index.print();
size_t n = index.size();
// Initialize domains
std::vector < Domain > domains;
for (size_t j = 0; j < n; j++)
domains.push_back(Domain(DiscreteKey(j,cardinality)));
// Create array of flags indicating a domain changed or not
std::vector<bool> changed(n);
// iterate nrIterations over entire grid
for (size_t it = 0; it < nrIterations; it++) {
bool anyChange = false;
// iterate over all cells
for (size_t v = 0; v < n; v++) {
// keep track of which domains changed
changed[v] = false;
// loop over all factors/constraints for variable v
const VariableIndex::Factors& factors = index[v];
BOOST_FOREACH(size_t f,factors) {
// if not already a singleton
if (!domains[v].isSingleton()) {
// get the constraint and call its ensureArcConsistency method
DiscreteFactor::shared_ptr factor = (*this)[f];
changed[v] = factor->ensureArcConsistency(v,domains) || changed[v];
}
} // f
if (changed[v]) anyChange = true;
} // v
if (!anyChange) break;
// TODO: Sudoku specific hack
if (print) {
if (cardinality == 9 && n == 81) {
for (size_t i = 0, v = 0; i < sqrt(n); i++) {
for (size_t j = 0; j < sqrt(n); j++, v++) {
if (changed[v]) cout << "*";
domains[v].print();
cout << "\t";
} // i
cout << endl;
} // j
} else {
for (size_t v = 0; v < n; v++) {
if (changed[v]) cout << "*";
domains[v].print();
cout << "\t";
} // v
}
cout << endl;
} // print
} // it
#ifndef INPROGRESS
// Now create new problem with all singleton variables removed
// We do this by adding simplifying all factors using parial application
// TODO: create a new ordering as we go, to ensure a connected graph
// KeyOrdering ordering;
// vector<Index> dkeys;
BOOST_FOREACH(const DiscreteFactor::shared_ptr& factor, factors_) {
DiscreteFactor::shared_ptr reduced = factor->partiallyApply(domains);
if (print) reduced->print();
}
#endif
}
} // gtsam

71
gtsam/discrete/CSP.h Normal file
View File

@ -0,0 +1,71 @@
/*
* CSP.h
* @brief Constraint Satisfaction Problem class
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/AllDiff.h>
#include <gtsam/discrete/SingleValue.h>
#include <gtsam/discrete/DiscreteFactorGraph.h>
namespace gtsam {
/**
* Constraint Satisfaction Problem class
* A specialization of a DiscreteFactorGraph.
* It knows about CSP-specific constraints and algorithms
*/
class CSP: public DiscreteFactorGraph {
public:
/// Constructor
CSP() {
}
/// Add a unary constraint, allowing only a single value
void addSingleValue(const DiscreteKey& dkey, size_t value) {
boost::shared_ptr<SingleValue> factor(new SingleValue(dkey, value));
push_back(factor);
}
/// Add a binary AllDiff constraint
void addAllDiff(const DiscreteKey& key1, const DiscreteKey& key2) {
boost::shared_ptr<BinaryAllDiff> factor(
new BinaryAllDiff(key1, key2));
push_back(factor);
}
/// Add a general AllDiff constraint
void addAllDiff(const DiscreteKeys& dkeys) {
boost::shared_ptr<AllDiff> factor(new AllDiff(dkeys));
push_back(factor);
}
/// Find the best total assignment - can be expensive
sharedValues optimalAssignment() const;
/*
* Perform loopy belief propagation
* True belief propagation would check for each value in domain
* whether any satisfying separator assignment can be found.
* This corresponds to hyper-arc consistency in CSP speak.
* This can be done by creating a mini-factor graph and search.
* For a nine-by-nine Sudoku, the search tree will be 8+6+6=20 levels deep.
* It will be very expensive to exclude values that way.
*/
// void applyBeliefPropagation(size_t nrIterations = 10) const;
/*
* Apply arc-consistency ~ Approximate loopy belief propagation
* We need to give the domains to a constraint, and it returns
* a domain whose values don't conflict in the arc-consistency way.
* TODO: should get cardinality from Indices
*/
void runArcConsistency(size_t cardinality, size_t nrIterations = 10,
bool print = false) const;
};
} // gtsam

View File

@ -0,0 +1,667 @@
/*
* @file DecisionTree.h
* @brief Decision Tree for use in DiscreteFactors
* @author Frank Dellaert
* @author Can Erdogan
* @date Jan 30, 2012
*/
#pragma once
#include <gtsam/discrete/DecisionTree.h>
#include <gtsam/base/Testable.h>
#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/unordered_set.hpp>
#include <boost/noncopyable.hpp>
#include <list>
#include <cmath>
#include <fstream>
#include <sstream>
namespace gtsam {
using namespace boost::assign;
/*********************************************************************************/
// Node
/*********************************************************************************/
#ifdef DT_DEBUG_MEMORY
template<typename L, typename Y>
int DecisionTree<L, Y>::Node::nrNodes = 0;
#endif
/*********************************************************************************/
// Leaf
/*********************************************************************************/
template<typename L, typename Y>
class DecisionTree<L, Y>::Leaf: public DecisionTree<L, Y>::Node {
/** constant stored in this leaf */
Y constant_;
public:
/** Constructor from constant */
Leaf(const Y& constant) :
constant_(constant) {}
/** return the constant */
const Y& constant() const {
return constant_;
}
/// Leaf-Leaf equality
bool sameLeaf(const Leaf& q) const {
return constant_ == q.constant_;
}
/// polymorphic equality: is q is a leaf, could be
bool sameLeaf(const Node& q) const {
return (q.isLeaf() && q.sameLeaf(*this));
}
/** equality up to tolerance */
bool equals(const Node& q, double tol) const {
const Leaf* other = dynamic_cast<const Leaf*> (&q);
if (!other) return false;
return fabs(this->constant_ - other->constant_) < tol;
}
/** print */
void print(const std::string& s) const {
bool showZero = true;
if (showZero || constant_) std::cout << s << " Leaf " << constant_ << std::endl;
}
/** to graphviz file */
void dot(std::ostream& os, bool showZero) const {
if (showZero || constant_) os << "\"" << this->id() << "\" [label=\""
<< boost::format("%4.2g") % constant_
<< "\", shape=box, rank=sink, height=0.35, fixedsize=true]\n"; // width=0.55,
}
/** evaluate */
const Y& operator()(const Assignment<L>& x) const {
return constant_;
}
/** apply unary operator */
NodePtr apply(const Unary& op) const {
NodePtr f(new Leaf(op(constant_)));
return f;
}
// Apply binary operator "h = f op g" on Leaf node
// Note op is not assumed commutative so we need to keep track of order
// Simply calls apply on argument to call correct virtual method:
// fL.apply_f_op_g(gL) -> gL.apply_g_op_fL(fL) (below)
// fL.apply_f_op_g(gC) -> gC.apply_g_op_fL(fL) (Choice)
NodePtr apply_f_op_g(const Node& g, const Binary& op) const {
return g.apply_g_op_fL(*this, op);
}
// Applying binary operator to two leaves results in a leaf
NodePtr apply_g_op_fL(const Leaf& fL, const Binary& op) const {
NodePtr h(new Leaf(op(fL.constant_, constant_))); // fL op gL
return h;
}
// If second argument is a Choice node, call it's apply with leaf as second
NodePtr apply_g_op_fC(const Choice& fC, const Binary& op) const {
return fC.apply_fC_op_gL(*this, op); // operand order back to normal
}
/** choose a branch, create new memory ! */
NodePtr choose(const L& label, size_t index) const {
return NodePtr(new Leaf(constant()));
}
bool isLeaf() const { return true; }
}; // Leaf
/*********************************************************************************/
// Choice
/*********************************************************************************/
template<typename L, typename Y>
class DecisionTree<L, Y>::Choice: public DecisionTree<L, Y>::Node {
/** the label of the variable on which we split */
L label_;
/** The children of this Choice node. */
std::vector<NodePtr> branches_;
private:
/** incremental allSame */
size_t allSame_;
typedef boost::shared_ptr<const Choice> ChoicePtr;
public:
virtual ~Choice() {
#ifdef DT_DEBUG_MEMORY
std::std::cout << Node::nrNodes << " destructing (Choice) " << this->id() << std::std::endl;
#endif
}
/** If all branches of a choice node f are the same, just return a branch */
static NodePtr Unique(const ChoicePtr& f) {
#ifndef DT_NO_PRUNING
if (f->allSame_) {
assert(f->branches().size() > 0);
NodePtr f0 = f->branches_[0];
assert(f0->isLeaf());
NodePtr newLeaf(new Leaf(boost::dynamic_pointer_cast<const Leaf>(f0)->constant()));
return newLeaf;
} else
#endif
return f;
}
bool isLeaf() const { return false; }
/** Constructor, given choice label and mandatory expected branch count */
Choice(const L& label, size_t count) :
label_(label), allSame_(true) {
branches_.reserve(count);
}
/**
* Construct from applying binary op to two Choice nodes
*/
Choice(const Choice& f, const Choice& g, const Binary& op) :
allSame_(true) {
// Choose what to do based on label
if (f.label() > g.label()) {
// f higher than g
label_ = f.label();
size_t count = f.nrChoices();
branches_.reserve(count);
for (size_t i = 0; i < count; i++)
push_back(f.branches_[i]->apply_f_op_g(g, op));
} else if (g.label() > f.label()) {
// f lower than g
label_ = g.label();
size_t count = g.nrChoices();
branches_.reserve(count);
for (size_t i = 0; i < count; i++)
push_back(g.branches_[i]->apply_g_op_fC(f, op));
} else {
// f same level as g
label_ = f.label();
size_t count = f.nrChoices();
branches_.reserve(count);
for (size_t i = 0; i < count; i++)
push_back(f.branches_[i]->apply_f_op_g(*g.branches_[i], op));
}
}
const L& label() const {
return label_;
}
size_t nrChoices() const {
return branches_.size();
}
const std::vector<NodePtr>& branches() const {
return branches_;
}
/** add a branch: TODO merge into constructor */
void push_back(const NodePtr& node) {
// allSame_ is restricted to leaf nodes in a decision tree
if (allSame_ && !branches_.empty()) {
allSame_ = node->sameLeaf(*branches_.back());
}
branches_.push_back(node);
}
/** print (as a tree) */
void print(const std::string& s) const {
std::cout << s << " Choice(";
// std::cout << this << ",";
std::cout << label_ << ") " << std::endl;
for (size_t i = 0; i < branches_.size(); i++)
branches_[i]->print((boost::format("%s %d") % s % i).str());
}
/** output to graphviz (as a a graph) */
void dot(std::ostream& os, bool showZero) const {
os << "\"" << this->id() << "\" [shape=circle, label=\"" << label_
<< "\"]\n";
for (size_t i = 0; i < branches_.size(); i++) {
NodePtr branch = branches_[i];
// Check if zero
if (!showZero) {
const Leaf* leaf = dynamic_cast<const Leaf*> (branch.get());
if (leaf && !leaf->constant()) continue;
}
os << "\"" << this->id() << "\" -> \"" << branch->id() << "\"";
if (i == 0) os << " [style=dashed]";
if (i > 1) os << " [style=bold]";
os << std::endl;
branch->dot(os, showZero);
}
}
/// Choice-Leaf equality: always false
bool sameLeaf(const Leaf& q) const {
return false;
}
/// polymorphic equality: if q is a leaf, could be...
bool sameLeaf(const Node& q) const {
return (q.isLeaf() && q.sameLeaf(*this));
}
/** equality up to tolerance */
bool equals(const Node& q, double tol) const {
const Choice* other = dynamic_cast<const Choice*> (&q);
if (!other) return false;
if (this->label_ != other->label_) return false;
if (branches_.size() != other->branches_.size()) return false;
// we don't care about shared pointers being equal here
for (size_t i = 0; i < branches_.size(); i++)
if (!(branches_[i]->equals(*(other->branches_[i]), tol))) return false;
return true;
}
/** evaluate */
const Y& operator()(const Assignment<L>& x) const {
#ifndef NDEBUG
typename Assignment<L>::const_iterator it = x.find(label_);
if (it == x.end()) {
std::cout << "Trying to find value for " << label_ << std::endl;
throw std::invalid_argument(
"DecisionTree::operator(): value undefined for a label");
}
#endif
size_t index = x.at(label_);
NodePtr child = branches_[index];
return (*child)(x);
}
/**
* Construct from applying unary op to a Choice node
*/
Choice(const L& label, const Choice& f, const Unary& op) :
label_(label), allSame_(true) {
branches_.reserve(f.branches_.size()); // reserve space
BOOST_FOREACH (const NodePtr& branch, f.branches_)
push_back(branch->apply(op));
}
/** apply unary operator */
NodePtr apply(const Unary& op) const {
boost::shared_ptr<Choice> r(new Choice(label_, *this, op));
return Unique(r);
}
// Apply binary operator "h = f op g" on Choice node
// Note op is not assumed commutative so we need to keep track of order
// Simply calls apply on argument to call correct virtual method:
// fC.apply_f_op_g(gL) -> gL.apply_g_op_fC(fC) -> (Leaf)
// fC.apply_f_op_g(gC) -> gC.apply_g_op_fC(fC) -> (below)
NodePtr apply_f_op_g(const Node& g, const Binary& op) const {
return g.apply_g_op_fC(*this, op);
}
// If second argument of binary op is Leaf node, recurse on branches
NodePtr apply_g_op_fL(const Leaf& fL, const Binary& op) const {
boost::shared_ptr<Choice> h(new Choice(label(), nrChoices()));
BOOST_FOREACH(NodePtr branch, branches_)
h->push_back(fL.apply_f_op_g(*branch, op));
return Unique(h);
}
// If second argument of binary op is Choice, call constructor
NodePtr apply_g_op_fC(const Choice& fC, const Binary& op) const {
boost::shared_ptr<Choice> h(new Choice(fC, *this, op));
return Unique(h);
}
// If second argument of binary op is Leaf
template<typename OP>
NodePtr apply_fC_op_gL(const Leaf& gL, OP op) const {
boost::shared_ptr<Choice> h(new Choice(label(), nrChoices()));
BOOST_FOREACH(const NodePtr& branch, branches_)
h->push_back(branch->apply_f_op_g(gL, op));
return Unique(h);
}
/** choose a branch, recursively */
NodePtr choose(const L& label, size_t index) const {
if (label_ == label)
return branches_[index]; // choose branch
// second case, not label of interest, just recurse
boost::shared_ptr<Choice> r(new Choice(label_, branches_.size()));
BOOST_FOREACH(const NodePtr& branch, branches_)
r->push_back(branch->choose(label, index));
return Unique(r);
}
}; // Choice
/*********************************************************************************/
// DecisionTree
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree() {
}
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const NodePtr& root) :
root_(root) {
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const Y& y) {
root_ = NodePtr(new Leaf(y));
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(//
const L& label, const Y& y1, const Y& y2) {
boost::shared_ptr<Choice> a(new Choice(label, 2));
NodePtr l1(new Leaf(y1)), l2(new Leaf(y2));
a->push_back(l1);
a->push_back(l2);
root_ = Choice::Unique(a);
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(//
const LabelC& labelC, const Y& y1, const Y& y2) {
if (labelC.second != 2) throw std::invalid_argument(
"DecisionTree: binary constructor called with non-binary label");
boost::shared_ptr<Choice> a(new Choice(labelC.first, 2));
NodePtr l1(new Leaf(y1)), l2(new Leaf(y2));
a->push_back(l1);
a->push_back(l2);
root_ = Choice::Unique(a);
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const std::vector<LabelC>& labelCs,
const std::vector<Y>& ys) {
// call recursive Create
root_ = create(labelCs.begin(), labelCs.end(), ys.begin(), ys.end());
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const std::vector<LabelC>& labelCs,
const std::string& table) {
// Convert std::string to doubles
std::vector<Y> ys;
std::istringstream iss(table);
copy(std::istream_iterator<Y>(iss), std::istream_iterator<Y>(),
back_inserter(ys));
// now call recursive Create
root_ = create(labelCs.begin(), labelCs.end(), ys.begin(), ys.end());
}
/*********************************************************************************/
template<typename L, typename Y>
template<typename Iterator> DecisionTree<L, Y>::DecisionTree(
Iterator begin, Iterator end, const L& label) {
root_ = compose(begin, end, label);
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y>::DecisionTree(const L& label,
const DecisionTree& f0, const DecisionTree& f1) {
std::vector<DecisionTree> functions;
functions += f0, f1;
root_ = compose(functions.begin(), functions.end(), label);
}
/*********************************************************************************/
template<typename L, typename Y>
template<typename M, typename X>
DecisionTree<L, Y>::DecisionTree(const DecisionTree<M, X>& other,
const std::map<M, L>& map, boost::function<Y(const X&)> op) {
root_ = convert(other.root_, map, op);
}
/*********************************************************************************/
// Called by two constructors above.
// Takes a label and a corresponding range of decision trees, and creates a new
// decision tree. However, the order of the labels needs to be respected, so we
// cannot just create a root Choice node on the label: if the label is not the
// highest label, we need to do a complicated and expensive recursive call.
template<typename L, typename Y> template<typename Iterator>
typename DecisionTree<L, Y>::NodePtr DecisionTree<L, Y>::compose(
Iterator begin, Iterator end, const L& label) const {
// find highest label among branches
boost::optional<L> highestLabel;
boost::optional<size_t> nrChoices;
for (Iterator it = begin; it != end; it++) {
if (it->root_->isLeaf()) continue;
boost::shared_ptr<const Choice> c = boost::dynamic_pointer_cast<const Choice> (it->root_);
if (!highestLabel || c->label() > *highestLabel) {
highestLabel.reset(c->label());
nrChoices.reset(c->nrChoices());
}
}
// if label is already in correct order, just put together a choice on label
if (!highestLabel || label > *highestLabel) {
boost::shared_ptr<Choice> choiceOnLabel(new Choice(label, end - begin));
for (Iterator it = begin; it != end; it++)
choiceOnLabel->push_back(it->root_);
return Choice::Unique(choiceOnLabel);
}
// Set up a new choice on the highest label
boost::shared_ptr<Choice> choiceOnHighestLabel(new Choice(*highestLabel, *nrChoices));
// now, for all possible values of highestLabel
for (size_t index = 0; index < *nrChoices; index++) {
// make a new set of functions for composing by iterating over the given
// functions, and selecting the appropriate branch.
std::vector<DecisionTree> functions;
for (Iterator it = begin; it != end; it++) {
// by restricting the input functions to value i for labelBelow
DecisionTree chosen = it->choose(*highestLabel, index);
functions.push_back(chosen);
}
// We then recurse, for all values of the highest label
NodePtr fi = compose(functions.begin(), functions.end(), label);
choiceOnHighestLabel->push_back(fi);
}
return Choice::Unique(choiceOnHighestLabel);
}
/*********************************************************************************/
// "create" is a bit of a complicated thing, but very useful.
// It takes a range of labels and a corresponding range of values,
// and creates a decision tree, as follows:
// - if there is only one label, creates a choice node with values in leaves
// - otherwise, it evenly splits up the range of values and creates a tree for
// each sub-range, and assigns that tree to first label's choices
// Example:
// create([B A],[1 2 3 4]) would call
// create([A],[1 2])
// create([A],[3 4])
// and produce
// B=0
// A=0: 1
// A=1: 2
// B=1
// A=0: 3
// A=1: 4
// Note, through the magic of "compose", create([A B],[1 2 3 4]) will produce
// exactly the same tree as above: the highest label is always the root.
// However, it will be *way* faster if labels are given highest to lowest.
template<typename L, typename Y>
template<typename It, typename ValueIt>
typename DecisionTree<L, Y>::NodePtr DecisionTree<L, Y>::create(
It begin, It end, ValueIt beginY, ValueIt endY) const {
// get crucial counts
size_t nrChoices = begin->second;
size_t size = endY - beginY;
// Find the next key to work on
It labelC = begin + 1;
if (labelC == end) {
// Base case: only one key left
// Create a simple choice node with values as leaves.
if (size != nrChoices) {
std::cout << "Trying to create DD on " << begin->first << std::endl;
std::cout << boost::format("DecisionTree::create: expected %d values but got %d instead") % nrChoices % size << std::endl;
throw std::invalid_argument("DecisionTree::create invalid argument");
}
boost::shared_ptr<Choice> choice(new Choice(begin->first, endY - beginY));
for (ValueIt y = beginY; y != endY; y++)
choice->push_back(NodePtr(new Leaf(*y)));
return Choice::Unique(choice);
}
// Recursive case: perform "Shannon expansion"
// Creates one tree (i.e.,function) for each choice of current key
// by calling create recursively, and then puts them all together.
std::vector<DecisionTree> functions;
size_t split = size / nrChoices;
for (size_t i = 0; i < nrChoices; i++, beginY += split) {
NodePtr f = create<It, ValueIt>(labelC, end, beginY, beginY + split);
functions += DecisionTree(f);
}
return compose(functions.begin(), functions.end(), begin->first);
}
/*********************************************************************************/
template<typename L, typename Y>
template<typename M, typename X>
typename DecisionTree<L, Y>::NodePtr DecisionTree<L, Y>::convert(
const typename DecisionTree<M, X>::NodePtr& f, const std::map<M, L>& map,
boost::function<Y(const X&)> op) {
typedef DecisionTree<M, X> MX;
typedef typename MX::Leaf MXLeaf;
typedef typename MX::Choice MXChoice;
typedef typename MX::NodePtr MXNodePtr;
typedef DecisionTree<L, Y> LY;
// ugliness below because apparently we can't have templated virtual functions
// If leaf, apply unary conversion "op" and create a unique leaf
const MXLeaf* leaf = dynamic_cast<const MXLeaf*> (f.get());
if (leaf) return NodePtr(new Leaf(op(leaf->constant())));
// Check if Choice
boost::shared_ptr<const MXChoice> choice = boost::dynamic_pointer_cast<const MXChoice> (f);
if (!choice) throw std::invalid_argument(
"DecisionTree::Convert: Invalid NodePtr");
// get new label
M oldLabel = choice->label();
L newLabel = map.at(oldLabel);
// put together via Shannon expansion otherwise not sorted.
std::vector<LY> functions;
BOOST_FOREACH(const MXNodePtr& branch, choice->branches()) {
LY converted(convert<M, X>(branch, map, op));
functions += converted;
}
return LY::compose(functions.begin(), functions.end(), newLabel);
}
/*********************************************************************************/
template<typename L, typename Y>
bool DecisionTree<L, Y>::equals(const DecisionTree& other, double tol) const {
return root_->equals(*other.root_, tol);
}
template<typename L, typename Y>
void DecisionTree<L, Y>::print(const std::string& s) const {
root_->print(s);
}
template<typename L, typename Y>
bool DecisionTree<L, Y>::operator==(const DecisionTree& other) const {
return root_->equals(*other.root_);
}
template<typename L, typename Y>
const Y& DecisionTree<L, Y>::operator()(const Assignment<L>& x) const {
return root_->operator ()(x);
}
template<typename L, typename Y>
DecisionTree<L, Y> DecisionTree<L, Y>::apply(const Unary& op) const {
return DecisionTree(root_->apply(op));
}
/*********************************************************************************/
template<typename L, typename Y>
DecisionTree<L, Y> DecisionTree<L, Y>::apply(const DecisionTree& g,
const Binary& op) const {
// apply the operaton on the root of both diagrams
NodePtr h = root_->apply_f_op_g(*g.root_, op);
// create a new class with the resulting root "h"
DecisionTree result(h);
return result;
}
/*********************************************************************************/
// The way this works:
// We have an ADT, picture it as a tree.
// At a certain depth, we have a branch on "label".
// The function "choose(label,index)" will return a tree of one less depth,
// where there is no more branch on "label": only the subtree under that
// branch point corresponding to the value "index" is left instead.
// The function below get all these smaller trees and "ops" them together.
template<typename L, typename Y>
DecisionTree<L, Y> DecisionTree<L, Y>::combine(const L& label,
size_t cardinality, const Binary& op) const {
DecisionTree result = choose(label, 0);
for (size_t index = 1; index < cardinality; index++) {
DecisionTree chosen = choose(label, index);
result = result.apply(chosen, op);
}
return result;
}
/*********************************************************************************/
template<typename L, typename Y>
void DecisionTree<L, Y>::dot(std::ostream& os, bool showZero) const {
os << "digraph G {\n";
root_->dot(os, showZero);
os << " [ordering=out]}" << std::endl;
}
template<typename L, typename Y>
void DecisionTree<L, Y>::dot(const std::string& name, bool showZero) const {
std::ofstream os((name + ".dot").c_str());
dot(os, showZero);
system(
("dot -Tpdf " + name + ".dot -o " + name + ".pdf >& /dev/null").c_str());
}
/*********************************************************************************/
} // namespace gtsam

View File

@ -0,0 +1,218 @@
/*
* @file DecisionTree.h
* @brief Decision Tree for use in DiscreteFactors
* @author Frank Dellaert
* @author Can Erdogan
* @date Jan 30, 2012
*/
#pragma once
#include <gtsam/discrete/Assignment.h>
#include <boost/function.hpp>
#include <iostream>
#include <vector>
#include <map>
namespace gtsam {
/**
* Algebraic Decision Trees
* L = label for variables
* Y = function range (any algebra), e.g., bool, int, double
*/
template<typename L, typename Y>
class DecisionTree {
public:
/** Handy typedefs for unary and binary function types */
typedef boost::function<Y(const Y&)> Unary;
typedef boost::function<Y(const Y&, const Y&)> Binary;
/** A label annotated with cardinality */
typedef std::pair<L,size_t> LabelC;
/** DD's consist of Leaf and Choice nodes, both subclasses of Node */
class Leaf;
class Choice;
/** ------------------------ Node base class --------------------------- */
class Node {
public:
typedef boost::shared_ptr<const Node> Ptr;
#ifdef DT_DEBUG_MEMORY
static int nrNodes;
#endif
// Constructor
Node() {
#ifdef DT_DEBUG_MEMORY
std::cout << ++nrNodes << " constructed " << id() << std::endl; std::cout.flush();
#endif
}
// Destructor
virtual ~Node() {
#ifdef DT_DEBUG_MEMORY
std::cout << --nrNodes << " destructed " << id() << std::endl; std::cout.flush();
#endif
}
// Unique ID for dot files
const void* id() const { return this; }
// everything else is virtual, no documentation here as internal
virtual void print(const std::string& s = "") const = 0;
virtual void dot(std::ostream& os, bool showZero) const = 0;
virtual bool sameLeaf(const Leaf& q) const = 0;
virtual bool sameLeaf(const Node& q) const = 0;
virtual bool equals(const Node& other, double tol = 1e-9) const = 0;
virtual const Y& operator()(const Assignment<L>& x) const = 0;
virtual Ptr apply(const Unary& op) const = 0;
virtual Ptr apply_f_op_g(const Node&, const Binary&) const = 0;
virtual Ptr apply_g_op_fL(const Leaf&, const Binary&) const = 0;
virtual Ptr apply_g_op_fC(const Choice&, const Binary&) const = 0;
virtual Ptr choose(const L& label, size_t index) const = 0;
virtual bool isLeaf() const = 0;
};
/** ------------------------ Node base class --------------------------- */
public:
/** A function is a shared pointer to the root of an ADD */
typedef typename Node::Ptr NodePtr;
/* an AlgebraicDecisionTree just contains the root */
NodePtr root_;
protected:
/** Internal recursive function to create from keys, cardinalities, and Y values */
template<typename It, typename ValueIt>
NodePtr create(It begin, It end, ValueIt beginY, ValueIt endY) const;
/** Convert to a different type */
template<typename M, typename X> NodePtr
convert(const typename DecisionTree<M, X>::NodePtr& f, const std::map<M,
L>& map, boost::function<Y(const X&)> op);
/** Default constructor */
DecisionTree();
public:
/// @name Standard Constructors
/// @{
/** Create a constant */
DecisionTree(const Y& y);
/** Create a new leaf function splitting on a variable */
DecisionTree(const L& label, const Y& y1, const Y& y2);
/** Allow Label+Cardinality for convenience */
DecisionTree(const LabelC& label, const Y& y1, const Y& y2);
/** Create from keys and string table */
DecisionTree(const std::vector<LabelC>& labelCs, const std::vector<Y>& ys);
/** Create from keys and string table */
DecisionTree(const std::vector<LabelC>& labelCs, const std::string& table);
/** Create DecisionTree from others */
template<typename Iterator>
DecisionTree(Iterator begin, Iterator end, const L& label);
/** Create DecisionTree from others others (binary version) */
DecisionTree(const L& label, //
const DecisionTree& f0, const DecisionTree& f1);
/** Convert from a different type */
template<typename M, typename X>
DecisionTree(const DecisionTree<M, X>& other,
const std::map<M, L>& map, boost::function<Y(const X&)> op);
/// @}
/// @name Testable
/// @{
/** GTSAM-style print */
void print(const std::string& s = "DecisionTree") const;
// Testable
bool equals(const DecisionTree& other, double tol = 1e-9) const;
/// @}
/// @name Standard Interface
/// @{
/** Make virtual */
virtual ~DecisionTree() {
}
/** equality */
bool operator==(const DecisionTree& q) const;
/** evaluate */
const Y& operator()(const Assignment<L>& x) const;
/** apply Unary operation "op" to f */
DecisionTree apply(const Unary& op) const;
/** apply binary operation "op" to f and g */
DecisionTree apply(const DecisionTree& g, const Binary& op) const;
/** create a new function where value(label)==index */
DecisionTree choose(const L& label, size_t index) const {
NodePtr newRoot = root_->choose(label, index);
return DecisionTree(newRoot);
}
/** combine subtrees on key with binary operation "op" */
DecisionTree combine(const L& label, size_t cardinality, const Binary& op) const;
/** combine with LabelC for convenience */
DecisionTree combine(const LabelC& labelC, const Binary& op) const {
return combine(labelC.first, labelC.second, op);
}
/** output to graphviz format, stream version */
void dot(std::ostream& os, bool showZero = true) const;
/** output to graphviz format, open a file */
void dot(const std::string& name, bool showZero = true) const;
/// @name Advanced Interface
/// @{
// internal use only
DecisionTree(const NodePtr& root);
// internal use only
template<typename Iterator> NodePtr
compose(Iterator begin, Iterator end, const L& label) const;
/// @}
}; // DecisionTree
/** free versions of apply */
template<typename Y, typename L>
DecisionTree<L, Y> apply(const DecisionTree<L, Y>& f,
const typename DecisionTree<L, Y>::Unary& op) {
return f.apply(op);
}
template<typename Y, typename L>
DecisionTree<L, Y> apply(const DecisionTree<L, Y>& f,
const DecisionTree<L, Y>& g,
const typename DecisionTree<L, Y>::Binary& op) {
return f.apply(g, op);
}
} // namespace gtsam

View File

@ -0,0 +1,91 @@
/*
* DecisionTreeFactor.cpp
* @brief: discrete factor
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/base/FastSet.h>
#include <boost/foreach.hpp>
using namespace std;
namespace gtsam {
/* ******************************************************************************** */
DecisionTreeFactor::DecisionTreeFactor() {
}
/* ******************************************************************************** */
DecisionTreeFactor::DecisionTreeFactor(const DiscreteKeys& keys,
const ADT& potentials) :
DiscreteFactor(keys.indices()), Potentials(keys, potentials) {
}
/* *************************************************************************/
DecisionTreeFactor::DecisionTreeFactor(const DiscreteConditional& c) :
DiscreteFactor(c.keys()), Potentials(c) {
}
/* ************************************************************************* */
bool DecisionTreeFactor::equals(const This& other, double tol) const {
return IndexFactor::equals(other, tol) && Potentials::equals(other, tol);
}
/* ************************************************************************* */
void DecisionTreeFactor::print(const string& s) const {
cout << s << ":\n";
IndexFactor::print("IndexFactor:");
Potentials::print("Potentials:");
}
/* ************************************************************************* */
DecisionTreeFactor DecisionTreeFactor::apply //
(const DecisionTreeFactor& f, ADT::Binary op) const {
map<Index,size_t> cs; // new cardinalities
// make unique key-cardinality map
BOOST_FOREACH(Index j, keys()) cs[j] = cardinality(j);
BOOST_FOREACH(Index j, f.keys()) cs[j] = f.cardinality(j);
// Convert map into keys
DiscreteKeys keys;
BOOST_FOREACH(const DiscreteKey& key, cs)
keys.push_back(key);
// apply operand
ADT result = ADT::apply(f, op);
// Make a new factor
return DecisionTreeFactor(keys, result);
}
/* ************************************************************************* */
DecisionTreeFactor::shared_ptr DecisionTreeFactor::combine //
(size_t nrFrontals, ADT::Binary op) const {
if (nrFrontals == 0 || nrFrontals > size()) throw invalid_argument(
(boost::format(
"DecisionTreeFactor::combine: invalid number of frontal keys %d, nr.keys=%d")
% nrFrontals % size()).str());
// sum over nrFrontals keys
size_t i;
ADT result(*this);
for (i = 0; i < nrFrontals; i++) {
Index j = keys()[i];
result = result.combine(j, cardinality(j), op);
}
// create new factor, note we start keys after nrFrontals
DiscreteKeys dkeys;
for (; i < keys().size(); i++) {
Index j = keys()[i];
dkeys.push_back(DiscreteKey(j,cardinality(j)));
}
shared_ptr f(new DecisionTreeFactor(dkeys, result));
return f;
}
/* ************************************************************************* */
} // namespace gtsam

View File

@ -0,0 +1,145 @@
/*
* DecisionTreeFactor.h
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
#pragma once
#include <gtsam/discrete/DiscreteFactor.h>
#include <gtsam/discrete/Potentials.h>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <exception>
#include <stdexcept>
namespace gtsam {
class DiscreteConditional;
/**
* A discrete probabilistic factor
*/
class DecisionTreeFactor: public DiscreteFactor, public Potentials {
public:
// typedefs needed to play nice with gtsam
typedef DecisionTreeFactor This;
typedef DiscreteConditional ConditionalType;
typedef boost::shared_ptr<DecisionTreeFactor> shared_ptr;
public:
/// @name Standard Constructors
/// @{
/** Default constructor for I/O */
DecisionTreeFactor();
/** Constructor from Indices, Ordering, and AlgebraicDecisionDiagram */
DecisionTreeFactor(const DiscreteKeys& keys, const ADT& potentials);
/** Constructor from Indices and (string or doubles) */
template<class SOURCE>
DecisionTreeFactor(const DiscreteKeys& keys, SOURCE table) :
DiscreteFactor(keys.indices()), Potentials(keys, table) {
}
/** Construct from a DiscreteConditional type */
DecisionTreeFactor(const DiscreteConditional& c);
/// @}
/// @name Testable
/// @{
/// equality
bool equals(const DecisionTreeFactor& other, double tol = 1e-9) const;
// print
void print(const std::string& s = "DecisionTreeFactor: ") const;
/// @}
/// @name Standard Interface
/// @{
/// Value is just look up in AlgebraicDecisonTree
virtual double operator()(const Values& values) const {
return Potentials::operator()(values);
}
/// multiply two factors
DecisionTreeFactor operator*(const DecisionTreeFactor& f) const {
return apply(f, ADT::Ring::mul);
}
/// divide by factor f (safely)
DecisionTreeFactor operator/(const DecisionTreeFactor& f) const {
return apply(f, safe_div);
}
/// Convert into a decisiontree
virtual operator DecisionTreeFactor() const {
return *this;
}
/// Create new factor by summing all values with the same separator values
shared_ptr sum(size_t nrFrontals) const {
return combine(nrFrontals, ADT::Ring::add);
}
/// Create new factor by maximizing over all values with the same separator values
shared_ptr max(size_t nrFrontals) const {
return combine(nrFrontals, ADT::Ring::max);
}
/// @}
/// @name Advanced Interface
/// @{
/**
* Apply binary operator (*this) "op" f
* @param f the second argument for op
* @param op a binary operator that operates on AlgebraicDecisionDiagram potentials
*/
DecisionTreeFactor apply(const DecisionTreeFactor& f, ADT::Binary op) const;
/**
* Combine frontal variables using binary operator "op"
* @param nrFrontals nr. of frontal to combine variables in this factor
* @param op a binary operator that operates on AlgebraicDecisionDiagram potentials
* @return shared pointer to newly created DecisionTreeFactor
*/
shared_ptr combine(size_t nrFrontals, ADT::Binary op) const;
/*
* Ensure Arc-consistency
* @param j domain to be checked
* @param domains all other domains
*/
///
bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const {
// throw std::runtime_error(
// "DecisionTreeFactor::ensureArcConsistency not implemented");
return false;
}
/// Partially apply known values
virtual DiscreteFactor::shared_ptr partiallyApply(const Values&) const {
throw std::runtime_error("DecisionTreeFactor::partiallyApply not implemented");
}
/// Partially apply known values, domain version
virtual DiscreteFactor::shared_ptr partiallyApply(
const std::vector<Domain>&) const {
throw std::runtime_error("DecisionTreeFactor::partiallyApply not implemented");
}
/// @}
};
// DecisionTreeFactor
}// namespace gtsam

View File

@ -0,0 +1,48 @@
/*
* DiscreteBayesNet.cpp
*
* @date Feb 15, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#include <gtsam/discrete/DiscreteBayesNet.h>
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/inference/BayesNet-inl.h>
#include <boost/make_shared.hpp>
namespace gtsam {
// Explicitly instantiate so we don't have to include everywhere
template class BayesNet<DiscreteConditional> ;
/* ************************************************************************* */
void add_front(DiscreteBayesNet& bayesNet, const Signature& s) {
bayesNet.push_front(boost::make_shared<DiscreteConditional>(s));
}
/* ************************************************************************* */
void add(DiscreteBayesNet& bayesNet, const Signature& s) {
bayesNet.push_back(boost::make_shared<DiscreteConditional>(s));
}
/* ************************************************************************* */
DiscreteFactor::sharedValues optimize(const DiscreteBayesNet& bn) {
// solve each node in turn in topological sort order (parents first)
DiscreteFactor::sharedValues result(new DiscreteFactor::Values());
BOOST_REVERSE_FOREACH (DiscreteConditional::shared_ptr conditional, bn)
conditional->solveInPlace(*result);
return result;
}
/* ************************************************************************* */
DiscreteFactor::sharedValues sample(const DiscreteBayesNet& bn) {
// sample each node in turn in topological sort order (parents first)
DiscreteFactor::sharedValues result(new DiscreteFactor::Values());
BOOST_REVERSE_FOREACH(DiscreteConditional::shared_ptr conditional, bn)
conditional->sampleInPlace(*result);
return result;
}
/* ************************************************************************* */
} // namespace

View File

@ -0,0 +1,33 @@
/*
* DiscreteBayesNet.h
*
* @date Feb 15, 2011
* @author Duy-Nguyen Ta
*/
#pragma once
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <gtsam/inference/BayesNet.h>
#include <gtsam/discrete/DiscreteConditional.h>
namespace gtsam {
typedef BayesNet<DiscreteConditional> DiscreteBayesNet;
/** Add a DiscreteCondtional */
void add(DiscreteBayesNet&, const Signature& s);
/** Add a DiscreteCondtional in front, when listing parents first*/
void add_front(DiscreteBayesNet&, const Signature& s);
/** Optimize function for back-substitution. */
DiscreteFactor::sharedValues optimize(const DiscreteBayesNet& bn);
/** Do ancestral sampling */
DiscreteFactor::sharedValues sample(const DiscreteBayesNet& bn);
} // namespace

View File

@ -0,0 +1,152 @@
/*
* DiscreteConditional.cpp
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/discrete/Signature.h>
#include <gtsam/base/Testable.h>
#include <gtsam/base/debug.h>
#include <boost/make_shared.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <vector>
#include <algorithm>
#include <stdexcept>
using namespace std;
namespace gtsam {
/* ******************************************************************************** */
DiscreteConditional::DiscreteConditional(const size_t nrFrontals,
const DecisionTreeFactor& f) :
IndexConditional(f.keys(), nrFrontals), Potentials(
f / (*f.sum(nrFrontals))) {
}
/* ******************************************************************************** */
DiscreteConditional::DiscreteConditional(const DecisionTreeFactor& joint,
const DecisionTreeFactor& marginal) :
IndexConditional(joint.keys(), joint.size() - marginal.size()), Potentials(
ISDEBUG("DiscreteConditional::COUNT") ? joint : joint / marginal) {
assert(nrFrontals() == 1);
if (ISDEBUG("DiscreteConditional::DiscreteConditional")) cout
<< (firstFrontalKey()) << endl;
}
/* ******************************************************************************** */
DiscreteConditional::DiscreteConditional(const Signature& signature) :
IndexConditional(signature.indices(), 1), Potentials(
signature.discreteKeysParentsFirst(), signature.cpt()) {
}
/* ******************************************************************************** */
Potentials::ADT DiscreteConditional::choose(
const Values& parentsValues) const {
ADT pFS(*this);
BOOST_FOREACH(Index key, parents())
try {
Index j = (key);
size_t value = parentsValues.at(j);
pFS = pFS.choose(j, value);
} catch (exception& e) {
throw runtime_error(
"DiscreteConditional::choose: parent value missing");
};
return pFS;
}
/* ******************************************************************************** */
void DiscreteConditional::solveInPlace(Values& values) const {
assert(nrFrontals() == 1);
Index j = (firstFrontalKey());
size_t mpe = solve(values); // Solve for variable
values[j] = mpe; // store result in partial solution
}
/* ******************************************************************************** */
void DiscreteConditional::sampleInPlace(Values& values) const {
assert(nrFrontals() == 1);
Index j = (firstFrontalKey());
size_t sampled = sample(values); // Sample variable
values[j] = sampled; // store result in partial solution
}
/* ******************************************************************************** */
size_t DiscreteConditional::solve(const Values& parentsValues) const {
// TODO: is this really the fastest way? I think it is.
ADT pFS = choose(parentsValues); // P(F|S=parentsValues)
// Then, find the max over all remaining
// TODO, only works for one key now, seems horribly slow this way
size_t mpe = 0;
Values frontals;
double maxP = 0;
assert(nrFrontals() == 1);
Index j = (firstFrontalKey());
for (size_t value = 0; value < cardinality(j); value++) {
frontals[j] = value;
double pValueS = pFS(frontals); // P(F=value|S=parentsValues)
// Update MPE solution if better
if (pValueS > maxP) {
maxP = pValueS;
mpe = value;
}
}
return mpe;
}
/* ******************************************************************************** */
size_t DiscreteConditional::sample(const Values& parentsValues) const {
using boost::uniform_real;
static boost::mt19937 gen(2); // random number generator
bool debug = ISDEBUG("DiscreteConditional::sample");
// Get the correct conditional density
ADT pFS = choose(parentsValues); // P(F|S=parentsValues)
if (debug) GTSAM_PRINT(pFS);
// get cumulative distribution function (cdf)
// TODO, only works for one key now, seems horribly slow this way
assert(nrFrontals() == 1);
Index j = (firstFrontalKey());
size_t nj = cardinality(j);
vector<double> cdf(nj);
Values frontals;
double sum = 0;
for (size_t value = 0; value < nj; value++) {
frontals[j] = value;
double pValueS = pFS(frontals); // P(F=value|S=parentsValues)
sum += pValueS; // accumulate
if (debug) cout << sum << " ";
if (pValueS == 1) {
if (debug) cout << "--> " << value << endl;
return value; // shortcut exit
}
cdf[value] = sum;
}
// inspired by http://www.boost.org/doc/libs/1_46_1/doc/html/boost_random/tutorial.html
uniform_real<> dist(0, cdf.back());
boost::variate_generator<boost::mt19937&, uniform_real<> > die(gen, dist);
size_t sampled = lower_bound(cdf.begin(), cdf.end(), die()) - cdf.begin();
if (debug) cout << "-> " << sampled << endl;
return sampled;
return 0;
}
/* ******************************************************************************** */
} // namespace

View File

@ -0,0 +1,110 @@
/*
* DiscreteConditional.h
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/Signature.h>
#include <gtsam/inference/IndexConditional.h>
#include <boost/shared_ptr.hpp>
namespace gtsam {
/**
* Discrete Conditional Density
* Derives from DecisionTreeFactor
*/
class DiscreteConditional: public IndexConditional, public Potentials {
public:
// typedefs needed to play nice with gtsam
typedef DiscreteFactor FactorType;
typedef boost::shared_ptr<DiscreteConditional> shared_ptr;
typedef IndexConditional Base;
/** A map from keys to values */
typedef Assignment<Index> Values;
typedef boost::shared_ptr<Values> sharedValues;
/// @name Standard Constructors
/// @{
/** default constructor needed for serialization */
DiscreteConditional() {
}
/** constructor from factor */
DiscreteConditional(size_t nFrontals, const DecisionTreeFactor& f);
/** Construct from signature */
DiscreteConditional(const Signature& signature);
/** construct P(X|Y)=P(X,Y)/P(Y) from P(X,Y) and P(Y) */
DiscreteConditional(const DecisionTreeFactor& joint,
const DecisionTreeFactor& marginal);
/// @}
/// @name Testable
/// @{
/** GTSAM-style print */
void print(const std::string& s = "Discrete Conditional: ") const {
std::cout << s << std::endl;
IndexConditional::print(s);
Potentials::print(s);
}
/** GTSAM-style equals */
bool equals(const DiscreteConditional& other, double tol = 1e-9) const {
return IndexConditional::equals(other, tol)
&& Potentials::equals(other, tol);
}
/// @}
/// @name Standard Interface
/// @{
/** Convert to a factor */
DecisionTreeFactor::shared_ptr toFactor() const {
return DecisionTreeFactor::shared_ptr(new DecisionTreeFactor(*this));
}
/** Restrict to given parent values, returns AlgebraicDecisionDiagram */
ADT choose(const Assignment<Index>& parentsValues) const;
/**
* solve a conditional
* @param parentsAssignment Known values of the parents
* @return MPE value of the child (1 frontal variable).
*/
size_t solve(const Values& parentsValues) const;
/**
* sample
* @param parentsAssignment Known values of the parents
* @return sample from conditional
*/
size_t sample(const Values& parentsValues) const;
/// @}
/// @name Advanced Interface
/// @{
/// solve a conditional, in place
void solveInPlace(Values& parentsValues) const;
/// sample in place, stores result in partial solution
void sampleInPlace(Values& parentsValues) const;
/// @}
};
// DiscreteConditional
}// gtsam

View File

@ -0,0 +1,21 @@
/*
* DiscreteFactor.cpp
* @brief: discrete factor
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#include <gtsam/discrete/DiscreteFactor.h>
#include <boost/foreach.hpp>
using namespace std;
namespace gtsam {
/* ******************************************************************************** */
DiscreteFactor::DiscreteFactor() {
}
/* ************************************************************************* */
} // namespace gtsam

View File

@ -0,0 +1,108 @@
/*
* DiscreteFactor.h
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
#pragma once
#include <gtsam/discrete/Assignment.h>
#include <gtsam/inference/IndexFactor.h>
namespace gtsam {
class DecisionTreeFactor;
class DiscreteConditional;
class Domain;
/**
* Base class for discrete probabilistic factors
* The most general one is the derived DecisionTreeFactor
*/
class DiscreteFactor: public IndexFactor {
public:
// typedefs needed to play nice with gtsam
typedef DiscreteFactor This;
typedef DiscreteConditional ConditionalType;
typedef boost::shared_ptr<DiscreteFactor> shared_ptr;
/** A map from keys to values */
typedef Assignment<Index> Values;
typedef boost::shared_ptr<Values> sharedValues;
protected:
/// Construct n-way factor
DiscreteFactor(const std::vector<Index>& js) :
IndexFactor(js) {
}
/// Construct unary factor
DiscreteFactor(Index j) :
IndexFactor(j) {
}
/// Construct binary factor
DiscreteFactor(Index j1, Index j2) :
IndexFactor(j1, j2) {
}
/// construct from container
template<class KeyIterator>
DiscreteFactor(KeyIterator beginKey, KeyIterator endKey) :
IndexFactor(beginKey, endKey) {
}
public:
/// @name Standard Constructors
/// @{
/// Default constructor for I/O
DiscreteFactor();
/// Virtual destructor
virtual ~DiscreteFactor() {}
/// @}
/// @name Testable
/// @{
// print
virtual void print(const std::string& s = "DiscreteFactor") const {
IndexFactor::print(s);
}
/// @}
/// @name Standard Interface
/// @{
/// Find value for given assignment of values to variables
virtual double operator()(const Values&) const = 0;
/// Multiply in a DecisionTreeFactor and return the result as DecisionTreeFactor
virtual DecisionTreeFactor operator*(const DecisionTreeFactor&) const = 0;
virtual operator DecisionTreeFactor() const = 0;
/*
* Ensure Arc-consistency
* @param j domain to be checked
* @param domains all other domains
*/
virtual bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const = 0;
/// Partially apply known values
virtual shared_ptr partiallyApply(const Values&) const = 0;
/// Partially apply known values, domain version
virtual shared_ptr partiallyApply(const std::vector<Domain>&) const = 0;
/// @}
};
// DiscreteFactor
}// namespace gtsam

View File

@ -0,0 +1,82 @@
/*
* DiscreteFactorGraph.cpp
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
//#define ENABLE_TIMING
#include <gtsam/discrete/DiscreteFactorGraph.h>
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/inference/EliminationTree-inl.h>
#include <boost/make_shared.hpp>
namespace gtsam {
// Explicitly instantiate so we don't have to include everywhere
template class FactorGraph<DiscreteFactor> ;
template class EliminationTree<DiscreteFactor> ;
/* ************************************************************************* */
DiscreteFactorGraph::DiscreteFactorGraph() {
}
/* ************************************************************************* */
DiscreteFactorGraph::DiscreteFactorGraph(
const BayesNet<DiscreteConditional>& bayesNet) :
FactorGraph<DiscreteFactor>(bayesNet) {
}
/* ************************************************************************* */
FastSet<Index> DiscreteFactorGraph::keys() const {
FastSet<Index> keys;
BOOST_FOREACH(const sharedFactor& factor, *this)
if (factor) keys.insert(factor->begin(), factor->end());
return keys;
}
/* ************************************************************************* */
DecisionTreeFactor DiscreteFactorGraph::product() const {
DecisionTreeFactor result;
BOOST_FOREACH(const sharedFactor& factor, *this)
if (factor) result = (*factor) * result;
return result;
}
/* ************************************************************************* */
double DiscreteFactorGraph::operator()(
const DiscreteFactor::Values &values) const {
double product = 1.0;
BOOST_FOREACH( const sharedFactor& factor, factors_ )
product *= (*factor)(values);
return product;
}
/* ************************************************************************* */
pair<DiscreteConditional::shared_ptr, DecisionTreeFactor::shared_ptr> //
EliminateDiscrete(const FactorGraph<DiscreteFactor>& factors, size_t num) {
// PRODUCT: multiply all factors
tic(1, "product");
DecisionTreeFactor product;
BOOST_FOREACH(const DiscreteFactor::shared_ptr& factor, factors)
product = (*factor) * product;
toc(1, "product");
// sum out frontals, this is the factor on the separator
tic(2, "sum");
DecisionTreeFactor::shared_ptr sum = product.sum(num);
toc(2, "sum");
// now divide product/sum to get conditional
tic(3, "divide");
DiscreteConditional::shared_ptr cond(new DiscreteConditional(product, *sum));
toc(3, "divide");
tictoc_finishedIteration();
return make_pair(cond, sum);
}
/* ************************************************************************* */
} // namespace

View File

@ -0,0 +1,87 @@
/*
* DiscreteFactorGraph.h
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
#pragma once
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/DiscreteBayesNet.h>
#include <gtsam/inference/FactorGraph.h>
#include <gtsam/base/FastSet.h>
#include <boost/make_shared.hpp>
namespace gtsam {
class DiscreteFactorGraph: public FactorGraph<DiscreteFactor> {
public:
/** A map from keys to values */
typedef std::vector<Index> Indices;
typedef Assignment<Index> Values;
typedef boost::shared_ptr<Values> sharedValues;
/** Construct empty factor graph */
DiscreteFactorGraph();
/** Constructor from a factor graph of GaussianFactor or a derived type */
template<class DERIVEDFACTOR>
DiscreteFactorGraph(const FactorGraph<DERIVEDFACTOR>& fg) {
push_back(fg);
}
/** construct from a BayesNet */
DiscreteFactorGraph(const BayesNet<DiscreteConditional>& bayesNet);
template<class SOURCE>
void add(const DiscreteKey& j, SOURCE table) {
DiscreteKeys keys;
keys.push_back(j);
push_back(boost::make_shared<DecisionTreeFactor>(keys, table));
}
template<class SOURCE>
void add(const DiscreteKey& j1, const DiscreteKey& j2, SOURCE table) {
DiscreteKeys keys;
keys.push_back(j1);
keys.push_back(j2);
push_back(boost::make_shared<DecisionTreeFactor>(keys, table));
}
/** add shared discreteFactor immediately from arguments */
template<class SOURCE>
void add(const DiscreteKeys& keys, SOURCE table) {
push_back(boost::make_shared<DecisionTreeFactor>(keys, table));
}
/** Return the set of variables involved in the factors (set union) */
FastSet<Index> keys() const;
/** return product of all factors as a single factor */
DecisionTreeFactor product() const;
/** Evaluates the factor graph given values, returns the joint probability of the factor graph given specific instantiation of values*/
double operator()(const DiscreteFactor::Values & values) const;
/// print
void print(const std::string& s = "DiscreteFactorGraph") const {
std::cout << s << std::endl;
std::cout << "size: " << size() << std::endl;
for (size_t i = 0; i < factors_.size(); i++) {
std::stringstream ss;
ss << "factor " << i << ": ";
if (factors_[i] != NULL) factors_[i]->print(ss.str());
}
}
};
// DiscreteFactorGraph
/** Main elimination function for DiscreteFactorGraph */
std::pair<boost::shared_ptr<DiscreteConditional>, DecisionTreeFactor::shared_ptr>
EliminateDiscrete(const FactorGraph<DiscreteFactor>& factors,
size_t nrFrontals = 1);
} // namespace gtsam

View File

@ -0,0 +1,44 @@
/*
* DiscreteKey.h
* @brief specialized key for discrete variables
* @author Frank Dellaert
* @date Feb 28, 2011
*/
#include <iostream>
#include <boost/format.hpp> // for key names
#include <boost/foreach.hpp> // FOREACH
#include "DiscreteKey.h"
namespace gtsam {
using namespace std;
DiscreteKeys::DiscreteKeys(const vector<int>& cs) {
for (size_t i = 0; i < cs.size(); i++) {
string name = boost::str(boost::format("v%1%") % i);
push_back(DiscreteKey(i, cs[i]));
}
}
vector<Index> DiscreteKeys::indices() const {
vector < Index > js;
BOOST_FOREACH(const DiscreteKey& key, *this)
js.push_back(key.first);
return js;
}
map<Index,size_t> DiscreteKeys::cardinalities() const {
map<Index,size_t> cs;
cs.insert(begin(),end());
// BOOST_FOREACH(const DiscreteKey& key, *this)
// cs.insert(key);
return cs;
}
DiscreteKeys operator&(const DiscreteKey& key1, const DiscreteKey& key2) {
DiscreteKeys keys(key1);
return keys & key2;
}
}

View File

@ -0,0 +1,59 @@
/*
* DiscreteKey.h
* @brief specialized key for discrete variables
* @author Frank Dellaert
* @date Feb 28, 2011
*/
#pragma once
#include <gtsam/base/types.h>
#include <map>
#include <string>
#include <vector>
namespace gtsam {
/**
* Key type for discrete conditionals
* Includes name and cardinality
*/
typedef std::pair<Index,size_t> DiscreteKey;
/// DiscreteKeys is a set of keys that can be assembled using the & operator
struct DiscreteKeys: public std::vector<DiscreteKey> {
/// Default constructor
DiscreteKeys() {
}
/// Construct from a key
DiscreteKeys(const DiscreteKey& key) {
push_back(key);
}
/// Construct from a vector of keys
DiscreteKeys(const std::vector<DiscreteKey>& keys) :
std::vector<DiscreteKey>(keys) {
}
/// Construct from cardinalities with default names
DiscreteKeys(const std::vector<int>& cs);
/// Return a vector of indices
std::vector<Index> indices() const;
/// Return a map from index to cardinality
std::map<Index,size_t> cardinalities() const;
/// Add a key (non-const!)
DiscreteKeys& operator&(const DiscreteKey& key) {
push_back(key);
return *this;
}
}; // DiscreteKeys
/// Create a list from two keys
DiscreteKeys operator&(const DiscreteKey& key1, const DiscreteKey& key2);
}

View File

@ -0,0 +1,47 @@
/*
* DiscreteSequentialSolver.cpp
*
* @date Feb 16, 2011
* @author Duy-Nguyen Ta
*/
//#define ENABLE_TIMING
#include <gtsam/discrete/DiscreteSequentialSolver.h>
#include <gtsam/discrete/PotentialTable.h>
#include <gtsam/inference/GenericSequentialSolver-inl.h>
#include <gtsam/base/timing.h>
namespace gtsam {
template class GenericSequentialSolver<DiscreteFactor> ;
/* ************************************************************************* */
DiscreteFactor::sharedValues DiscreteSequentialSolver::optimize() const {
static const bool debug = false;
if (debug) this->factors_->print("DiscreteSequentialSolver, eliminating ");
if (debug) this->eliminationTree_->print(
"DiscreteSequentialSolver, elimination tree ");
// Eliminate using the elimination tree
tic(1, "eliminate");
DiscreteBayesNet::shared_ptr bayesNet = eliminate();
toc(1, "eliminate");
if (debug) bayesNet->print("DiscreteSequentialSolver, Bayes net ");
// Allocate the solution vector if it is not already allocated
// Back-substitute
tic(2, "optimize");
DiscreteFactor::sharedValues solution = gtsam::optimize(*bayesNet);
toc(2, "optimize");
if (debug) solution->print("DiscreteSequentialSolver, solution ");
return solution;
}
/* ************************************************************************* */
}

View File

@ -0,0 +1,97 @@
/*
* DiscreteSequentialSolver.h
*
* @date Feb 16, 2011
* @author Duy-Nguyen Ta
*/
#pragma once
#include <gtsam/discrete/DiscreteFactorGraph.h>
#include <gtsam/inference/GenericSequentialSolver.h>
#include <boost/shared_ptr.hpp>
namespace gtsam {
// The base class provides all of the needed functionality
class DiscreteSequentialSolver: public GenericSequentialSolver<DiscreteFactor> {
protected:
typedef GenericSequentialSolver<DiscreteFactor> Base;
typedef boost::shared_ptr<const DiscreteSequentialSolver> shared_ptr;
public:
/**
* The problem we are trying to solve (SUM or MPE).
*/
typedef enum {
BEL, // Belief updating (or conditional updating)
MPE, // Most-Probable-Explanation
MAP
// Maximum A Posteriori hypothesis
} ProblemType;
/**
* Construct the solver for a factor graph. This builds the elimination
* tree, which already does some of the work of elimination.
*/
DiscreteSequentialSolver(const FactorGraph<DiscreteFactor>& factorGraph) :
Base(factorGraph) {
}
/**
* Construct the solver with a shared pointer to a factor graph and to a
* VariableIndex. The solver will store these pointers, so this constructor
* is the fastest.
*/
DiscreteSequentialSolver(
const FactorGraph<DiscreteFactor>::shared_ptr& factorGraph,
const VariableIndex::shared_ptr& variableIndex) :
Base(factorGraph, variableIndex) {
}
const EliminationTree<DiscreteFactor>& eliminationTree() const {
return *eliminationTree_;
}
/**
* Eliminate the factor graph sequentially. Uses a column elimination tree
* to recursively eliminate.
*/
BayesNet<DiscreteConditional>::shared_ptr eliminate() const {
return Base::eliminate(&EliminateDiscrete);
}
#ifdef BROKEN
/**
* Compute the marginal joint over a set of variables, by integrating out
* all of the other variables. This function returns the result as a factor
* graph.
*/
DiscreteFactorGraph::shared_ptr jointFactorGraph(
const std::vector<Index>& js) const {
DiscreteFactorGraph::shared_ptr results(new DiscreteFactorGraph(
*Base::jointFactorGraph(js, &EliminateDiscrete)));
return results;
}
/**
* Compute the marginal density over a variable, by integrating out
* all of the other variables. This function returns the result as a factor.
*/
DiscreteFactor::shared_ptr marginalFactor(Index j) const {
return Base::marginalFactor(j, &EliminateDiscrete);
}
#endif
/**
* Compute the MPE solution of the DiscreteFactorGraph. This
* eliminates to create a BayesNet and then back-substitutes this BayesNet to
* obtain the solution.
*/
DiscreteFactor::sharedValues optimize() const;
};
} // gtsam

95
gtsam/discrete/Domain.cpp Normal file
View File

@ -0,0 +1,95 @@
/*
* Domain.cpp
* @brief Domain restriction constraint
* @date Feb 13, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/Domain.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/base/Testable.h>
#include <boost/make_shared.hpp>
namespace gtsam {
using namespace std;
/* ************************************************************************* */
void Domain::print(const string& s) const {
// cout << s << ": Domain on " << keys_[0] << " (j=" << keys_[0]
// << ") with values";
// BOOST_FOREACH (size_t v,values_) cout << " " << v;
// cout << endl;
BOOST_FOREACH (size_t v,values_) cout << v;
}
/* ************************************************************************* */
double Domain::operator()(const Values& values) const {
return contains(values.at(keys_[0]));
}
/* ************************************************************************* */
Domain::operator DecisionTreeFactor() const {
DiscreteKeys keys;
keys += DiscreteKey(keys_[0],cardinality_);
vector<double> table;
for (size_t i1 = 0; i1 < cardinality_; ++i1)
table.push_back(contains(i1));
DecisionTreeFactor converted(keys, table);
return converted;
}
/* ************************************************************************* */
DecisionTreeFactor Domain::operator*(const DecisionTreeFactor& f) const {
// TODO: can we do this more efficiently?
return DecisionTreeFactor(*this) * f;
}
/* ************************************************************************* */
bool Domain::ensureArcConsistency(size_t j, vector<Domain>& domains) const {
if (j != keys_[0]) throw invalid_argument("Domain check on wrong domain");
Domain& D = domains[j];
BOOST_FOREACH(size_t value, values_)
if (!D.contains(value)) throw runtime_error("Unsatisfiable");
D = *this;
return true;
}
/* ************************************************************************* */
bool Domain::checkAllDiff(const vector<Index> keys, vector<Domain>& domains) {
Index j = keys_[0];
// for all values in this domain
BOOST_FOREACH(size_t value, values_) {
// for all connected domains
BOOST_FOREACH(Index k, keys)
// if any domain contains the value we cannot make this domain singleton
if (k!=j && domains[k].contains(value))
goto found;
values_.clear();
values_.insert(value);
return true; // we changed it
found:;
}
return false; // we did not change it
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr Domain::partiallyApply(
const Values& values) const {
Values::const_iterator it = values.find(keys_[0]);
if (it != values.end() && !contains(it->second)) throw runtime_error(
"Domain::partiallyApply: unsatisfiable");
return boost::make_shared < Domain > (*this);
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr Domain::partiallyApply(
const vector<Domain>& domains) const {
const Domain& Dk = domains[keys_[0]];
if (Dk.isSingleton() && !contains(*Dk.begin())) throw runtime_error(
"Domain::partiallyApply: unsatisfiable");
return boost::make_shared < Domain > (Dk);
}
/* ************************************************************************* */
} // namespace gtsam

107
gtsam/discrete/Domain.h Normal file
View File

@ -0,0 +1,107 @@
/*
* Domain.h
* @brief Domain restriction constraint
* @date Feb 13, 2012
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/DiscreteKey.h>
#include <gtsam/discrete/DiscreteFactor.h>
namespace gtsam {
/**
* Domain restriction constraint
*/
class Domain: public DiscreteFactor {
size_t cardinality_; /// Cardinality
std::set<size_t> values_; /// allowed values
public:
typedef boost::shared_ptr<Domain> shared_ptr;
// Constructor on Discrete Key initializes an "all-allowed" domain
Domain(const DiscreteKey& dkey) :
DiscreteFactor(dkey.first), cardinality_(dkey.second) {
for (size_t v = 0; v < cardinality_; v++)
values_.insert(v);
}
// Constructor on Discrete Key with single allowed value
// Consider SingleValue constraint
Domain(const DiscreteKey& dkey, size_t v) :
DiscreteFactor(dkey.first), cardinality_(dkey.second) {
values_.insert(v);
}
/// Constructor
Domain(const Domain& other) :
DiscreteFactor(other.keys_[0]), values_(other.values_) {
}
/// insert a value, non const :-(
void insert(size_t value) {
values_.insert(value);
}
/// erase a value, non const :-(
void erase(size_t value) {
values_.erase(value);
}
size_t nrValues() const {
return values_.size();
}
bool isSingleton() const {
return nrValues() == 1;
}
size_t firstValue() const {
return *values_.begin();
}
// print
virtual void print(const std::string& s = "") const;
bool contains(size_t value) const {
return values_.count(value)>0;
}
/// Calculate value
virtual double operator()(const Values& values) const;
/// Convert into a decisiontree
virtual operator DecisionTreeFactor() const;
/// Multiply into a decisiontree
virtual DecisionTreeFactor operator*(const DecisionTreeFactor& f) const;
/*
* Ensure Arc-consistency
* @param j domain to be checked
* @param domains all other domains
*/
bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const;
/**
* Check for a value in domain that does not occur in any other connected domain.
* If found, we make this a singleton... Called in AllDiff::ensureArcConsistency
* @param keys connected domains through alldiff
*/
bool checkAllDiff(const std::vector<Index> keys, std::vector<Domain>& domains);
/// Partially apply known values
virtual DiscreteFactor::shared_ptr partiallyApply(
const Values& values) const;
/// Partially apply known values, domain version
virtual DiscreteFactor::shared_ptr partiallyApply(
const std::vector<Domain>& domains) const;
};
} // namespace gtsam

View File

@ -0,0 +1,162 @@
/*
* Potentials.cpp
*
* @date Feb 21, 2011
* @author Duy-Nguyen Ta
*/
#include <math.h>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <gtsam/discrete/PotentialTable.h>
using namespace std;
namespace gtsam {
/* ************************************************************************* */
void PotentialTable::Iterator::operator++() {
// note size_t is unsigned and i>=0 is always true, so strange-looking loop:
for (size_t i = size(); i--; ) {
if (++at(i) < cardinalities_[i])
return;
else
at(i) = 0;
}
}
/* ************************************************************************* */
size_t PotentialTable::computeTableSize(
const std::vector<size_t>& cardinalities) {
size_t tableSize = 1;
BOOST_FOREACH(const size_t c, cardinalities)
tableSize *= c;
return tableSize;
}
/* ************************************************************************* */
PotentialTable::PotentialTable(const std::vector<size_t>& cs) :
cardinalities_(cs), table_(computeTableSize(cs)) {
generateKeyFactors();
}
/* ************************************************************************* */
PotentialTable::PotentialTable(const std::vector<size_t>& cardinalities,
const Table& table) : cardinalities_(cardinalities),table_(table) {
generateKeyFactors();
}
/* ************************************************************************* */
PotentialTable::PotentialTable(const std::vector<size_t>& cardinalities,
const std::string& tableString) : cardinalities_(cardinalities) {
parse(tableString);
generateKeyFactors();
}
/* ************************************************************************* */
bool PotentialTable::equals(const PotentialTable& other, double tol) const {
//TODO: compare potentials in a more general sense with arbitrary order of keys???
if ((cardinalities_ == other.cardinalities_) && (table_.size()
== other.table_.size()) && (keyFactors_ == other.keyFactors_)) {
for (size_t i = 0; i < table_.size(); i++) {
if (fabs(table_[i] - other.table_[i]) > tol) {
return false;
}
return true;
}
}
return false;
}
/* ************************************************************************* */
void PotentialTable::print(const std::string& s) const {
cout << s << endl;
for (size_t i = 0; i < cardinalities_.size(); i++)
cout << boost::format("[%d,%d]") % cardinalities_[i] % keyFactors_[i] << " ";
cout << endl;
Iterator assignment(cardinalities_);
for (size_t idx = 0; idx < table_.size(); ++idx, ++assignment) {
for (size_t k = 0; k < assignment.size(); k++)
cout << assignment[k] << "\t\t";
cout << table_[idx] << endl;
}
}
/* ************************************************************************* */
const double& PotentialTable::operator()(const Assignment& var) const {
return table_[tableIndexFromAssignment(var)];
}
/* ************************************************************************* */
const double& PotentialTable::operator[](const size_t index) const {
return table_.at(index);
}
/* ************************************************************************* */
void PotentialTable::setPotential(const PotentialTable::Assignment& asg, const double potential) {
size_t idx = tableIndexFromAssignment(asg);
assert(idx<table_.size());
table_[idx] = potential;
}
/* ************************************************************************* */
void PotentialTable::setPotential(const size_t tableIndex, const double potential) {
assert(tableIndex<table_.size());
table_[tableIndex] = potential;
}
/* ************************************************************************* */
size_t PotentialTable::tableIndexFromAssignment(
const PotentialTable::Assignment& values) const {
size_t index = 0;
for (size_t i = 0; i < keyFactors_.size(); i++) {
index += keyFactors_[i] * values[i];
}
return index;
}
/* ************************************************************************* */
PotentialTable::Assignment PotentialTable::assignmentFromTableIndex(
const size_t idx) const {
assert(idx < table_.size());
Assignment values(cardinalities_);
Index processedIndex = idx;
for (size_t i = 0; i < keyFactors_.size(); i++) {
values[i] = processedIndex / keyFactors_[i];
processedIndex %= keyFactors_[i];
}
return values;
}
/* ************************************************************************* */
void PotentialTable::generateKeyFactors() {
size_t accumIndex = table_.size();
BOOST_FOREACH(size_t card, cardinalities_) {
accumIndex /= card;
keyFactors_.push_back(accumIndex);
}
}
/* ************************************************************************* */
void PotentialTable::parse(const std::string& tableString) {
// parse doubles
istringstream iss(tableString);
copy(istream_iterator<double> (iss), istream_iterator<double> (),
back_inserter(table_));
#ifndef NDEBUG
size_t expectedSize = computeTableSize(cardinalities_);
if (table_.size() != expectedSize) throw invalid_argument(
boost::str(
boost::format(
"String specification \"%s\" for table only contains %d doubles instead of %d")
% tableString % table_.size() % expectedSize));
#endif
}
} // namespace

View File

@ -0,0 +1,95 @@
/*
* Potentials.h
*
* @date Feb 21, 2011
* @author Duy-Nguyen Ta
*/
#ifndef POTENTIALS_H_
#define POTENTIALS_H_
#include <vector>
#include <set>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <gtsam/base/types.h>
namespace gtsam
{
/**
* PotentialTable holds the real-valued potentials for Factors or Conditionals
*/
class PotentialTable {
public:
typedef std::vector<double> Table; // container type for potentials f(x1,x2,..)
typedef std::vector<size_t> Cardinalities; // just a typedef
typedef std::vector<size_t> Assignment; // just a typedef
/**
* An assignment that can be incemented
*/
struct Iterator: std::vector<size_t> {
Cardinalities cardinalities_;
Iterator(const Cardinalities& cs):cardinalities_(cs) {
for(size_t i=0;i<cs.size();i++) push_back(0);
}
void operator++();
};
private:
std::vector<size_t> cardinalities_; // cardinalities of variables
Table table_; // Potential values of all instantiations of the variables, following the variables' order in vector Keys.
std::vector<size_t> keyFactors_; // factors to multiply a key's assignment with, to access the potential table
void generateKeyFactors();
void parse(const std::string& tableString);
public:
/** compute table size from variable cardinalities */
static size_t computeTableSize(const std::vector<size_t>& cardinalities);
/** construct an empty potential */
PotentialTable() {}
/** Dangerous empty n-ary potential. */
PotentialTable(const std::vector<size_t>& cardinalities);
/** n-ary potential. */
PotentialTable(const std::vector<size_t>& cardinalities,
const Table& table);
/** n-ary potential. */
PotentialTable(const std::vector<size_t>& cardinalities,
const std::string& tableString);
/** return iterator to first element */
Iterator begin() const { return Iterator(cardinalities_);}
/** equality */
bool equals(const PotentialTable& other, double tol = 1e-9) const;
/** print */
void print(const std::string& s = "Potential Table: ") const;
/** return cardinality of a variable */
size_t cardinality(size_t var) const { return cardinalities_[var]; }
size_t tableSize() const { return table_.size(); }
/** accessors to potential values in the table given the assignment */
const double& operator()(const Assignment& var) const;
const double& operator[](const size_t index) const;
void setPotential(const Assignment& asg, const double potential);
void setPotential(const size_t tableIndex, const double potential);
/** convert between assignment and where it is in the table */
size_t tableIndexFromAssignment(const Assignment& var) const;
Assignment assignmentFromTableIndex(const size_t i) const;
};
} // namespace
#endif /* POTENTIALS_H_ */

View File

@ -0,0 +1,53 @@
/*
* Potentials.cpp
* @date March 24, 2011
* @author Frank Dellaert
*/
#include <gtsam/discrete/Potentials.h>
#include <gtsam/discrete/DecisionTree-inl.h>
#include <boost/format.hpp>
using namespace std;
namespace gtsam {
// explicit instantiation
template class DecisionTree<Index, double> ;
template class AlgebraicDecisionTree<Index> ;
/* ************************************************************************* */
double Potentials::safe_div(const double& a, const double& b) {
// cout << boost::format("%g / %g = %g\n") % a % b % ((a == 0) ? 0 : (a / b));
// The use for safe_div is when we divide the product factor by the sum factor.
// If the product or sum is zero, we accord zero probability to the event.
return (a == 0 || b == 0) ? 0 : (a / b);
}
/* ******************************************************************************** */
Potentials::Potentials() :
ADT(1.0) {
}
/* ******************************************************************************** */
Potentials::Potentials(const DiscreteKeys& keys, const ADT& decisionTree) :
ADT(decisionTree), cardinalities_(keys.cardinalities()) {
}
/* ************************************************************************* */
bool Potentials::equals(const Potentials& other, double tol) const {
return ADT::equals(other, tol);
}
/* ************************************************************************* */
void Potentials::print(const string&s) const {
cout << s << "\n Cardinalities: ";
BOOST_FOREACH(const DiscreteKey& key, cardinalities_)
cout << key.first << "=" << key.second << " ";
cout << endl;
ADT::print(" ");
}
/* ************************************************************************* */
} // namespace gtsam

View File

@ -0,0 +1,62 @@
/*
* Potentials.h
* @date March 24, 2011
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/AlgebraicDecisionTree.h>
#include <gtsam/discrete/DiscreteKey.h>
#include <gtsam/base/types.h>
#include <boost/shared_ptr.hpp>
#include <set>
namespace gtsam {
/**
* A base class for both DiscreteFactor and DiscreteConditional
*/
class Potentials: public AlgebraicDecisionTree<Index> {
public:
typedef AlgebraicDecisionTree<Index> ADT;
protected:
/// Cardinality for each key, used in combine
std::map<Index,size_t> cardinalities_;
/** Constructor from ColumnIndex, and ADT */
Potentials(const ADT& potentials) :
ADT(potentials) {
}
// Safe division for probabilities
static double safe_div(const double& a, const double& b);
public:
/** Default constructor for I/O */
Potentials();
/** Constructor from Indices and ADT */
Potentials(const DiscreteKeys& keys, const ADT& decisionTree);
/** Constructor from Indices and (string or doubles) */
template<class SOURCE>
Potentials(const DiscreteKeys& keys, SOURCE table) :
ADT(keys, table), cardinalities_(keys.cardinalities()) {
}
// Testable
bool equals(const Potentials& other, double tol = 1e-9) const;
void print(const std::string& s = "Potentials: ") const;
size_t cardinality(Index j) const { return cardinalities_.at(j);}
}; // Potentials
} // namespace gtsam

View File

@ -0,0 +1,9 @@
/*
* @file RefCounted.cpp
* @brief Simple reference-counted base class
* @author Frank Dellaert
* @date Mar 29, 2011
*/
#include <gtsam/discrete/RefCounted.h>

View File

@ -0,0 +1,86 @@
/*
* @file RefCounted.h
* @brief Simple reference-counted base class
* @author Frank Dellaert
* @date Mar 29, 2011
*/
#include <boost/intrusive_ptr.hpp>
// Forward Declarations
namespace gtsam {
struct RefCounted;
}
namespace boost {
void intrusive_ptr_add_ref(const gtsam::RefCounted * p);
void intrusive_ptr_release(const gtsam::RefCounted * p);
}
namespace gtsam {
/**
* Simple reference counted class inspired by
* http://www.codeproject.com/KB/stl/boostsmartptr.aspx
*/
struct RefCounted {
private:
mutable long references_;
friend void ::boost::intrusive_ptr_add_ref(const RefCounted * p);
friend void ::boost::intrusive_ptr_release(const RefCounted * p);
public:
RefCounted() :
references_(0) {
}
virtual ~RefCounted() {
}
};
} // namespace gtsam
// Intrusive Pointer free functions
#ifndef DEBUG_REFCOUNT
namespace boost {
// increment reference count of object *p
inline void intrusive_ptr_add_ref(const gtsam::RefCounted * p) {
++(p->references_);
}
// decrement reference count, and delete object when reference count reaches 0
inline void intrusive_ptr_release(const gtsam::RefCounted * p) {
if (--(p->references_) == 0)
delete p;
}
} // namespace boost
#else
#include <iostream>
namespace gtsam {
static long GlobalRefCount = 0;
}
namespace boost {
inline void intrusive_ptr_add_ref(const gtsam::RefCounted * p) {
++(p->references_);
gtsam::GlobalRefCount++;
std::cout << "add_ref " << p << " " << p->references_ << //
" " << gtsam::GlobalRefCount << std::endl;
}
inline void intrusive_ptr_release(const gtsam::RefCounted * p) {
gtsam::GlobalRefCount--;
std::cout << "release " << p << " " << (p->references_ - 1) << //
" " << gtsam::GlobalRefCount << std::endl;
if (--(p->references_) == 0)
delete p;
}
} // namespace boost
#endif

View File

@ -0,0 +1,297 @@
/*
* Scheduler.h
* @brief an example how inference can be used for scheduling qualifiers
* @date Mar 26, 2011
* @author Frank Dellaert
*/
#include <gtsam/discrete/Scheduler.h>
#include <gtsam/discrete/DiscreteFactorGraph.h>
#include <gtsam/discrete/DiscreteSequentialSolver.h>
#include <gtsam/base/debug.h>
#include <gtsam/base/timing.h>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <fstream>
#include <iomanip>
#include <cmath>
namespace gtsam {
using namespace std;
Scheduler::Scheduler(size_t maxNrStudents, const string& filename):
maxNrStudents_(maxNrStudents)
{
typedef boost::tokenizer<boost::escaped_list_separator<char> > Tokenizer;
// open file
ifstream is(filename.c_str());
string line; // buffer
// process first line with faculty
if (getline(is, line, '\r')) {
Tokenizer tok(line);
Tokenizer::iterator it = tok.begin();
for (++it; it != tok.end(); ++it)
addFaculty(*it);
}
// for all remaining lines
size_t count = 0;
while (getline(is, line, '\r')) {
if (count++ > 100) throw runtime_error("reached 100 lines, exiting");
Tokenizer tok(line);
Tokenizer::iterator it = tok.begin();
addSlot(*it++); // add slot
// add availability
for (; it != tok.end(); ++it)
available_ += (it->empty()) ? "0 " : "1 ";
available_ += '\n';
}
} // constructor
/** addStudent has to be called after adding slots and faculty */
void Scheduler::addStudent(const string& studentName,
const string& area1, const string& area2,
const string& area3, const string& advisor) {
assert(nrStudents()<maxNrStudents_);
assert(facultyInArea_.count(area1));
assert(facultyInArea_.count(area2));
assert(facultyInArea_.count(area3));
size_t advisorIndex = facultyIndex_[advisor];
Student student(nrFaculty(), advisorIndex);
student.name_ = studentName;
// We fix the ordering by assigning a higher index to the student
// and numbering the areas lower
Index j = 3*maxNrStudents_ + nrStudents();
student.key_ = DiscreteKey(j, nrTimeSlots());
Index base = 3*nrStudents();
student.keys_[0] = DiscreteKey(base+0, nrFaculty());
student.keys_[1] = DiscreteKey(base+1, nrFaculty());
student.keys_[2] = DiscreteKey(base+2, nrFaculty());
student.areaName_[0] = area1;
student.areaName_[1] = area2;
student.areaName_[2] = area3;
students_.push_back(student);
}
/** get key for student and area, 0 is time slot itself */
const DiscreteKey& Scheduler::key(size_t s, boost::optional<size_t> area) const {
return area ? students_[s].keys_[*area] : students_[s].key_;
}
const string& Scheduler::studentName(size_t i) const {
assert(i<nrStudents());
return students_[i].name_;
}
const DiscreteKey& Scheduler::studentKey(size_t i) const {
assert(i<nrStudents());
return students_[i].key_;
}
const string& Scheduler::studentArea(size_t i, size_t area) const {
assert(i<nrStudents());
return students_[i].areaName_[area];
}
/** Add student-specific constraints to the graph */
void Scheduler::addStudentSpecificConstraints(size_t i, boost::optional<size_t> slot) {
bool debug = ISDEBUG("Scheduler::buildGraph");
assert(i<nrStudents());
const Student& s = students_[i];
if (!slot && !slotsAvailable_.empty()) {
if (debug) cout << "Adding availability of slots" << endl;
DiscreteFactorGraph::add(s.key_, slotsAvailable_);
}
// For all areas
for (size_t area = 0; area < 3; area++) {
DiscreteKey areaKey = s.keys_[area];
const string& areaName = s.areaName_[area];
if (debug) cout << "Area constraints " << areaName << endl;
DiscreteFactorGraph::add(areaKey, facultyInArea_[areaName]);
if (debug) cout << "Advisor constraint " << areaName << endl;
DiscreteFactorGraph::add(areaKey, s.advisor_);
if (debug) cout << "Availability of faculty " << areaName << endl;
if (slot) {
// get all constraints then specialize to slot
DiscreteKey dummy(0, nrTimeSlots());
Potentials::ADT p(dummy & areaKey, available_);
Potentials::ADT q = p.choose(0, *slot);
DecisionTreeFactor::shared_ptr f(new DecisionTreeFactor(areaKey, q));
DiscreteFactorGraph::push_back(f);
} else {
DiscreteFactorGraph::add(s.key_, areaKey, available_);
}
}
// add mutex
if (debug) cout << "Mutex for faculty" << endl;
addAllDiff(s.keys_[0] & s.keys_[1] & s.keys_[2]);
} // students loop
/** Main routine that builds factor graph */
void Scheduler::buildGraph(size_t mutexBound) {
bool debug = ISDEBUG("Scheduler::buildGraph");
if (debug) cout << "Adding student-specific constraints" << endl;
for (size_t i = 0; i < nrStudents(); i++)
addStudentSpecificConstraints(i);
// special constraint for MN
if (studentName(0) == "Michael N") DiscreteFactorGraph::add(studentKey(0),
"0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1");
if (!mutexBound) {
DiscreteKeys dkeys;
BOOST_FOREACH(const Student& s, students_)
dkeys.push_back(s.key_);
addAllDiff(dkeys);
} else {
if (debug) cout << "Mutex for Students" << endl;
for (size_t i1 = 0; i1 < nrStudents(); i1++) {
// if mutexBound=1, we only mutex with next student
size_t bound = min((i1 + 1 + mutexBound), nrStudents());
for (size_t i2 = i1 + 1; i2 < bound; i2++) {
addAllDiff(studentKey(i1), studentKey(i2));
}
}
}
} // buildGraph
/** print */
void Scheduler::print(const string& s) const {
cout << s << " Faculty:" << endl;
BOOST_FOREACH(const string& name, facultyName_)
cout << name << '\n';
cout << endl;
cout << s << " Slots:\n";
size_t i = 0;
BOOST_FOREACH(const string& name, slotName_)
cout << i++ << " " << name << endl;
cout << endl;
cout << "Availability:\n" << available_ << '\n';
cout << s << " Area constraints:\n";
BOOST_FOREACH(const FacultyInArea::value_type& it, facultyInArea_)
{
cout << setw(12) << it.first << ": ";
BOOST_FOREACH(double v, it.second)
cout << v << " ";
cout << '\n';
}
cout << endl;
cout << s << " Students:\n";
BOOST_FOREACH (const Student& student, students_)
student.print();
cout << endl;
DiscreteFactorGraph::print(s + " Factor graph");
cout << endl;
} // print
/** Print readable form of assignment */
void Scheduler::printAssignment(sharedValues assignment) const {
// Not intended to be general! Assumes very particular ordering !
cout << endl;
for (size_t s = 0; s < nrStudents(); s++) {
Index j = 3*maxNrStudents_ + s;
size_t slot = assignment->at(j);
cout << studentName(s) << " slot: " << slotName_[slot] << endl;
Index base = 3*s;
for (size_t area = 0; area < 3; area++) {
size_t faculty = assignment->at(base+area);
cout << setw(12) << studentArea(s,area) << ": " << facultyName_[faculty]
<< endl;
}
cout << endl;
}
}
/** Special print for single-student case */
void Scheduler::printSpecial(sharedValues assignment) const {
Values::const_iterator it = assignment->begin();
for (size_t area = 0; area < 3; area++, it++) {
size_t f = it->second;
cout << setw(12) << it->first << ": " << facultyName_[f] << endl;
}
cout << endl;
}
/** Accumulate faculty stats */
void Scheduler::accumulateStats(sharedValues assignment, vector<
size_t>& stats) const {
for (size_t s = 0; s < nrStudents(); s++) {
Index base = 3*s;
for (size_t area = 0; area < 3; area++) {
size_t f = assignment->at(base+area);
assert(f<stats.size());
stats[f]++;
} // area
} // s
}
/** Eliminate, return a Bayes net */
DiscreteBayesNet::shared_ptr Scheduler::eliminate() const {
tic(1, "my_solver");
DiscreteSequentialSolver solver(*this);
toc(1, "my_solver");
tic(2, "my_eliminate");
DiscreteBayesNet::shared_ptr chordal = solver.eliminate();
toc(2, "my_eliminate");
return chordal;
}
/** Find the best total assignment - can be expensive */
Scheduler::sharedValues Scheduler::optimalAssignment() const {
DiscreteBayesNet::shared_ptr chordal = eliminate();
if (ISDEBUG("Scheduler::optimalAssignment")) {
DiscreteBayesNet::const_reverse_iterator it = chordal->rbegin();
const Student & student = students_.front();
cout << endl;
(*it)->print(student.name_);
}
tic(3, "my_optimize");
sharedValues mpe = optimize(*chordal);
toc(3, "my_optimize");
return mpe;
}
/** find the assignment of students to slots with most possible committees */
Scheduler::sharedValues Scheduler::bestSchedule() const {
sharedValues best;
throw runtime_error("bestSchedule not implemented");
return best;
}
/** find the corresponding most desirable committee assignment */
Scheduler::sharedValues Scheduler::bestAssignment(
sharedValues bestSchedule) const {
sharedValues best;
throw runtime_error("bestAssignment not implemented");
return best;
}
} // gtsam

171
gtsam/discrete/Scheduler.h Normal file
View File

@ -0,0 +1,171 @@
/*
* Scheduler.h
* @brief an example how inference can be used for scheduling qualifiers
* @date Mar 26, 2011
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/CSP.h>
namespace gtsam {
/**
* Scheduler class
* Creates one variable for each student, and three variables for each
* of the student's areas, for a total of 4*nrStudents variables.
* The "student" variable will determine when the student takes the qual.
* The "area" variables determine which faculty are on his/her committee.
*/
class Scheduler : public CSP {
private:
/** Internal data structure for students */
struct Student {
std::string name_;
DiscreteKey key_; // key for student
std::vector<DiscreteKey> keys_; // key for areas
std::vector<std::string> areaName_;
std::vector<double> advisor_;
Student(size_t nrFaculty, size_t advisorIndex) :
keys_(3), areaName_(3), advisor_(nrFaculty, 1.0) {
advisor_[advisorIndex] = 0.0;
}
void print() const {
using std::cout;
cout << name_ << ": ";
for (size_t area = 0; area < 3; area++)
cout << areaName_[area] << " ";
cout << std::endl;
}
};
/** Maximum number of students */
size_t maxNrStudents_;
/** discrete keys, indexed by student and area index */
std::vector<Student> students_;
/** faculty identifiers */
std::map<std::string, size_t> facultyIndex_;
std::vector<std::string> facultyName_, slotName_, areaName_;
/** area constraints */
typedef std::map<std::string, std::vector<double> > FacultyInArea;
FacultyInArea facultyInArea_;
/** nrTimeSlots * nrFaculty availability constraints */
std::string available_;
/** which slots are good */
std::vector<double> slotsAvailable_;
public:
/**
* Constructor
* WE need to know the number of students in advance for ordering keys.
* then add faculty, slots, areas, availability, students, in that order
*/
Scheduler(size_t maxNrStudents):maxNrStudents_(maxNrStudents) {
}
void addFaculty(const std::string& facultyName) {
facultyIndex_[facultyName] = nrFaculty();
facultyName_.push_back(facultyName);
}
size_t nrFaculty() const {
return facultyName_.size();
}
/** boolean std::string of nrTimeSlots * nrFaculty */
void setAvailability(const std::string& available) {
available_ = available;
}
void addSlot(const std::string& slotName) {
slotName_.push_back(slotName);
}
size_t nrTimeSlots() const {
return slotName_.size();
}
const std::string& slotName(size_t s) const {
return slotName_[s];
}
/** slots available, boolean */
void setSlotsAvailable(const std::vector<double>& slotsAvailable) {
slotsAvailable_ = slotsAvailable;
}
void addArea(const std::string& facultyName, const std::string& areaName) {
areaName_.push_back(areaName);
std::vector<double>& table = facultyInArea_[areaName]; // will create if needed
if (table.empty()) table.resize(nrFaculty(), 0);
table[facultyIndex_[facultyName]] = 1;
}
/**
* Constructor that reads in faculty, slots, availibility.
* Still need to add areas and students after this
*/
Scheduler(size_t maxNrStudents, const std::string& filename);
/** get key for student and area, 0 is time slot itself */
const DiscreteKey& key(size_t s, boost::optional<size_t> area = boost::none) const;
/** addStudent has to be called after adding slots and faculty */
void addStudent(const std::string& studentName, const std::string& area1,
const std::string& area2, const std::string& area3,
const std::string& advisor);
/// current number of students
size_t nrStudents() const {
return students_.size();
}
const std::string& studentName(size_t i) const;
const DiscreteKey& studentKey(size_t i) const;
const std::string& studentArea(size_t i, size_t area) const;
/** Add student-specific constraints to the graph */
void addStudentSpecificConstraints(size_t i, boost::optional<size_t> slot = boost::none);
/** Main routine that builds factor graph */
void buildGraph(size_t mutexBound = 7);
/** print */
void print(const std::string& s = "Scheduler") const;
/** Print readable form of assignment */
void printAssignment(sharedValues assignment) const;
/** Special print for single-student case */
void printSpecial(sharedValues assignment) const;
/** Accumulate faculty stats */
void accumulateStats(sharedValues assignment,
std::vector<size_t>& stats) const;
/** Eliminate, return a Bayes net */
DiscreteBayesNet::shared_ptr eliminate() const;
/** Find the best total assignment - can be expensive */
sharedValues optimalAssignment() const;
/** find the assignment of students to slots with most possible committees */
sharedValues bestSchedule() const;
/** find the corresponding most desirable committee assignment */
sharedValues bestAssignment(sharedValues bestSchedule) const;
}; // Scheduler
} // gtsam

View File

@ -0,0 +1,217 @@
/*
* Signature.cpp
* @brief: signatures for conditional densities
* @author: Frank dellaert
* @date Feb 27, 2011
*/
#include <sstream>
#include <boost/foreach.hpp>
#include "Signature.h"
#ifdef BOOST_HAVE_PARSER
#include <boost/spirit/include/qi.hpp> // for parsing
#include <boost/spirit/include/phoenix.hpp> // for qi::_val
#endif
namespace gtsam {
using namespace std;
#ifdef BOOST_HAVE_PARSER
namespace qi = boost::spirit::qi;
// parser for strings of form "99/1 80/20" etc...
namespace parser {
typedef string::const_iterator It;
using boost::phoenix::val;
using boost::phoenix::ref;
using boost::phoenix::push_back;
// Special rows, true and false
Signature::Row createF() {
Signature::Row r(2);
r[0] = 1;
r[1] = 0;
return r;
}
Signature::Row createT() {
Signature::Row r(2);
r[0] = 0;
r[1] = 1;
return r;
}
Signature::Row T = createT(), F = createF();
// Special tables (inefficient, but do we care for user input?)
Signature::Table logic(bool ff, bool ft, bool tf, bool tt) {
Signature::Table t(4);
t[0] = ff ? T : F;
t[1] = ft ? T : F;
t[2] = tf ? T : F;
t[3] = tt ? T : F;
return t;
}
struct Grammar {
qi::rule<It, qi::space_type, Signature::Table()> table, or_, and_, rows;
qi::rule<It, Signature::Row()> true_, false_, row;
Grammar() {
table = or_ | and_ | rows;
or_ = qi::lit("OR")[qi::_val = logic(false, true, true, true)];
and_ = qi::lit("AND")[qi::_val = logic(false, false, false, true)];
rows = +(row | true_ | false_); // only loads first of the rows under boost 1.42
row = qi::double_ >> +("/" >> qi::double_);
true_ = qi::lit("T")[qi::_val = T];
false_ = qi::lit("F")[qi::_val = F];
}
} grammar;
// Create simpler parsing function to avoid the issue of only parsing a single row
bool parse_table(const string& spec, Signature::Table& table) {
// check for OR, AND on whole phrase
It f = spec.begin(), l = spec.end();
if (qi::parse(f, l,
qi::lit("OR")[ref(table) = logic(false, true, true, true)]) ||
qi::parse(f, l,
qi::lit("AND")[ref(table) = logic(false, false, false, true)]))
return true;
// tokenize into separate rows
istringstream iss(spec);
string token;
while (iss >> token) {
Signature::Row values;
It tf = token.begin(), tl = token.end();
bool r = qi::parse(tf, tl,
qi::double_[push_back(ref(values), qi::_1)] >> +("/" >> qi::double_[push_back(ref(values), qi::_1)]) |
qi::lit("T")[ref(values) = T] |
qi::lit("F")[ref(values) = F] );
if (!r)
return false;
table.push_back(values);
}
return true;
}
} // \namespace parser
#endif
ostream& operator <<(ostream &os, const Signature::Row &row) {
os << row[0];
for (size_t i = 1; i < row.size(); i++)
os << " " << row[i];
return os;
}
ostream& operator <<(ostream &os, const Signature::Table &table) {
for (size_t i = 0; i < table.size(); i++)
os << table[i] << endl;
return os;
}
Signature::Signature(const DiscreteKey& key) :
key_(key) {
}
DiscreteKeys Signature::discreteKeysParentsFirst() const {
DiscreteKeys keys;
BOOST_FOREACH(const DiscreteKey& key, parents_)
keys.push_back(key);
keys.push_back(key_);
return keys;
}
vector<Index> Signature::indices() const {
vector<Index> js;
js.push_back(key_.first);
BOOST_FOREACH(const DiscreteKey& key, parents_)
js.push_back(key.first);
return js;
}
vector<double> Signature::cpt() const {
vector<double> cpt;
if (table_) {
BOOST_FOREACH(const Row& row, *table_)
BOOST_FOREACH(const double& x, row)
cpt.push_back(x);
}
return cpt;
}
Signature& Signature::operator,(const DiscreteKey& parent) {
parents_.push_back(parent);
return *this;
}
static void normalize(Signature::Row& row) {
double sum = 0;
for (size_t i = 0; i < row.size(); i++)
sum += row[i];
for (size_t i = 0; i < row.size(); i++)
row[i] /= sum;
}
Signature& Signature::operator=(const string& spec) {
spec_.reset(spec);
#ifdef BOOST_HAVE_PARSER
Table table;
// NOTE: using simpler parse function to ensure boost back compatibility
// parser::It f = spec.begin(), l = spec.end();
bool success = //
// qi::phrase_parse(f, l, parser::grammar.table, qi::space, table); // using full grammar
parser::parse_table(spec, table);
if (success) {
BOOST_FOREACH(Row& row, table)
normalize(row);
table_.reset(table);
}
#endif
return *this;
}
Signature& Signature::operator=(const Table& t) {
Table table = t;
BOOST_FOREACH(Row& row, table)
normalize(row);
table_.reset(table);
return *this;
}
ostream& operator <<(ostream &os, const Signature &s) {
os << s.key_.first;
if (s.parents_.empty()) {
os << " % ";
} else {
os << " | " << s.parents_[0].first;
for (size_t i = 1; i < s.parents_.size(); i++)
os << " && " << s.parents_[i].first;
os << " = ";
}
os << (s.spec_ ? *s.spec_ : "no spec") << endl;
if (s.table_)
os << (*s.table_);
else
os << "spec could not be parsed" << endl;
return os;
}
Signature operator|(const DiscreteKey& key, const DiscreteKey& parent) {
Signature s(key);
return s, parent;
}
Signature operator%(const DiscreteKey& key, const string& parent) {
Signature s(key);
return s = parent;
}
Signature operator%(const DiscreteKey& key, const Signature::Table& parent) {
Signature s(key);
return s = parent;
}
} // namespace gtsam

129
gtsam/discrete/Signature.h Normal file
View File

@ -0,0 +1,129 @@
/*
* Signature.h
* @brief: signatures for conditional densities
* @author: Frank dellaert
* @date Feb 27, 2011
*/
#pragma once
#include <string>
#include <vector>
#include <boost/optional.hpp>
#include <gtsam/discrete/DiscreteKey.h>
#include <boost/version.hpp> // for checking whether we are using boost 1.40
#if BOOST_VERSION >= 104200
#define BOOST_HAVE_PARSER
#endif
namespace gtsam {
/**
* Signature for a discrete conditional density, used to construct conditionals.
*
* The format is (Key % string) for nodes with no parents,
* and (Key | Key, Key = string) for nodes with parents.
*
* The string specifies a conditional probability spec in the 00 01 10 11 order.
* For three-valued, it would be 00 01 02 10 11 12 20 21 22, etc...
*
* For example, given the following keys
*
* Key A("Asia"), S("Smoking"), T("Tuberculosis"), L("LungCancer"),
* B("Bronchitis"), E("Either"), X("XRay"), D("Dyspnoea");
*
* These are all valid signatures (Asia network example):
*
* A % "99/1"
* S % "50/50"
* T|A = "99/1 95/5"
* L|S = "99/1 90/10"
* B|S = "70/30 40/60"
* E|T,L = "F F F 1"
* X|E = "95/5 2/98"
* D|E,B = "9/1 2/8 3/7 1/9"
*/
class Signature {
public:
/** Data type for the CPT */
typedef std::vector<double> Row;
typedef std::vector<Row> Table;
private:
/** the variable key */
DiscreteKey key_;
/** the parent keys */
DiscreteKeys parents_;
// the given CPT specification string
boost::optional<std::string> spec_;
// the CPT as parsed, if successful
boost::optional<Table> table_;
public:
/** Constructor from DiscreteKey */
Signature(const DiscreteKey& key);
/** the variable key */
const DiscreteKey& key() const {
return key_;
}
/** the parent keys */
const DiscreteKeys& parents() const {
return parents_;
}
/** All keys, with variable key last */
DiscreteKeys discreteKeysParentsFirst() const;
/** All key indices, with variable key first */
std::vector<Index> indices() const;
// the CPT as parsed, if successful
const boost::optional<Table>& table() const {
return table_;
}
// the CPT as a vector of doubles, with key's values most rapidly changing
std::vector<double> cpt() const;
/** Add a parent */
Signature& operator,(const DiscreteKey& parent);
/** Add the CPT spec - Fails in boost 1.40 */
Signature& operator=(const std::string& spec);
/** Add the CPT spec directly as a table */
Signature& operator=(const Table& table);
/** provide streaming */
friend std::ostream& operator <<(std::ostream &os, const Signature &s);
};
/**
* Helper function to create Signature objects
* example: Signature s = D | E;
*/
Signature operator|(const DiscreteKey& key, const DiscreteKey& parent);
/**
* Helper function to create Signature objects
* example: Signature s(D % "99/1");
* Uses string parser, which requires BOOST 1.42 or higher
*/
Signature operator%(const DiscreteKey& key, const std::string& parent);
/**
* Helper function to create Signature objects, using table construction directly
* example: Signature s(D % table);
*/
Signature operator%(const DiscreteKey& key, const Signature::Table& parent);
}

View File

@ -0,0 +1,78 @@
/*
* SingleValue.cpp
* @brief domain constraint
* @date Feb 13, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/SingleValue.h>
#include <gtsam/discrete/Domain.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/base/Testable.h>
#include <boost/make_shared.hpp>
namespace gtsam {
using namespace std;
/* ************************************************************************* */
void SingleValue::print(const string& s) const {
cout << s << ": SingleValue on " << keys_[0] << " (j=" << keys_[0]
<< ") with value " << value_ << endl;
}
/* ************************************************************************* */
double SingleValue::operator()(const Values& values) const {
return (double) (values.at(keys_[0]) == value_);
}
/* ************************************************************************* */
SingleValue::operator DecisionTreeFactor() const {
DiscreteKeys keys;
keys += DiscreteKey(keys_[0],cardinality_);
vector<double> table;
for (size_t i1 = 0; i1 < cardinality_; i1++)
table.push_back(i1 == value_);
DecisionTreeFactor converted(keys, table);
return converted;
}
/* ************************************************************************* */
DecisionTreeFactor SingleValue::operator*(const DecisionTreeFactor& f) const {
// TODO: can we do this more efficiently?
return DecisionTreeFactor(*this) * f;
}
/* ************************************************************************* */
bool SingleValue::ensureArcConsistency(size_t j,
vector<Domain>& domains) const {
if (j != keys_[0]) throw invalid_argument(
"SingleValue check on wrong domain");
Domain& D = domains[j];
if (D.isSingleton()) {
if (D.firstValue() != value_) throw runtime_error("Unsatisfiable");
return false;
}
D = Domain(discreteKey(),value_);
return true;
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr SingleValue::partiallyApply(const Values& values) const {
Values::const_iterator it = values.find(keys_[0]);
if (it != values.end() && it->second != value_) throw runtime_error(
"SingleValue::partiallyApply: unsatisfiable");
return boost::make_shared < SingleValue > (keys_[0], cardinality_, value_);
}
/* ************************************************************************* */
DiscreteFactor::shared_ptr SingleValue::partiallyApply(
const vector<Domain>& domains) const {
const Domain& Dk = domains[keys_[0]];
if (Dk.isSingleton() && !Dk.contains(value_)) throw runtime_error(
"SingleValue::partiallyApply: unsatisfiable");
return boost::make_shared < SingleValue > (discreteKey(), value_);
}
/* ************************************************************************* */
} // namespace gtsam

View File

@ -0,0 +1,72 @@
/*
* SingleValue.h
* @brief domain constraint
* @date Feb 6, 2012
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/discrete/DiscreteKey.h>
#include <gtsam/discrete/DiscreteFactor.h>
namespace gtsam {
/**
* SingleValue constraint
*/
class SingleValue: public DiscreteFactor {
/// Number of values
size_t cardinality_;
/// allowed value
size_t value_;
DiscreteKey discreteKey() const {
return DiscreteKey(keys_[0],cardinality_);
}
public:
typedef boost::shared_ptr<SingleValue> shared_ptr;
/// Constructor
SingleValue(Index key, size_t n, size_t value) :
DiscreteFactor(key), cardinality_(n), value_(value) {
}
/// Constructor
SingleValue(const DiscreteKey& dkey, size_t value) :
DiscreteFactor(dkey.first), cardinality_(dkey.second), value_(value) {
}
// print
virtual void print(const std::string& s = "") const;
/// Calculate value
virtual double operator()(const Values& values) const;
/// Convert into a decisiontree
virtual operator DecisionTreeFactor() const;
/// Multiply into a decisiontree
virtual DecisionTreeFactor operator*(const DecisionTreeFactor& f) const;
/*
* Ensure Arc-consistency
* @param j domain to be checked
* @param domains all other domains
*/
bool ensureArcConsistency(size_t j, std::vector<Domain>& domains) const;
/// Partially apply known values
virtual DiscreteFactor::shared_ptr partiallyApply(
const Values& values) const;
/// Partially apply known values, domain version
virtual DiscreteFactor::shared_ptr partiallyApply(
const std::vector<Domain>& domains) const;
};
} // namespace gtsam

View File

@ -0,0 +1,117 @@
/*
* @file TypedDiscreteFactor.cpp
* @brief
* @author Duy-Nguyen Ta
* @date Mar 5, 2011
*/
#include <boost/make_shared.hpp>
#include <gtsam/discrete/TypedDiscreteFactor.h>
#include <gtsam/inference/Factor-inl.h>
#include <gtsam/discrete/DecisionDiagram-inl.h>
using namespace std;
namespace gtsam {
/* ******************************************************************************** */
TypedDiscreteFactor::TypedDiscreteFactor(const Indices& keys,
const string& table) :
Factor<Index> (keys.begin(), keys.end()), potentials_(keys, table) {
}
/* ******************************************************************************** */
TypedDiscreteFactor::TypedDiscreteFactor(const Indices& keys,
const vector<double>& table) :
Factor<Index> (keys.begin(), keys.end()), potentials_(keys, table) {
//#define DEBUG_FACTORS
#ifdef DEBUG_FACTORS
static size_t count = 0;
string dotfile = (boost::format("Factor-%03d") % ++count).str();
potentials_.dot(dotfile);
if (count == 57) potentials_.print("57");
#endif
}
/* ************************************************************************* */
double TypedDiscreteFactor::operator()(const Values& values) const {
return potentials_(values);
}
/* ************************************************************************* */
void TypedDiscreteFactor::print(const string&s) const {
Factor<Index>::print(s);
potentials_.print();
}
/* ************************************************************************* */
bool TypedDiscreteFactor::equals(const TypedDiscreteFactor& other, double tol) const {
return potentials_.equals(other.potentials_, tol);
}
/* ******************************************************************************** */
DiscreteFactor::shared_ptr TypedDiscreteFactor::toDiscreteFactor(
const KeyOrdering& ordering) const {
throw std::runtime_error("broken");
//return boost::make_shared<DiscreteFactor>(keys(), ordering, potentials_);
}
#ifdef OLD
DiscreteFactor TypedDiscreteFactor::toDiscreteFactor(
const KeyOrdering& ordering, const ProblemType problemType) const {
{
static bool debug = false;
// instantiate vector keys and column index in order
DiscreteFactor::ColumnIndex orderColumnIndex;
vector<Index> keys;
BOOST_FOREACH(const KeyOrdering::value_type& ord, ordering)
{
if (debug) cout << "Key: " << ord.first;
// find the key with ord.first in this factor
vector<Index>::const_iterator it = std::find(keys_.begin(),
keys_.end(), ord.first);
// if found
if (it != keys_.end()) {
if (debug) cout << "it found: " << (*it) << ", index: "
<< ord.second << endl;
keys.push_back(ord.second); // push back the ordering index
orderColumnIndex[ord.second] = columnIndex_.at(ord.first.name());
if (debug) cout << "map " << ord.second << " with name: "
<< ord.first.name() << " to " << columnIndex_.at(
ord.first.name()) << endl;
}
}
DiscreteFactor f(keys, potentials_, orderColumnIndex, problemType);
return f;
}
/* ******************************************************************************** */
std::vector<size_t> TypedDiscreteFactor::init(const Indices& keys) {
vector<size_t> cardinalities;
for (size_t j = 0; j < keys.size(); j++) {
Index key = keys[j];
keys_.push_back(key);
columnIndex_[key.name()] = j;
cardinalities.push_back(key.cardinality());
}
return cardinalities;
}
/* ******************************************************************************** */
double TypedDiscreteFactor::potential(const TypedValues& values) const {
vector<size_t> assignment(values.size());
BOOST_FOREACH(const TypedValues::value_type& val, values)
if (columnIndex_.find(val.first) != columnIndex_.end()) assignment[columnIndex_.at(
val.first)] = val.second;
return potentials_(assignment);
}
#endif
} // namespace

View File

@ -0,0 +1,68 @@
/*
* @file TypedDiscreteFactor.h
* @brief
* @author Duy-Nguyen Ta
* @date Mar 5, 2011
*/
#pragma once
#include <map>
#include <gtsam/inference/Factor.h>
#include <gtsam/discrete/DiscreteFactor.h>
#include <gtsam/discrete/AlgebraicDecisionDiagram.h>
namespace gtsam {
/**
* A factor on discrete variables with string keys
*/
class TypedDiscreteFactor: public Factor<Index> {
typedef AlgebraicDecisionDiagram<Index> ADD;
/** potentials of the factor */
ADD potentials_;
public:
/** A map from keys to values */
typedef ADD::Assignment Values;
/** Constructor from keys and string table */
TypedDiscreteFactor(const Indices& keys, const std::string& table);
/** Constructor from keys and doubles */
TypedDiscreteFactor(const Indices& keys,
const std::vector<double>& table);
/** Evaluate */
double operator()(const Values& values) const;
// Testable
bool equals(const TypedDiscreteFactor& other, double tol = 1e-9) const;
void print(const std::string& s = "DiscreteFactor: ") const;
DiscreteFactor::shared_ptr toDiscreteFactor(const KeyOrdering& ordering) const;
#ifdef OLD
/** map each variable name to its column index in the potential table */
typedef std::map<std::string, size_t> Index2IndexMap;
Index2IndexMap columnIndex_;
/** Initialize keys, column index, and return cardinalities */
std::vector<size_t> init(const Indices& keys);
public:
/** Default constructor */
TypedDiscreteFactor() {}
/** Evaluate potential of a given assignment of values */
double potential(const TypedValues& values) const;
#endif
}; // TypedDiscreteFactor
} // namespace

View File

@ -0,0 +1,68 @@
/*
* @file TypedDiscreteFactorGraph.cpp
* @brief
* @author Duy-Nguyen Ta
* @date Mar 1, 2011
*/
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <gtsam/discrete/DiscreteFactor.h>
#include <gtsam/discrete/TypedDiscreteFactorGraph.h>
#include <gtsam/discrete/parseUAI.h>
#include <gtsam/inference/FactorGraph.h>
using namespace std;
namespace gtsam {
/* ************************************************************************* */
TypedDiscreteFactorGraph::TypedDiscreteFactorGraph() {
}
/* ************************************************************************* */
TypedDiscreteFactorGraph::TypedDiscreteFactorGraph(const string& filename) {
bool success = parseUAI(filename, *this);
if (!success) throw runtime_error(
"TypedDiscreteFactorGraph constructor from filename failed");
}
/* ************************************************************************* */
void TypedDiscreteFactorGraph::add//
(const Indices& keys, const string& table) {
push_back(boost::shared_ptr<TypedDiscreteFactor>//
(new TypedDiscreteFactor(keys, table)));
}
/* ************************************************************************* */
void TypedDiscreteFactorGraph::add//
(const Indices& keys, const vector<double>& table) {
push_back(boost::shared_ptr<TypedDiscreteFactor>//
(new TypedDiscreteFactor(keys, table)));
}
/* ************************************************************************* */
void TypedDiscreteFactorGraph::print(const string s) {
cout << s << endl;
cout << "Factors: " << endl;
BOOST_FOREACH(const sharedFactor factor, factors_)
factor->print();
}
/* ************************************************************************* */
double TypedDiscreteFactorGraph::operator()(
const TypedDiscreteFactor::Values& values) const {
// Loop over all factors and multiply their probabilities
double p = 1.0;
BOOST_FOREACH(const sharedFactor& factor, *this)
p *= (*factor)(values);
return p;
}
/* ************************************************************************* */
}

View File

@ -0,0 +1,50 @@
/*
* @file TypedDiscreteFactorGraph.h
* @brief Factor graph with typed factors (with Index keys)
* @author Duy-Nguyen Ta
* @author Frank Dellaert
* @date Mar 1, 2011
*/
#pragma once
#include <vector>
#include <set>
#include <gtsam/inference/FactorGraph.h>
#include <gtsam/discrete/TypedDiscreteFactor.h>
namespace gtsam {
/**
* Typed discrete factor graph, where keys are strings
*/
class TypedDiscreteFactorGraph: public FactorGraph<TypedDiscreteFactor> {
public:
/**
* Default constructor
*/
TypedDiscreteFactorGraph();
/**
* Constructor from file
* For now assumes in .uai format from UAI'08 Probablistic Inference Evaluation
* See http://graphmod.ics.uci.edu/uai08/FileFormat
*/
TypedDiscreteFactorGraph(const std::string& filename);
// Add factors without shared pointer ugliness
void add(const Indices& keys, const std::string& table);
void add(const Indices& keys, const std::vector<double>& table);
/** print */
void print(const std::string s);
/** Evaluate potential of a given assignment of values */
double operator()(const TypedDiscreteFactor::Values& values) const;
}; // TypedDiscreteFactorGraph
} // namespace

View File

@ -0,0 +1 @@
,Ron Arkin,Andrea Thomaz,Ayanna Howard,Wayne Book,Mike Stilman,Charlie Kemp,Jun Ueda,Patricio Vela,Magnus Egerstedt,Harvey Lipkin,Frank Dellaert,Irfan Essa,Aaron Bobick,Jim Rehg,Henrik Christensen,Tucker Balch,Karen Feigh,N/A 1,N/A 2 Mon 9:00-10.30,,1,1,1,1,,1,1,,,1,,,,1,,,1,1 Mon 10:30-12:00,,1,1,1,1,,,1,1,,,,,,,,,1,1 Mon 1:30-3:00,,,1,,,1,1,1,1,1,1,,,,1,,,1,1 Mon 3:00-4:30,,,,1,,1,1,1,,1,1,1,,1,1,,,1,1 Tue 9:00-10.30,,,1,,,,,1,,1,1,,,1,1,,,1,1 Tue 10:30-12:00,,,1,1,1,,1,1,,1,1,,,1,,1,,1,1 Tue 1:30-3:00,,1,,1,1,,1,1,1,1,1,,,,,1,,1,1 Tue 3:00-4:30,,1,1,,,,,1,1,1,1,,,,1,1,,1,1 Wed 9:00-10.30,,,1,1,,,,,1,,1,,1,,1,,1,1,1 Wed 10:30-12:00,,,,1,1,,1,1,1,,,1,1,,1,1,1,1,1 Wed 1:30-3:00,,,,,1,1,,1,,1,1,1,1,,,1,,1,1 Wed 3:00-4:30,,,,,1,1,1,1,1,,1,1,,1,,1,,1,1 Thu 9:00-10.30,,,1,,,,,1,,1,,,1,1,,,,1,1 Thu 10:30-12:00,,,1,1,1,,1,1,,1,,,,1,,1,,1,1 Thu 1:30-3:00,,,1,1,1,,1,1,1,1,,,,1,,1,1,1,1 Thu 3:00-4:30,,,1,,,,,,1,1,,,,,1,1,1,1,1 Fri 9:00-10.30,,,1,1,1,1,1,1,,,1,,,,1,,,1,1 Fri 10:30-12:00,,,1,1,1,,1,1,,,,1,,,1,,,1,1 Fri 1:30-3:00,,,1,1,1,,,1,,1,1,1,1,,,,,1,1 Fri 3:00-4:30,,,,,,,,,,1,1,,1,,,,,1,1
1 Ron Arkin Andrea Thomaz Ayanna Howard Wayne Book Mike Stilman Charlie Kemp Jun Ueda Patricio Vela Magnus Egerstedt Harvey Lipkin Frank Dellaert Irfan Essa Aaron Bobick Jim Rehg Henrik Christensen Tucker Balch Karen Feigh N/A 1 N/A 2 Mon 9:00-10.30 1 1 1 1 1 1 1 1 1 1 Mon 10:30-12:00 1 1 1 1 1 1 1 1 Mon 1:30-3:00 1 1 1 1 1 1 1 1 1 1 Mon 3:00-4:30 1 1 1 1 1 1 1 1 1 1 1 Tue 9:00-10.30 1 1 1 1 1 1 1 1 Tue 10:30-12:00 1 1 1 1 1 1 1 1 1 1 1 Tue 1:30-3:00 1 1 1 1 1 1 1 1 1 1 1 Tue 3:00-4:30 1 1 1 1 1 1 1 1 1 1 Wed 9:00-10.30 1 1 1 1 1 1 1 1 1 Wed 10:30-12:00 1 1 1 1 1 1 1 1 1 1 1 1 Wed 1:30-3:00 1 1 1 1 1 1 1 1 1 1 Wed 3:00-4:30 1 1 1 1 1 1 1 1 1 1 1 Thu 9:00-10.30 1 1 1 1 1 1 1 Thu 10:30-12:00 1 1 1 1 1 1 1 1 1 1 Thu 1:30-3:00 1 1 1 1 1 1 1 1 1 1 1 1 Thu 3:00-4:30 1 1 1 1 1 1 1 1 Fri 9:00-10.30 1 1 1 1 1 1 1 1 1 1 Fri 10:30-12:00 1 1 1 1 1 1 1 1 1 Fri 1:30-3:00 1 1 1 1 1 1 1 1 1 1 Fri 3:00-4:30 1 1 1 1 1

Binary file not shown.

View File

@ -0,0 +1 @@
,Karen Feigh,Henrik Christensen,Panos Tsiotras,Ron Arkin,Andrea Thomaz,Magnus Egerstedt,Charles Isbell,Fumin Zhang,Mike Stilman,Jun Ueda,Aaron Bobick,Ayanna Howard,Patricio Vela,Charlie Kemp,Tucker Balch Mon 9:00 AM - 10:30 AM,,,1,1,1,1,1,,,,1,,,, Mon 10:30 AM - 12:00 PM,1,,,1,1,,1,1,1,,1,,1,1,1 Mon 1:30 PM - 3:00 PM,1,1,1,,,1,1,1,1,1,1,1,1,,1 Mon 3:00 PM - 4:30 PM,,,1,1,,,1,,1,,1,1,1,,1 Mon 4:30 PM - 6:00 PM,,1,1,,,,,1,,1,1,,1,, Tue 9:00 AM - 10:30 AM,,1,1,,1,1,1,,,,1,1,,, Tue 10:30 AM - 12:00 PM,1,1,1,1,1,,1,1,,1,1,,1,,1 Tue 1:30 PM - 3:00 PM,1,1,1,,1,1,,1,1,1,1,,,1, Tue 3:00 PM - 4:30 PM,,1,,,1,1,,1,,,,,,, Tue 4:30 PM - 6:00 PM,,,,,1,,,1,1,,1,,,, Wed 9:00 AM - 10:30 AM,1,1,1,,1,,1,,,,,1,,, Wed 10:30 AM - 12:00 PM,1,,,,1,1,1,1,1,1,,,1,1, Wed 1:30 PM - 3:00 PM,1,,1,,,1,,1,1,1,,,1,, Wed 3:00 PM - 4:30 PM,,,1,,,,,,1,,,,1,,1 Wed 4:30 PM - 6:00 PM,,,1,,,,,1,,,,,1,, Thu 9:00 AM - 10:30 AM,,1,1,,,1,,,,,,,,, Thu 10:30 AM - 12:00 PM,1,1,,,,1,,1,,1,,,,,1 Thu 1:30 PM - 3:00 PM,1,,,,,1,,1,,,,,,, Thu 3:00 PM - 4:30 PM,,1,1,,,1,1,1,,,,,,, Thu 4:30 PM - 6:00 PM,,1,1,,,,,1,,,,,,, Fri 9:00 AM - 10:30 AM,1,1,,,,,1,,,,,1,,, Fri 10:30 AM - 12:00 PM,1,1,,,,,,1,1,1,,,,,1 Fri 1:30 PM - 3:00 PM,1,,,,,1,,1,1,1,,,1,1,1 Fri 3:00 PM - 4:30 PM,1,,,,,,1,1,1,1,,,,,1 Fri 4:30 PM - 6:00 PM,,1,,,,,,1,,,,,1,,
1 Karen Feigh Henrik Christensen Panos Tsiotras Ron Arkin Andrea Thomaz Magnus Egerstedt Charles Isbell Fumin Zhang Mike Stilman Jun Ueda Aaron Bobick Ayanna Howard Patricio Vela Charlie Kemp Tucker Balch Mon 9:00 AM - 10:30 AM 1 1 1 1 1 1 Mon 10:30 AM - 12:00 PM 1 1 1 1 1 1 1 1 1 1 Mon 1:30 PM - 3:00 PM 1 1 1 1 1 1 1 1 1 1 1 1 Mon 3:00 PM - 4:30 PM 1 1 1 1 1 1 1 1 Mon 4:30 PM - 6:00 PM 1 1 1 1 1 1 Tue 9:00 AM - 10:30 AM 1 1 1 1 1 1 1 Tue 10:30 AM - 12:00 PM 1 1 1 1 1 1 1 1 1 1 1 Tue 1:30 PM - 3:00 PM 1 1 1 1 1 1 1 1 1 1 Tue 3:00 PM - 4:30 PM 1 1 1 1 Tue 4:30 PM - 6:00 PM 1 1 1 1 Wed 9:00 AM - 10:30 AM 1 1 1 1 1 1 Wed 10:30 AM - 12:00 PM 1 1 1 1 1 1 1 1 1 Wed 1:30 PM - 3:00 PM 1 1 1 1 1 1 1 Wed 3:00 PM - 4:30 PM 1 1 1 1 Wed 4:30 PM - 6:00 PM 1 1 1 Thu 9:00 AM - 10:30 AM 1 1 1 Thu 10:30 AM - 12:00 PM 1 1 1 1 1 1 Thu 1:30 PM - 3:00 PM 1 1 1 Thu 3:00 PM - 4:30 PM 1 1 1 1 1 Thu 4:30 PM - 6:00 PM 1 1 1 Fri 9:00 AM - 10:30 AM 1 1 1 1 Fri 10:30 AM - 12:00 PM 1 1 1 1 1 1 Fri 1:30 PM - 3:00 PM 1 1 1 1 1 1 1 1 Fri 3:00 PM - 4:30 PM 1 1 1 1 1 1 Fri 4:30 PM - 6:00 PM 1 1 1

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,344 @@
/*
* schedulingExample.cpp
* @brief hard scheduling example
* @date March 25, 2011
* @author Frank Dellaert
*/
//#define ENABLE_TIMING
#define ADD_NO_CACHING
#define ADD_NO_PRUNING
#include <gtsam/discrete/Scheduler.h>
#include <gtsam/base/debug.h>
#include <gtsam/base/timing.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <algorithm>
using namespace boost::assign;
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
void addStudent(Scheduler& s, size_t i) {
switch (i) {
case 0:
s.addStudent("Michael N", "AI", "Autonomy", "Perception", "Tucker Balch");
break;
case 1:
s.addStudent("Tucker H", "Controls", "AI", "Perception", "Jim Rehg");
break;
case 2:
s.addStudent("Jake H", "Controls", "AI", "Perception", "Henrik Christensen");
break;
case 3:
s.addStudent("Tobias K", "Controls", "AI", "Autonomy", "Mike Stilman");
break;
case 4:
s.addStudent("Shu J", "Controls", "AI", "HRI", "N/A 1");
break;
case 5:
s.addStudent("Akansel C", "AI", "Autonomy", "Mechanics",
"Henrik Christensen");
break;
case 6:
s.addStudent("Tiffany C", "Controls", "N/A 1", "N/A 2", "Charlie Kemp");
break;
}
}
/* ************************************************************************* */
Scheduler largeExample(size_t nrStudents = 7) {
string path("/Users/dellaert/borg/gtsam/gtsam/discrete/examples/");
Scheduler s(nrStudents, path + "Doodle.csv");
s.addArea("Harvey Lipkin", "Mechanics");
s.addArea("Wayne Book", "Mechanics");
s.addArea("Jun Ueda", "Mechanics");
// s.addArea("Wayne Book", "Controls");
s.addArea("Patricio Vela", "Controls");
s.addArea("Magnus Egerstedt", "Controls");
s.addArea("Jun Ueda", "Controls");
// s.addArea("Frank Dellaert", "Perception");
s.addArea("Jim Rehg", "Perception");
s.addArea("Irfan Essa", "Perception");
s.addArea("Aaron Bobick", "Perception");
s.addArea("Henrik Christensen", "Perception");
s.addArea("Mike Stilman", "AI");
s.addArea("Henrik Christensen", "AI");
s.addArea("Frank Dellaert", "AI");
s.addArea("Ayanna Howard", "AI");
// s.addArea("Tucker Balch", "AI");
s.addArea("Ayanna Howard", "Autonomy");
// s.addArea("Andrea Thomaz", "Autonomy");
s.addArea("Charlie Kemp", "Autonomy");
s.addArea("Tucker Balch", "Autonomy");
s.addArea("Ron Arkin", "Autonomy");
s.addArea("Andrea Thomaz", "HRI");
s.addArea("Karen Feigh", "HRI");
s.addArea("Charlie Kemp", "HRI");
// Allow students not to take three areas
s.addArea("N/A 1", "N/A 1");
s.addArea("N/A 2", "N/A 2");
// add students
for (size_t i = 0; i < nrStudents; i++)
addStudent(s, i);
return s;
}
/* ************************************************************************* */
void runLargeExample() {
Scheduler scheduler = largeExample();
scheduler.print();
// BUILD THE GRAPH !
size_t addMutex = 2;
scheduler.buildGraph(addMutex);
// Do brute force product and output that to file
if (scheduler.nrStudents() == 1) { // otherwise too slow
DecisionTreeFactor product = scheduler.product();
product.dot("scheduling-large", false);
}
// Do exact inference
// SETDEBUG("timing-verbose", true);
SETDEBUG("DiscreteConditional::DiscreteConditional", true);
tic(2, "large");
DiscreteFactor::sharedValues MPE = scheduler.optimalAssignment();
toc(2, "large");
tictoc_finishedIteration();
tictoc_print();
scheduler.printAssignment(MPE);
}
/* ************************************************************************* */
// Solve a series of relaxed problems for maximum flexibility solution
void solveStaged(size_t addMutex = 2) {
// super-hack! just count...
bool debug = false;
SETDEBUG("DiscreteConditional::COUNT", true);
SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress
// make a vector with slot availability, initially all 1
// Reads file to get count :-)
vector<double> slotsAvailable(largeExample(0).nrTimeSlots(), 1.0);
// now, find optimal value for each student, using relaxed mutex constraints
for (size_t s = 0; s < 7; s++) {
// add all students first time, then drop last one second time, etc...
Scheduler scheduler = largeExample(7 - s);
//scheduler.print(str(boost::format("Scheduler %d") % (7-s)));
// only allow slots not yet taken
scheduler.setSlotsAvailable(slotsAvailable);
// BUILD THE GRAPH !
scheduler.buildGraph(addMutex);
// Do EXACT INFERENCE
tic_("eliminate");
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
toc_("eliminate");
// find root node
DiscreteConditional::shared_ptr root = *(chordal->rbegin());
if (debug)
root->print(""/*scheduler.studentName(s)*/);
// solve root node only
Scheduler::Values values;
size_t bestSlot = root->solve(values);
// get corresponding count
DiscreteKey dkey = scheduler.studentKey(6 - s);
values[dkey.first] = bestSlot;
size_t count = (*root)(values);
// remove this slot from consideration
slotsAvailable[bestSlot] = 0.0;
cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(6-s)
% scheduler.slotName(bestSlot) % bestSlot % count << endl;
}
tictoc_print_();
// Solution with addMutex = 2: (20 secs)
// TC = Wed 2 (9), count = 96375041778
// AC = Tue 2 (5), count = 4076088090
// SJ = Mon 1 (0), count = 29596704
// TK = Mon 3 (2), count = 755370
// JH = Wed 4 (11), count = 12000
// TH = Fri 2 (17), count = 220
// MN = Fri 1 (16), count = 5
//
// Mutex does make a difference !!
}
/* ************************************************************************* */
// Sample from solution found above and evaluate cost function
bool NonZero(size_t i) {
return i > 0;
}
DiscreteBayesNet::shared_ptr createSampler(size_t i,
size_t slot, vector<Scheduler>& schedulers) {
Scheduler scheduler = largeExample(0); // todo: wrong nr students
addStudent(scheduler, i);
SETDEBUG("Scheduler::buildGraph", false);
scheduler.addStudentSpecificConstraints(0, slot);
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
// chordal->print(scheduler[i].studentKey(0).name()); // large !
schedulers.push_back(scheduler);
return chordal;
}
void sampleSolutions() {
vector<Scheduler> schedulers;
vector<DiscreteBayesNet::shared_ptr> samplers(7);
// Given the time-slots, we can create 7 independent samplers
vector<size_t> slots;
slots += 16, 17, 11, 2, 0, 5, 9; // given slots
for (size_t i = 0; i < 7; i++)
samplers[i] = createSampler(i, slots[i], schedulers);
// now, sample schedules
for (size_t n = 0; n < 500; n++) {
vector<size_t> stats(19, 0);
vector<Scheduler::sharedValues> samples;
for (size_t i = 0; i < 7; i++) {
samples.push_back(sample(*samplers[i]));
schedulers[i].accumulateStats(samples[i], stats);
}
size_t max = *max_element(stats.begin(), stats.end());
size_t min = *min_element(stats.begin(), stats.end());
size_t nz = count_if(stats.begin(), stats.end(), NonZero);
if (nz >= 15 && max <= 2) {
cout << boost::format(
"Sampled schedule %d, min = %d, nz = %d, max = %d\n") % (n + 1) % min
% nz % max;
for (size_t i = 0; i < 7; i++) {
cout << schedulers[i].studentName(0) << " : " << schedulers[i].slotName(
slots[i]) << endl;
schedulers[i].printSpecial(samples[i]);
}
}
}
// Output was
// Sampled schedule 359, min = 0, nz = 15, max = 2
// Michael N : Fri 9:00-10.30
// Michael N AI: Frank Dellaert
// Michael N Autonomy: Charlie Kemp
// Michael N Perception: Henrik Christensen
//
// Tucker H : Fri 10:30-12:00
// Tucker H AI: Ayanna Howard
// Tucker H Controls: Patricio Vela
// Tucker H Perception: Irfan Essa
//
// Jake H : Wed 3:00-4:30
// Jake H AI: Mike Stilman
// Jake H Controls: Magnus Egerstedt
// Jake H Perception: Jim Rehg
//
// Tobias K : Mon 1:30-3:00
// Tobias K AI: Ayanna Howard
// Tobias K Autonomy: Charlie Kemp
// Tobias K Controls: Magnus Egerstedt
//
// Shu J : Mon 9:00-10.30
// Shu J AI: Mike Stilman
// Shu J Controls: Jun Ueda
// Shu J HRI: Andrea Thomaz
//
// Akansel C : Tue 10:30-12:00
// Akansel C AI: Frank Dellaert
// Akansel C Autonomy: Tucker Balch
// Akansel C Mechanics: Harvey Lipkin
//
// Tiffany C : Wed 10:30-12:00
// Tiffany C Controls: Patricio Vela
// Tiffany C N/A 1: N/A 1
// Tiffany C N/A 2: N/A 2
}
/* ************************************************************************* */
void accomodateStudent() {
// super-hack! just count...
bool debug = false;
// SETDEBUG("DiscreteConditional::COUNT",true);
SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress
Scheduler scheduler = largeExample(0);
// scheduler.addStudent("Victor E", "Autonomy", "HRI", "AI",
// "Henrik Christensen");
scheduler.addStudent("Carlos N", "Perception", "AI", "Autonomy",
"Henrik Christensen");
scheduler.print("scheduler");
// rule out all occupied slots
vector<size_t> slots;
slots += 16, 17, 11, 2, 0, 5, 9, 14;
vector<double> slotsAvailable(scheduler.nrTimeSlots(), 1.0);
BOOST_FOREACH(size_t s, slots)
slotsAvailable[s] = 0;
scheduler.setSlotsAvailable(slotsAvailable);
// BUILD THE GRAPH !
scheduler.buildGraph(1);
// Do EXACT INFERENCE
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
// find root node
DiscreteConditional::shared_ptr root = *(chordal->rbegin());
if (debug)
root->print(""/*scheduler.studentName(s)*/);
// GTSAM_PRINT(*chordal);
// solve root node only
Scheduler::Values values;
size_t bestSlot = root->solve(values);
// get corresponding count
DiscreteKey dkey = scheduler.studentKey(0);
values[dkey.first] = bestSlot;
size_t count = (*root)(values);
cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(0)
% scheduler.slotName(bestSlot) % bestSlot % count << endl;
// sample schedules
for (size_t n = 0; n < 10; n++) {
Scheduler::sharedValues sample0 = sample(*chordal);
scheduler.printAssignment(sample0);
}
}
/* ************************************************************************* */
int main() {
runLargeExample();
solveStaged(3);
// sampleSolutions();
// accomodateStudent();
return 0;
}
/* ************************************************************************* */

View File

@ -0,0 +1,264 @@
/*
* schedulingExample.cpp
* @brief hard scheduling example
* @date March 25, 2011
* @author Frank Dellaert
*/
#define ENABLE_TIMING
#define ADD_NO_CACHING
#define ADD_NO_PRUNING
#include <gtsam/discrete/Scheduler.h>
#include <gtsam/base/debug.h>
#include <gtsam/base/timing.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <algorithm>
using namespace boost::assign;
using namespace std;
using namespace gtsam;
size_t NRSTUDENTS = 9;
bool NonZero(size_t i) {
return i > 0;
}
/* ************************************************************************* */
void addStudent(Scheduler& s, size_t i) {
switch (i) {
case 0:
s.addStudent("Pan, Yunpeng", "Controls", "Perception", "Mechanics", "Eric Johnson");
break;
case 1:
s.addStudent("Sawhney, Rahul", "Controls", "AI", "Perception", "Henrik Christensen");
break;
case 2:
s.addStudent("Akgun, Baris", "Controls", "AI", "HRI", "Andrea Thomaz");
break;
case 3:
s.addStudent("Jiang, Shu", "Controls", "AI", "Perception", "Ron Arkin");
break;
case 4:
s.addStudent("Grice, Phillip", "Controls", "Perception", "HRI", "Charlie Kemp");
break;
case 5:
s.addStudent("Huaman, Ana", "Controls", "AI", "Perception", "Mike Stilman");
break;
case 6:
s.addStudent("Levihn, Martin", "AI", "Autonomy", "Perception", "Mike Stilman");
break;
case 7:
s.addStudent("Nieto, Carlos", "AI", "Autonomy", "Perception", "Henrik Christensen");
break;
case 8:
s.addStudent("Robinette, Paul", "Controls", "AI", "HRI", "Ayanna Howard");
break;
}
}
/* ************************************************************************* */
Scheduler largeExample(size_t nrStudents = NRSTUDENTS) {
string path("/Users/dellaert/borg/gtsam/gtsam/discrete/examples/");
Scheduler s(nrStudents, path + "Doodle2012.csv");
s.addArea("Harvey Lipkin", "Mechanics");
s.addArea("Jun Ueda", "Mechanics");
s.addArea("Patricio Vela", "Controls");
s.addArea("Magnus Egerstedt", "Controls");
s.addArea("Jun Ueda", "Controls");
s.addArea("Panos Tsiotras", "Controls");
s.addArea("Fumin Zhang", "Controls");
s.addArea("Henrik Christensen", "Perception");
s.addArea("Aaron Bobick", "Perception");
s.addArea("Mike Stilman", "AI");
// s.addArea("Henrik Christensen", "AI");
s.addArea("Ayanna Howard", "AI");
s.addArea("Charles Isbell", "AI");
s.addArea("Tucker Balch", "AI");
s.addArea("Ayanna Howard", "Autonomy");
s.addArea("Charlie Kemp", "Autonomy");
s.addArea("Tucker Balch", "Autonomy");
s.addArea("Ron Arkin", "Autonomy");
s.addArea("Andrea Thomaz", "HRI");
s.addArea("Karen Feigh", "HRI");
s.addArea("Charlie Kemp", "HRI");
// add students
for (size_t i = 0; i < nrStudents; i++)
addStudent(s, i);
return s;
}
/* ************************************************************************* */
void runLargeExample() {
Scheduler scheduler = largeExample();
scheduler.print();
// BUILD THE GRAPH !
size_t addMutex = 3;
// SETDEBUG("Scheduler::buildGraph", true);
scheduler.buildGraph(addMutex);
// Do brute force product and output that to file
if (scheduler.nrStudents() == 1) { // otherwise too slow
DecisionTreeFactor product = scheduler.product();
product.dot("scheduling-large", false);
}
// Do exact inference
// SETDEBUG("timing-verbose", true);
SETDEBUG("DiscreteConditional::DiscreteConditional", true);
#define SAMPLE
#ifdef SAMPLE
tic(2, "large");
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
toc(2, "large");
tictoc_finishedIteration();
tictoc_print();
for (size_t i=0;i<100;i++) {
DiscreteFactor::sharedValues assignment = sample(*chordal);
vector<size_t> stats(scheduler.nrFaculty());
scheduler.accumulateStats(assignment, stats);
size_t max = *max_element(stats.begin(), stats.end());
size_t min = *min_element(stats.begin(), stats.end());
size_t nz = count_if(stats.begin(), stats.end(), NonZero);
// cout << min << ", " << max << ", " << nz << endl;
if (nz >= 13 && min >=1 && max <= 4) {
cout << "======================================================\n";
scheduler.printAssignment(assignment);
}
}
#else
tic(2, "large");
DiscreteFactor::sharedValues MPE = scheduler.optimalAssignment();
toc(2, "large");
tictoc_finishedIteration();
tictoc_print();
scheduler.printAssignment(MPE);
#endif
}
/* ************************************************************************* */
// Solve a series of relaxed problems for maximum flexibility solution
void solveStaged(size_t addMutex = 2) {
// super-hack! just count...
bool debug = false;
SETDEBUG("DiscreteConditional::COUNT", true);
SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress
// make a vector with slot availability, initially all 1
// Reads file to get count :-)
vector<double> slotsAvailable(largeExample(0).nrTimeSlots(), 1.0);
// now, find optimal value for each student, using relaxed mutex constraints
for (size_t s = 0; s < NRSTUDENTS; s++) {
// add all students first time, then drop last one second time, etc...
Scheduler scheduler = largeExample(NRSTUDENTS - s);
//scheduler.print(str(boost::format("Scheduler %d") % (NRSTUDENTS-s)));
// only allow slots not yet taken
scheduler.setSlotsAvailable(slotsAvailable);
// BUILD THE GRAPH !
scheduler.buildGraph(addMutex);
// Do EXACT INFERENCE
tic_("eliminate");
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
toc_("eliminate");
// find root node
DiscreteConditional::shared_ptr root = *(chordal->rbegin());
if (debug)
root->print(""/*scheduler.studentName(s)*/);
// solve root node only
Scheduler::Values values;
size_t bestSlot = root->solve(values);
// get corresponding count
DiscreteKey dkey = scheduler.studentKey(NRSTUDENTS - 1 - s);
values[dkey.first] = bestSlot;
size_t count = (*root)(values);
// remove this slot from consideration
slotsAvailable[bestSlot] = 0.0;
cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(NRSTUDENTS-1-s)
% scheduler.slotName(bestSlot) % bestSlot % count << endl;
}
tictoc_print_();
}
/* ************************************************************************* */
// Sample from solution found above and evaluate cost function
DiscreteBayesNet::shared_ptr createSampler(size_t i,
size_t slot, vector<Scheduler>& schedulers) {
Scheduler scheduler = largeExample(0); // todo: wrong nr students
addStudent(scheduler, i);
SETDEBUG("Scheduler::buildGraph", false);
scheduler.addStudentSpecificConstraints(0, slot);
DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate();
// chordal->print(scheduler[i].studentKey(0).name()); // large !
schedulers.push_back(scheduler);
return chordal;
}
void sampleSolutions() {
vector<Scheduler> schedulers;
vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS);
// Given the time-slots, we can create NRSTUDENTS independent samplers
vector<size_t> slots;
slots += 3, 20, 2, 6, 5, 11, 1, 4; // given slots
for (size_t i = 0; i < NRSTUDENTS; i++)
samplers[i] = createSampler(i, slots[i], schedulers);
// now, sample schedules
for (size_t n = 0; n < 500; n++) {
vector<size_t> stats(19, 0);
vector<Scheduler::sharedValues> samples;
for (size_t i = 0; i < NRSTUDENTS; i++) {
samples.push_back(sample(*samplers[i]));
schedulers[i].accumulateStats(samples[i], stats);
}
size_t max = *max_element(stats.begin(), stats.end());
size_t min = *min_element(stats.begin(), stats.end());
size_t nz = count_if(stats.begin(), stats.end(), NonZero);
if (nz >= 15 && max <= 2) {
cout << boost::format(
"Sampled schedule %d, min = %d, nz = %d, max = %d\n") % (n + 1) % min
% nz % max;
for (size_t i = 0; i < NRSTUDENTS; i++) {
cout << schedulers[i].studentName(0) << " : " << schedulers[i].slotName(
slots[i]) << endl;
schedulers[i].printSpecial(samples[i]);
}
}
}
}
/* ************************************************************************* */
int main() {
runLargeExample();
// solveStaged(3);
// sampleSolutions();
return 0;
}
/* ************************************************************************* */

View File

@ -0,0 +1 @@
,Frank,Harvey,Magnus,Andrea Mon,1,1,1, Wed,1,1,1,1 Fri,,1,1,1
1 Frank Harvey Magnus Andrea Mon 1 1 1 Wed 1 1 1 1 Fri 1 1 1

157
gtsam/discrete/parseUAI.cpp Normal file
View File

@ -0,0 +1,157 @@
/*
* parseUAI.cpp
* @brief: parse UAI 2008 format
* @date March 5, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
//#define PARSE
#ifdef PARSE
#include <fstream>
#include <boost/spirit/include/qi.hpp> // for parsing
#include <boost/spirit/include/phoenix.hpp> // for ref
#include <boost/spirit/home/phoenix/bind.hpp>
#include <boost/spirit/home/phoenix/object.hpp>
#include <boost/spirit/home/phoenix/operator.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <gtsam/discrete/parseUAI.h>
using namespace std;
namespace qi = boost::spirit::qi;
namespace gtsam {
/* ************************************************************************* */
// Keys are the vars of variables connected to a factor
// subclass of Indices with special constructor
struct Keys: public Indices {
Keys() {
}
// Pick correct vars based on indices
Keys(const Indices& vars, const vector<int>& indices) {
BOOST_FOREACH(int i, indices)
push_back(vars[i]);
}
};
/* ************************************************************************* */
// The UAI grammar is defined in a class
// Spirit local variables are used, see
// http://boost-spirit.com/home/2010/01/21/what-are-rule-bound-semantic-actions
/* ************************************************************************* */
struct Grammar {
// declare all parsers as instance variables
typedef vector<double> Table;
typedef boost::spirit::istream_iterator It;
qi::rule<It, qi::space_type> uai, preamble, type, vars, factors, tables;
qi::rule<It, qi::space_type, Keys(), qi::locals<size_t> > keys;
qi::rule<It, qi::space_type, Table(), qi::locals<size_t> > table;
// Variables filled by preamble parser
size_t nrVars_, nrFactors_;
Indices vars_;
vector<Keys> factors_;
// Variables filled by tables parser
vector<Table> tables_;
// The constructor defines the parser rules (declared below)
// To debug, just say debug(rule) after defining the rule
Grammar() {
using boost::phoenix::val;
using boost::phoenix::ref;
using boost::phoenix::construct;
using namespace boost::spirit::qi;
//--------------- high level parsers with side-effects :-( -----------------
// A uai file consists of preamble followed by tables
uai = preamble >> tables;
// The preamble defines the variables and factors
// The parser fills in the first set of variables above,
// including the vector of factor "Neighborhoods"
preamble = type >> vars >> int_[ref(nrFactors_) = _1] >> factors;
// type string, does not seem to matter
type = lit("BAYES") | lit("MARKOV");
// vars parses "3 2 2 3" and synthesizes a Keys class, in this case
// containing Indices {v0,2}, {v1,2}, and {v2,3}
vars = int_[ref(nrVars_) = _1] >> (repeat(ref(nrVars_))[int_]) //
[ref(vars_) = construct<Indices> (_1)];
// Parse a list of Neighborhoods and fill factors_
factors = (repeat(ref(nrFactors_))[keys])//
[ref(factors_) = _1];
// The tables parser fills in the tables_
tables = (repeat(ref(nrFactors_))[table])//
[ref(tables_) = _1];
//----------- basic parsers with synthesized attributes :-) -----------------
// keys parses strings like "2 1 2", indicating
// a binary factor (2) on variables v1 and v2.
// It returns a Keys class as attribute
keys = int_[_a = _1] >> repeat(_a)[int_] //
[_val = construct<Keys> (ref(vars_), _1)];
// The tables are a list of doubles preceded by a count, e.g. "4 1.0 2.0 3.0 4.0"
// The table parser returns a PotentialTable::Table attribute
table = int_[_a = _1] >> repeat(_a)[double_] //
[_val = construct<Table> (_1)];
}
// Add the factors to the graph
void addFactorsToGraph(TypedDiscreteFactorGraph& graph) {
assert(factors_.size()==nrFactors_);
assert(tables_.size()==nrFactors_);
for (size_t i = 0; i < nrFactors_; i++)
graph.add(factors_[i], tables_[i]);
}
};
/* ************************************************************************* */
bool parseUAI(const std::string& filename, TypedDiscreteFactorGraph& graph) {
// open file, disable skipping of whitespace
std::ifstream in(filename.c_str());
if (!in) {
cerr << "Could not open " << filename << endl;
return false;
}
in.unsetf(std::ios::skipws);
// wrap istream into iterator
boost::spirit::istream_iterator first(in);
boost::spirit::istream_iterator last;
// Parse and add factors into the graph
Grammar grammar;
bool success = qi::phrase_parse(first, last, grammar.uai, qi::space);
if (success) grammar.addFactorsToGraph(graph);
return success;
}
/* ************************************************************************* */
}// gtsam
#else
#include <gtsam/discrete/parseUAI.h>
namespace gtsam {
/** Dummy version of function - otherwise, missing symbol */
bool parseUAI(const std::string& filename, TypedDiscreteFactorGraph& graph) {
return false;
}
} // \namespace gtsam
#endif

22
gtsam/discrete/parseUAI.h Normal file
View File

@ -0,0 +1,22 @@
/*
* parseUAI.h
* @brief: parse UAI 2008 format
* @date March 5, 2011
* @author Duy-Nguyen Ta
* @author Frank Dellaert
*/
#include <string>
#include <gtsam/discrete/TypedDiscreteFactorGraph.h>
namespace gtsam {
/**
* Constructor from file
* For now assumes in .uai format from UAI'08 Probablistic Inference Evaluation
* See http://graphmod.ics.uci.edu/uai08/FileFormat
*/
bool parseUAI(const std::string& filename,
gtsam::TypedDiscreteFactorGraph& graph);
} // gtsam

View File

@ -0,0 +1,935 @@
# ALARM network
# from http://compbio.cs.huji.ac.il/Repository/Datasets/alarm/alarm.dsc
37
2
0 5
2 2
4
0 0.9
1 0.1
2 0.01
3 0.99
2
1 4
3 3
9
0 0.95
1 0.04
2 0.01
3 0.04
4 0.95
5 0.01
6 0.01
7 0.29
8 0.7
2
2 4
3 3
9
0 0.95
1 0.04
2 0.01
3 0.04
4 0.95
5 0.01
6 0.01
7 0.04
8 0.95
1
3
2
2
0 0.2
1 0.8
3
3 4 5
2 3 2
12
0 0.95
1 0.01
2 0.04
3 0.09
4 0.01
5 0.9
6 0.98
7 0.05
8 0.01
9 0.9
10 0.01
11 0.05
1
5
2
2
0 0.05
1 0.95
3
3 5 6
2 2 3
12
0 0.98
1 0.5
2 0.95
3 0.05
4 0.01
5 0.49
6 0.04
7 0.9
8 0.01
9 0.01
10 0.01
11 0.05
1
7
2
2
0 0.05
1 0.95
3
7 8 34
2 3 3
18
0 0.98
1 0.98
2 0.01
3 0.01
4 0.01
5 0.01
6 0.4
7 0.01
8 0.59
9 0.98
10 0.01
11 0.01
12 0.3
13 0.01
14 0.4
15 0.01
16 0.3
17 0.98
3
9 10 34
3 2 3
18
0 0.333
1 0.333
2 0.333
3 0.98
4 0.01
5 0.01
6 0.333
7 0.333
8 0.333
9 0.01
10 0.98
11 0.01
12 0.333
13 0.333
14 0.333
15 0.01
16 0.01
17 0.98
1
10
2
2
0 0.1
1 0.9
3
10 11 34
2 3 3
18
0 0.333
1 0.98
2 0.333
3 0.01
4 0.333
5 0.01
6 0.333
7 0.01
8 0.333
9 0.98
10 0.333
11 0.01
12 0.333
13 0.01
14 0.333
15 0.01
16 0.333
17 0.98
1
12
2
2
0 0.1
1 0.9
1
13
2
2
0 0.01
1 0.99
2
13 14
2 3
6
0 0.98
1 0.3
2 0.01
3 0.4
4 0.01
5 0.3
3
15 30 32
4 4 3
48
0 0.97
1 0.01
2 0.01
3 0.01
4 0.01
5 0.97
6 0.01
7 0.01
8 0.01
9 0.01
10 0.97
11 0.01
12 0.01
13 0.01
14 0.01
15 0.97
16 0.01
17 0.97
18 0.01
19 0.01
20 0.97
21 0.01
22 0.01
23 0.01
24 0.01
25 0.01
26 0.97
27 0.01
28 0.01
29 0.01
30 0.01
31 0.97
32 0.01
33 0.97
34 0.01
35 0.01
36 0.01
37 0.01
38 0.97
39 0.01
40 0.97
41 0.01
42 0.01
43 0.01
44 0.01
45 0.01
46 0.01
47 0.97
1
16
2
2
0 0.04
1 0.96
3
17 24 30
4 3 4
48
0 0.97
1 0.01
2 0.01
3 0.01
4 0.97
5 0.01
6 0.01
7 0.01
8 0.97
9 0.01
10 0.01
11 0.01
12 0.01
13 0.97
14 0.01
15 0.01
16 0.6
17 0.38
18 0.01
19 0.01
20 0.01
21 0.97
22 0.01
23 0.01
24 0.01
25 0.01
26 0.97
27 0.01
28 0.5
29 0.48
30 0.01
31 0.01
32 0.01
33 0.01
34 0.97
35 0.01
36 0.01
37 0.01
38 0.01
39 0.97
40 0.5
41 0.48
42 0.01
43 0.01
44 0.01
45 0.01
46 0.01
47 0.97
1
18
2
2
0 0.05
1 0.95
3
18 19 31
2 3 4
19
0 1
1 1
6 0.99
7 0.95
8 0.01
9 0.04
11 0.01
12 0.95
13 0.01
14 0.04
15 0.95
16 0.01
17 0.04
18 0.95
19 0.01
20 0.04
21 0.01
22 0.01
23 0.98
3
19 20 23
3 3 2
18
0 0.98
1 0.01
2 0.98
3 0.01
4 0.01
5 0.01
6 0.01
7 0.98
8 0.01
9 0.01
10 0.98
11 0.69
12 0.98
13 0.01
14 0.3
15 0.01
16 0.01
17 0.01
2
21 22
3 2
6
0 0.01
1 0.19
2 0.8
3 0.05
4 0.9
5 0.05
1
22
2
2
0 0.01
1 0.99
3
22 23 24
2 2 3
12
0 0.1
1 0.95
2 0.9
3 0.05
4 0.1
5 0.95
6 0.9
7 0.05
8 0.01
9 0.05
10 0.99
11 0.95
1
24
3
3
0 0.92
1 0.03
2 0.05
4
16 24 25 29
2 3 4 4
96
0 0.97
1 0.97
2 0.97
3 0.97
4 0.97
5 0.97
6 0.01
7 0.01
8 0.01
9 0.01
10 0.01
11 0.01
12 0.01
13 0.01
14 0.01
15 0.01
16 0.01
17 0.01
18 0.01
19 0.01
20 0.01
21 0.01
22 0.01
23 0.01
24 0.01
25 0.01
26 0.1
27 0.4
28 0.01
29 0.01
30 0.3
31 0.97
32 0.84
33 0.58
34 0.29
35 0.9
36 0.49
37 0.01
38 0.05
39 0.01
40 0.3
41 0.08
42 0.2
43 0.01
44 0.01
45 0.01
46 0.4
47 0.01
48 0.01
49 0.01
50 0.05
51 0.2
52 0.01
53 0.01
54 0.01
55 0.01
56 0.25
57 0.75
58 0.01
59 0.01
60 0.08
61 0.97
62 0.25
63 0.04
64 0.08
65 0.38
66 0.9
67 0.01
68 0.45
69 0.01
70 0.9
71 0.6
72 0.01
73 0.01
74 0.01
75 0.2
76 0.01
77 0.01
78 0.01
79 0.01
80 0.15
81 0.7
82 0.01
83 0.01
84 0.01
85 0.01
86 0.25
87 0.09
88 0.01
89 0.01
90 0.97
91 0.97
92 0.59
93 0.01
94 0.97
95 0.97
1
26
2
2
0 0.1
1 0.9
1
27
3
3
0 0.05
1 0.9
2 0.05
2
27 28
3 4
12
0 0.05
1 0.05
2 0.05
3 0.93
4 0.01
5 0.01
6 0.01
7 0.93
8 0.01
9 0.01
10 0.01
11 0.93
3
26 28 29
2 4 4
32
0 0.97
1 0.97
2 0.97
3 0.01
4 0.97
5 0.01
6 0.97
7 0.01
8 0.01
9 0.01
10 0.01
11 0.97
12 0.01
13 0.01
14 0.01
15 0.01
16 0.01
17 0.01
18 0.01
19 0.01
20 0.01
21 0.97
22 0.01
23 0.01
24 0.01
25 0.01
26 0.01
27 0.01
28 0.01
29 0.01
30 0.01
31 0.97
4
16 24 29 30
2 3 4 4
96
0 0.97
1 0.97
2 0.97
3 0.97
4 0.97
5 0.97
6 0.95
7 0.01
8 0.97
9 0.97
10 0.95
11 0.01
12 0.4
13 0.01
14 0.97
15 0.97
16 0.5
17 0.01
18 0.3
19 0.01
20 0.97
21 0.97
22 0.3
23 0.01
24 0.01
25 0.01
26 0.01
27 0.01
28 0.01
29 0.01
30 0.03
31 0.97
32 0.01
33 0.01
34 0.03
35 0.97
36 0.58
37 0.01
38 0.01
39 0.01
40 0.48
41 0.01
42 0.68
43 0.01
44 0.01
45 0.01
46 0.68
47 0.01
48 0.01
49 0.01
50 0.01
51 0.01
52 0.01
53 0.01
54 0.01
55 0.01
56 0.01
57 0.01
58 0.01
59 0.01
60 0.01
61 0.97
62 0.01
63 0.01
64 0.01
65 0.97
66 0.01
67 0.01
68 0.01
69 0.01
70 0.01
71 0.01
72 0.01
73 0.01
74 0.01
75 0.01
76 0.01
77 0.01
78 0.01
79 0.01
80 0.01
81 0.01
82 0.01
83 0.01
84 0.01
85 0.01
86 0.01
87 0.01
88 0.01
89 0.01
90 0.01
91 0.97
92 0.01
93 0.01
94 0.01
95 0.97
3
24 30 31
3 4 4
48
0 0.97
1 0.97
2 0.97
3 0.01
4 0.01
5 0.03
6 0.01
7 0.01
8 0.01
9 0.01
10 0.01
11 0.01
12 0.01
13 0.01
14 0.01
15 0.97
16 0.97
17 0.95
18 0.01
19 0.01
20 0.94
21 0.01
22 0.01
23 0.88
24 0.01
25 0.01
26 0.01
27 0.01
28 0.01
29 0.01
30 0.97
31 0.97
32 0.04
33 0.01
34 0.01
35 0.1
36 0.01
37 0.01
38 0.01
39 0.01
40 0.01
41 0.01
42 0.01
43 0.01
44 0.01
45 0.97
46 0.97
47 0.01
2
31 32
4 3
12
0 0.01
1 0.01
2 0.04
3 0.9
4 0.01
5 0.01
6 0.92
7 0.09
8 0.98
9 0.98
10 0.04
11 0.01
5
12 14 20 32 33
2 3 3 3 2
108
0 0.01
1 0.05
2 0.01
3 0.7
4 0.01
5 0.95
6 0.01
7 0.05
8 0.01
9 0.7
10 0.05
11 0.95
12 0.01
13 0.05
14 0.05
15 0.7
16 0.05
17 0.95
18 0.01
19 0.05
20 0.01
21 0.7
22 0.01
23 0.99
24 0.01
25 0.05
26 0.01
27 0.7
28 0.05
29 0.99
30 0.01
31 0.05
32 0.05
33 0.7
34 0.05
35 0.99
36 0.01
37 0.01
38 0.01
39 0.1
40 0.01
41 0.3
42 0.01
43 0.01
44 0.01
45 0.1
46 0.01
47 0.3
48 0.01
49 0.01
50 0.01
51 0.1
52 0.01
53 0.3
54 0.99
55 0.95
56 0.99
57 0.3
58 0.99
59 0.05
60 0.99
61 0.95
62 0.99
63 0.3
64 0.95
65 0.05
66 0.99
67 0.95
68 0.95
69 0.3
70 0.95
71 0.05
72 0.99
73 0.95
74 0.99
75 0.3
76 0.99
77 0.01
78 0.99
79 0.95
80 0.99
81 0.3
82 0.95
83 0.01
84 0.99
85 0.95
86 0.95
87 0.3
88 0.95
89 0.01
90 0.99
91 0.99
92 0.99
93 0.9
94 0.99
95 0.7
96 0.99
97 0.99
98 0.99
99 0.9
100 0.99
101 0.7
102 0.99
103 0.99
104 0.99
105 0.9
106 0.99
107 0.7
2
33 34
2 3
6
0 0.05
1 0.01
2 0.9
3 0.09
4 0.05
5 0.9
3
6 34 35
3 3 3
27
0 0.98
1 0.95
2 0.3
3 0.95
4 0.04
5 0.01
6 0.8
7 0.01
8 0.01
9 0.01
10 0.04
11 0.69
12 0.04
13 0.95
14 0.3
15 0.19
16 0.04
17 0.01
18 0.01
19 0.01
20 0.01
21 0.01
22 0.01
23 0.69
24 0.01
25 0.95
26 0.98
3
14 35 36
3 3 3
27
0 0.98
1 0.98
2 0.3
3 0.98
4 0.1
5 0.05
6 0.9
7 0.05
8 0.01
9 0.01
10 0.01
11 0.6
12 0.01
13 0.85
14 0.4
15 0.09
16 0.2
17 0.09
18 0.01
19 0.01
20 0.1
21 0.01
22 0.05
23 0.55
24 0.01
25 0.75
26 0.9

View File

@ -0,0 +1,18 @@
MARKOV
3
2 2 3
3
1 0
2 0 1
2 1 2
2
0.436 0.564
4
0.128 0.872
0.920 0.080
6
0.210 0.333 0.457
0.811 0.000 0.189

View File

@ -0,0 +1,3 @@
2
1 0
2 1

View File

@ -0,0 +1,996 @@
BAYES
54
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
54
4 1 17 27 0
4 49 32 38 1
2 22 2
2 19 3
1 4
2 49 5
3 17 19 6
4 36 26 28 7
1 8
5 22 51 4 28 9
4 8 23 26 10
2 5 11
1 12
3 27 53 13
3 38 12 14
3 32 29 15
3 23 45 16
4 49 38 23 17
6 32 36 33 43 39 18
4 23 26 44 19
5 31 22 38 23 20
6 22 29 34 37 40 21
1 22
5 49 31 2 29 23
2 4 24
3 49 5 25
4 22 5 29 26
2 2 27
3 25 47 28
1 29
2 2 30
1 31
1 32
3 42 41 33
3 36 25 34
5 32 38 5 41 35
1 36
10 36 27 19 53 18 46 50 35 11 37
2 22 38
3 38 26 39
1 40
1 41
3 2 25 42
4 1 23 4 43
1 44
4 34 7 0 45
4 2 30 33 46
5 49 23 26 27 47
3 31 44 48
1 49
3 26 41 50
1 51
4 36 8 23 52
3 32 26 53
16
0.285714 0.714286
0.461538 0.538462
0.307692 0.692308
0.300000 0.700000
0.333333 0.666667
0.714286 0.285714
0.588235 0.411765
0.588235 0.411765
16
0.625000 0.375000
0.750000 0.250000
0.625000 0.375000
0.166667 0.833333
0.555556 0.444444
0.545455 0.454545
0.500000 0.500000
0.428571 0.571429
4
0.666667 0.333333
0.571429 0.428571
4
0.461538 0.538462
0.272727 0.727273
2
0.230769 0.769231
4
0.625000 0.375000
0.583333 0.416667
8
0.800000 0.200000
0.500000 0.500000
0.333333 0.666667
0.250000 0.750000
16
0.411765 0.588235
0.500000 0.500000
0.769231 0.230769
0.692308 0.307692
0.625000 0.375000
0.600000 0.400000
0.833333 0.166667
0.571429 0.428571
2
0.700000 0.300000
32
0.833333 0.166667
0.250000 0.750000
0.500000 0.500000
0.500000 0.500000
0.526316 0.473684
0.500000 0.500000
0.428571 0.571429
0.500000 0.500000
0.444444 0.555556
0.666667 0.333333
0.636364 0.363636
0.384615 0.615385
0.222222 0.777778
0.411765 0.588235
0.526316 0.473684
0.583333 0.416667
16
0.357143 0.642857
0.363636 0.636364
0.166667 0.833333
0.777778 0.222222
0.473684 0.526316
0.538462 0.461538
0.500000 0.500000
0.470588 0.529412
4
0.470588 0.529412
0.400000 0.600000
2
0.500000 0.500000
8
0.473684 0.526316
0.555556 0.444444
0.411765 0.588235
0.714286 0.285714
8
0.800000 0.200000
0.444444 0.555556
0.600000 0.400000
0.666667 0.333333
8
0.500000 0.500000
0.333333 0.666667
0.625000 0.375000
0.692308 0.307692
8
0.285714 0.714286
0.714286 0.285714
0.500000 0.500000
0.500000 0.500000
16
0.833333 0.166667
0.454545 0.545455
0.625000 0.375000
0.250000 0.750000
0.727273 0.272727
0.588235 0.411765
0.400000 0.600000
0.500000 0.500000
64
0.166667 0.833333
0.666667 0.333333
0.692308 0.307692
0.538462 0.461538
0.500000 0.500000
0.250000 0.750000
0.437500 0.562500
0.473684 0.526316
0.769231 0.230769
0.400000 0.600000
0.555556 0.444444
0.272727 0.727273
0.473684 0.526316
0.818182 0.181818
0.750000 0.250000
0.416667 0.583333
0.588235 0.411765
0.769231 0.230769
0.500000 0.500000
0.473684 0.526316
0.833333 0.166667
0.444444 0.555556
0.600000 0.400000
0.529412 0.470588
0.727273 0.272727
0.615385 0.384615
0.444444 0.555556
0.400000 0.600000
0.642857 0.357143
0.200000 0.800000
0.333333 0.666667
0.437500 0.562500
16
0.666667 0.333333
0.250000 0.750000
0.625000 0.375000
0.357143 0.642857
0.500000 0.500000
0.300000 0.700000
0.526316 0.473684
0.600000 0.400000
32
0.444444 0.555556
0.583333 0.416667
0.500000 0.500000
0.571429 0.428571
0.400000 0.600000
0.500000 0.500000
0.333333 0.666667
0.666667 0.333333
0.473684 0.526316
0.500000 0.500000
0.545455 0.454545
0.454545 0.545455
0.500000 0.500000
0.466667 0.533333
0.777778 0.222222
0.222222 0.777778
64
0.333333 0.666667
0.818182 0.181818
0.526316 0.473684
0.375000 0.625000
0.625000 0.375000
0.444444 0.555556
0.473684 0.526316
0.533333 0.466667
0.500000 0.500000
0.500000 0.500000
0.363636 0.636364
0.300000 0.700000
0.250000 0.750000
0.562500 0.437500
0.571429 0.428571
0.642857 0.357143
0.666667 0.333333
0.363636 0.636364
0.384615 0.615385
0.600000 0.400000
0.818182 0.181818
0.428571 0.571429
0.625000 0.375000
0.562500 0.437500
0.583333 0.416667
0.529412 0.470588
0.529412 0.470588
0.545455 0.454545
0.333333 0.666667
0.230769 0.769231
0.500000 0.500000
0.230769 0.769231
2
0.588235 0.411765
32
0.333333 0.666667
0.333333 0.666667
0.428571 0.571429
0.600000 0.400000
0.750000 0.250000
0.666667 0.333333
0.411765 0.588235
0.583333 0.416667
0.800000 0.200000
0.545455 0.454545
0.333333 0.666667
0.375000 0.625000
0.571429 0.428571
0.285714 0.714286
0.555556 0.444444
0.461538 0.538462
4
0.500000 0.500000
0.625000 0.375000
8
0.727273 0.272727
0.461538 0.538462
0.777778 0.222222
0.400000 0.600000
16
0.555556 0.444444
0.600000 0.400000
0.571429 0.428571
0.833333 0.166667
0.777778 0.222222
0.357143 0.642857
0.285714 0.714286
0.642857 0.357143
4
0.461538 0.538462
0.250000 0.750000
8
0.692308 0.307692
0.529412 0.470588
0.437500 0.562500
0.666667 0.333333
2
0.727273 0.272727
4
0.500000 0.500000
0.571429 0.428571
2
0.375000 0.625000
2
0.428571 0.571429
8
0.666667 0.333333
0.444444 0.555556
0.500000 0.500000
0.416667 0.583333
8
0.357143 0.642857
0.461538 0.538462
0.272727 0.727273
0.411765 0.588235
32
0.470588 0.529412
0.466667 0.533333
0.700000 0.300000
0.555556 0.444444
0.444444 0.555556
0.666667 0.333333
0.466667 0.533333
0.466667 0.533333
0.200000 0.800000
0.588235 0.411765
0.166667 0.833333
0.333333 0.666667
0.526316 0.473684
0.562500 0.437500
0.333333 0.666667
0.700000 0.300000
2
0.166667 0.833333
1024
0.250000 0.750000
0.307692 0.692308
0.500000 0.500000
0.666667 0.333333
0.818182 0.181818
0.500000 0.500000
0.625000 0.375000
0.615385 0.384615
0.500000 0.500000
0.285714 0.714286
0.230769 0.769231
0.692308 0.307692
0.333333 0.666667
0.625000 0.375000
0.437500 0.562500
0.625000 0.375000
0.272727 0.727273
0.636364 0.363636
0.181818 0.818182
0.500000 0.500000
0.500000 0.500000
0.500000 0.500000
0.818182 0.181818
0.437500 0.562500
0.500000 0.500000
0.750000 0.250000
0.375000 0.625000
0.625000 0.375000
0.700000 0.300000
0.466667 0.533333
0.411765 0.588235
0.666667 0.333333
0.750000 0.250000
0.285714 0.714286
0.250000 0.750000
0.571429 0.428571
0.555556 0.444444
0.428571 0.571429
0.500000 0.500000
0.666667 0.333333
0.571429 0.428571
0.222222 0.777778
0.615385 0.384615
0.461538 0.538462
0.250000 0.750000
0.666667 0.333333
0.200000 0.800000
0.384615 0.615385
0.300000 0.700000
0.466667 0.533333
0.625000 0.375000
0.562500 0.437500
0.583333 0.416667
0.500000 0.500000
0.727273 0.272727
0.571429 0.428571
0.250000 0.750000
0.333333 0.666667
0.500000 0.500000
0.545455 0.454545
0.333333 0.666667
0.666667 0.333333
0.461538 0.538462
0.181818 0.818182
0.714286 0.285714
0.666667 0.333333
0.470588 0.529412
0.500000 0.500000
0.470588 0.529412
0.500000 0.500000
0.416667 0.583333
0.625000 0.375000
0.625000 0.375000
0.692308 0.307692
0.500000 0.500000
0.666667 0.333333
0.714286 0.285714
0.600000 0.400000
0.461538 0.538462
0.500000 0.500000
0.500000 0.500000
0.181818 0.818182
0.750000 0.250000
0.357143 0.642857
0.400000 0.600000
0.625000 0.375000
0.250000 0.750000
0.461538 0.538462
0.250000 0.750000
0.333333 0.666667
0.272727 0.727273
0.428571 0.571429
0.166667 0.833333
0.600000 0.400000
0.750000 0.250000
0.583333 0.416667
0.769231 0.230769
0.769231 0.230769
0.545455 0.454545
0.470588 0.529412
0.454545 0.545455
0.555556 0.444444
0.714286 0.285714
0.384615 0.615385
0.428571 0.571429
0.636364 0.363636
0.583333 0.416667
0.384615 0.615385
0.357143 0.642857
0.571429 0.428571
0.642857 0.357143
0.636364 0.363636
0.714286 0.285714
0.230769 0.769231
0.333333 0.666667
0.428571 0.571429
0.533333 0.466667
0.625000 0.375000
0.444444 0.555556
0.357143 0.642857
0.555556 0.444444
0.500000 0.500000
0.333333 0.666667
0.384615 0.615385
0.600000 0.400000
0.333333 0.666667
0.700000 0.300000
0.500000 0.500000
0.545455 0.454545
0.800000 0.200000
0.625000 0.375000
0.250000 0.750000
0.500000 0.500000
0.500000 0.500000
0.500000 0.500000
0.666667 0.333333
0.666667 0.333333
0.692308 0.307692
0.400000 0.600000
0.692308 0.307692
0.666667 0.333333
0.555556 0.444444
0.666667 0.333333
0.222222 0.777778
0.562500 0.437500
0.500000 0.500000
0.666667 0.333333
0.230769 0.769231
0.555556 0.444444
0.307692 0.692308
0.800000 0.200000
0.400000 0.600000
0.666667 0.333333
0.285714 0.714286
0.500000 0.500000
0.444444 0.555556
0.555556 0.444444
0.272727 0.727273
0.600000 0.400000
0.428571 0.571429
0.400000 0.600000
0.526316 0.473684
0.333333 0.666667
0.750000 0.250000
0.636364 0.363636
0.333333 0.666667
0.750000 0.250000
0.500000 0.500000
0.818182 0.181818
0.375000 0.625000
0.333333 0.666667
0.625000 0.375000
0.583333 0.416667
0.230769 0.769231
0.769231 0.230769
0.800000 0.200000
0.636364 0.363636
0.384615 0.615385
0.562500 0.437500
0.727273 0.272727
0.250000 0.750000
0.600000 0.400000
0.538462 0.461538
0.750000 0.250000
0.428571 0.571429
0.300000 0.700000
0.555556 0.444444
0.692308 0.307692
0.230769 0.769231
0.333333 0.666667
0.454545 0.545455
0.666667 0.333333
0.583333 0.416667
0.454545 0.545455
0.562500 0.437500
0.666667 0.333333
0.500000 0.500000
0.250000 0.750000
0.625000 0.375000
0.588235 0.411765
0.818182 0.181818
0.500000 0.500000
0.250000 0.750000
0.636364 0.363636
0.181818 0.818182
0.333333 0.666667
0.411765 0.588235
0.500000 0.500000
0.428571 0.571429
0.230769 0.769231
0.333333 0.666667
0.562500 0.437500
0.666667 0.333333
0.600000 0.400000
0.333333 0.666667
0.500000 0.500000
0.333333 0.666667
0.714286 0.285714
0.333333 0.666667
0.714286 0.285714
0.454545 0.545455
0.181818 0.818182
0.400000 0.600000
0.750000 0.250000
0.636364 0.363636
0.300000 0.700000
0.222222 0.777778
0.200000 0.800000
0.777778 0.222222
0.500000 0.500000
0.384615 0.615385
0.411765 0.588235
0.818182 0.181818
0.357143 0.642857
0.588235 0.411765
0.285714 0.714286
0.562500 0.437500
0.529412 0.470588
0.466667 0.533333
0.454545 0.545455
0.800000 0.200000
0.571429 0.428571
0.250000 0.750000
0.500000 0.500000
0.400000 0.600000
0.444444 0.555556
0.600000 0.400000
0.500000 0.500000
0.200000 0.800000
0.642857 0.357143
0.666667 0.333333
0.600000 0.400000
0.250000 0.750000
0.500000 0.500000
0.600000 0.400000
0.300000 0.700000
0.363636 0.636364
0.727273 0.272727
0.250000 0.750000
0.500000 0.500000
0.666667 0.333333
0.615385 0.384615
0.642857 0.357143
0.473684 0.526316
0.437500 0.562500
0.545455 0.454545
0.411765 0.588235
0.466667 0.533333
0.666667 0.333333
0.333333 0.666667
0.562500 0.437500
0.700000 0.300000
0.500000 0.500000
0.473684 0.526316
0.357143 0.642857
0.571429 0.428571
0.416667 0.583333
0.555556 0.444444
0.833333 0.166667
0.727273 0.272727
0.181818 0.818182
0.750000 0.250000
0.200000 0.800000
0.470588 0.529412
0.583333 0.416667
0.625000 0.375000
0.800000 0.200000
0.400000 0.600000
0.437500 0.562500
0.400000 0.600000
0.444444 0.555556
0.454545 0.545455
0.181818 0.818182
0.615385 0.384615
0.533333 0.466667
0.428571 0.571429
0.625000 0.375000
0.777778 0.222222
0.333333 0.666667
0.588235 0.411765
0.285714 0.714286
0.500000 0.500000
0.636364 0.363636
0.428571 0.571429
0.727273 0.272727
0.500000 0.500000
0.285714 0.714286
0.818182 0.181818
0.250000 0.750000
0.555556 0.444444
0.181818 0.818182
0.727273 0.272727
0.529412 0.470588
0.625000 0.375000
0.555556 0.444444
0.777778 0.222222
0.714286 0.285714
0.727273 0.272727
0.300000 0.700000
0.411765 0.588235
0.222222 0.777778
0.800000 0.200000
0.642857 0.357143
0.769231 0.230769
0.562500 0.437500
0.600000 0.400000
0.400000 0.600000
0.600000 0.400000
0.461538 0.538462
0.500000 0.500000
0.461538 0.538462
0.750000 0.250000
0.307692 0.692308
0.444444 0.555556
0.400000 0.600000
0.666667 0.333333
0.727273 0.272727
0.250000 0.750000
0.666667 0.333333
0.500000 0.500000
0.473684 0.526316
0.727273 0.272727
0.444444 0.555556
0.428571 0.571429
0.285714 0.714286
0.500000 0.500000
0.470588 0.529412
0.500000 0.500000
0.363636 0.636364
0.428571 0.571429
0.615385 0.384615
0.500000 0.500000
0.555556 0.444444
0.500000 0.500000
0.250000 0.750000
0.642857 0.357143
0.400000 0.600000
0.411765 0.588235
0.250000 0.750000
0.700000 0.300000
0.500000 0.500000
0.416667 0.583333
0.692308 0.307692
0.500000 0.500000
0.357143 0.642857
0.750000 0.250000
0.181818 0.818182
0.166667 0.833333
0.250000 0.750000
0.714286 0.285714
0.769231 0.230769
0.666667 0.333333
0.714286 0.285714
0.333333 0.666667
0.285714 0.714286
0.750000 0.250000
0.166667 0.833333
0.500000 0.500000
0.466667 0.533333
0.714286 0.285714
0.545455 0.454545
0.166667 0.833333
0.428571 0.571429
0.750000 0.250000
0.307692 0.692308
0.428571 0.571429
0.818182 0.181818
0.375000 0.625000
0.625000 0.375000
0.250000 0.750000
0.700000 0.300000
0.300000 0.700000
0.625000 0.375000
0.642857 0.357143
0.428571 0.571429
0.500000 0.500000
0.777778 0.222222
0.444444 0.555556
0.333333 0.666667
0.428571 0.571429
0.307692 0.692308
0.333333 0.666667
0.166667 0.833333
0.571429 0.428571
0.333333 0.666667
0.500000 0.500000
0.538462 0.461538
0.250000 0.750000
0.416667 0.583333
0.500000 0.500000
0.500000 0.500000
0.625000 0.375000
0.473684 0.526316
0.375000 0.625000
0.470588 0.529412
0.454545 0.545455
0.500000 0.500000
0.333333 0.666667
0.500000 0.500000
0.363636 0.636364
0.600000 0.400000
0.166667 0.833333
0.769231 0.230769
0.588235 0.411765
0.642857 0.357143
0.636364 0.363636
0.833333 0.166667
0.166667 0.833333
0.470588 0.529412
0.700000 0.300000
0.700000 0.300000
0.666667 0.333333
0.714286 0.285714
0.384615 0.615385
0.500000 0.500000
0.777778 0.222222
0.454545 0.545455
0.500000 0.500000
0.181818 0.818182
0.526316 0.473684
0.700000 0.300000
0.777778 0.222222
0.529412 0.470588
0.714286 0.285714
0.428571 0.571429
0.500000 0.500000
0.588235 0.411765
0.571429 0.428571
0.750000 0.250000
0.500000 0.500000
0.666667 0.333333
0.363636 0.636364
0.571429 0.428571
0.454545 0.545455
0.444444 0.555556
0.250000 0.750000
0.363636 0.636364
0.272727 0.727273
0.333333 0.666667
0.615385 0.384615
0.615385 0.384615
0.333333 0.666667
0.583333 0.416667
0.166667 0.833333
0.428571 0.571429
0.400000 0.600000
0.454545 0.545455
0.500000 0.500000
0.714286 0.285714
0.500000 0.500000
0.800000 0.200000
0.500000 0.500000
0.500000 0.500000
0.300000 0.700000
0.454545 0.545455
0.416667 0.583333
0.615385 0.384615
0.600000 0.400000
0.357143 0.642857
0.454545 0.545455
0.230769 0.769231
0.428571 0.571429
0.500000 0.500000
0.562500 0.437500
0.555556 0.444444
0.571429 0.428571
0.750000 0.250000
0.166667 0.833333
0.285714 0.714286
0.400000 0.600000
0.461538 0.538462
0.333333 0.666667
0.555556 0.444444
0.416667 0.583333
0.466667 0.533333
0.333333 0.666667
0.444444 0.555556
0.375000 0.625000
0.642857 0.357143
0.727273 0.272727
0.470588 0.529412
0.363636 0.636364
0.714286 0.285714
0.666667 0.333333
0.411765 0.588235
0.250000 0.750000
0.437500 0.562500
0.500000 0.500000
0.400000 0.600000
0.400000 0.600000
0.428571 0.571429
0.222222 0.777778
4
0.454545 0.545455
0.363636 0.636364
8
0.285714 0.714286
0.625000 0.375000
0.400000 0.600000
0.727273 0.272727
2
0.526316 0.473684
2
0.454545 0.545455
8
0.529412 0.470588
0.500000 0.500000
0.538462 0.461538
0.500000 0.500000
16
0.526316 0.473684
0.571429 0.428571
0.562500 0.437500
0.230769 0.769231
0.333333 0.666667
0.750000 0.250000
0.333333 0.666667
0.600000 0.400000
2
0.714286 0.285714
16
0.230769 0.769231
0.454545 0.545455
0.571429 0.428571
0.777778 0.222222
0.466667 0.533333
0.250000 0.750000
0.384615 0.615385
0.571429 0.428571
16
0.666667 0.333333
0.555556 0.444444
0.363636 0.636364
0.833333 0.166667
0.400000 0.600000
0.818182 0.181818
0.692308 0.307692
0.692308 0.307692
32
0.533333 0.466667
0.400000 0.600000
0.666667 0.333333
0.333333 0.666667
0.588235 0.411765
0.363636 0.636364
0.470588 0.529412
0.500000 0.500000
0.636364 0.363636
0.400000 0.600000
0.636364 0.363636
0.428571 0.571429
0.500000 0.500000
0.714286 0.285714
0.272727 0.727273
0.357143 0.642857
8
0.250000 0.750000
0.285714 0.714286
0.583333 0.416667
0.571429 0.428571
2
0.375000 0.625000
8
0.666667 0.333333
0.300000 0.700000
0.529412 0.470588
0.473684 0.526316
2
0.500000 0.500000
16
0.666667 0.333333
0.200000 0.800000
0.500000 0.500000
0.500000 0.500000
0.666667 0.333333
0.714286 0.285714
0.470588 0.529412
0.533333 0.466667
8
0.307692 0.692308
0.470588 0.529412
0.333333 0.666667
0.333333 0.666667

View File

@ -0,0 +1,11 @@
10
0 1
2 0
9 0
16 1
20 1
21 1
22 0
26 1
39 0
41 1

View File

@ -0,0 +1,3 @@
z -2.7351873
m 54 2 0.0 1.0 2 0.5995855 0.40041456 2 1.0 0.0 2 0.3761365 0.62386346 2 0.25656807 0.7434319 2 0.6449692 0.35503078 2 0.4957979 0.5042021 2 0.69854456 0.30145544 2 0.7 0.3 2 1.0 0.0 2 0.5303537 0.46964625 2 0.44570237 0.5542976 2 0.5 0.5 2 0.55686617 0.4431338 2 0.6284742 0.3715258 2 0.5607879 0.43921205 2 0.0 1.0 2 0.54289234 0.4571077 2 0.5770133 0.42298666 2 0.547688 0.452312 2 0.0 1.0 2 0.0 1.0 2 1.0 0.0 2 0.5760513 0.4239487 2 0.592929 0.40707102 2 0.63438964 0.36561036 2 0.0 1.0 2 0.52899235 0.47100765 2 0.5998554 0.40014458 2 0.7750039 0.22499608 2 0.50000435 0.49999565 2 0.36475798 0.63524204 2 0.44666538 0.55333465 2 0.43111995 0.56888 2 0.37207335 0.62792665 2 0.5581817 0.4418183 2 0.16809757 0.83190244 2 0.4813641 0.5186359 2 0.43732184 0.56267816 2 1.0 0.0 2 0.54721755 0.45278242 2 0.0 1.0 2 0.51865995 0.48134002 2 0.51229435 0.48770565 2 0.7142385 0.2857615 2 0.53666514 0.46333483 2 0.6171147 0.38288528 2 0.46532288 0.5346771 2 0.46330887 0.5366911 2 0.36718464 0.63281536 2 0.4735739 0.5264261 2 0.5244508 0.4755492 2 0.604569 0.395431 2 0.3945428 0.6054572
s -11.533098 54 1 0 0 1 1 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 0 1 0 1 0 1 1 0 0 1

View File

@ -0,0 +1,269 @@
BAYES
21
4 4 4 4 4 4 4 4 4 2 2 2 2 2 2 2 2 2 2 2 2
21
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
3 1 0 9
3 1 3 10
3 5 1 11
3 2 6 12
3 6 4 13
3 3 6 14
3 5 7 15
3 7 2 16
3 7 3 17
3 0 8 18
3 3 8 19
3 8 4 20
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.25 0.25 0.25 0.25
4
0.1 0.2 0.3 0.4
4
0.25 0.25 0.25 0.25
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
32
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1
0.1 0.9
0.1 0.9
0.1 0.9
0.1 0.9
0.9 0.1

View File

@ -0,0 +1,13 @@
12
17 0
10 0
19 0
18 0
11 0
13 0
15 0
20 0
9 0
12 0
16 0
14 0

View File

@ -0,0 +1,3 @@
z -5.264346
m 21 4 0.116109975 0.20537 0.29463002 0.38389003 4 0.10865768 0.2028859 0.2971141 0.3913423 4 0.11159538 0.20386513 0.29613486 0.3884046 4 0.105094366 0.20169812 0.29830188 0.39490563 4 0.116109975 0.20537 0.29463002 0.38389003 4 0.11159538 0.20386513 0.29613486 0.3884046 4 0.10865768 0.2028859 0.2971141 0.3913423 4 0.1 0.2 0.3 0.4 4 0.10956474 0.20318824 0.29681176 0.39043528 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0 2 1.0 0.0
s -5.7635098 21 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1,94 @@
MARKOV
9
4 4 4 4 4 4 4 4 4
13
1 7
2 1 0
2 1 3
2 5 1
2 2 6
2 6 4
2 3 6
2 5 7
2 7 2
2 7 3
2 0 8
2 3 8
2 8 4
4
0.1 0.2 0.3 0.4
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9
16
0.9 0.1 0.1 0.1
0.1 0.9 0.1 0.1
0.1 0.1 0.9 0.1
0.1 0.1 0.1 0.9

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,3 @@
z -0.44786617
m 9 4 0.116109975 0.20537 0.29463002 0.38389003 4 0.10865768 0.2028859 0.2971141 0.3913423 4 0.11159538 0.20386513 0.29613486 0.3884046 4 0.105094366 0.20169812 0.29830188 0.39490563 4 0.116109975 0.20537 0.29463002 0.38389003 4 0.11159538 0.20386513 0.29613486 0.3884046 4 0.10865768 0.2028859 0.2971141 0.3913423 4 0.1 0.2 0.3 0.4 4 0.10956474 0.20318824 0.29681176 0.39043528
s -0.9470299 9 3 3 3 3 3 3 3 3 3

View File

@ -0,0 +1,524 @@
/*
* @file testDecisionTree.cpp
* @brief Develop DecisionTree
* @author Frank Dellaert
* @date Mar 6, 2011
*/
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/DiscreteKey.h> // make sure we have traits
// headers first to make sure no missing headers
//#define DT_NO_PRUNING
#include <gtsam/discrete/AlgebraicDecisionTree.h>
#include <gtsam/discrete/DecisionTree-inl.h> // for convert only
#define DISABLE_TIMING
#include <boost/version.hpp> // for checking whether we are using boost 1.40
#if BOOST_VERSION >= 104200
#define BOOST_HAVE_PARSER
#endif
#include <boost/timer.hpp>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <gtsam/discrete/Signature.h>
using namespace std;
using namespace gtsam;
/* ******************************************************************************** */
typedef AlgebraicDecisionTree<Index> ADT;
template class DecisionTree<Index,double>;
template class AlgebraicDecisionTree<Index>;
#define DISABLE_DOT
template<typename T>
void dot(const T&f, const string& filename) {
#ifndef DISABLE_DOT
f.dot(filename);
#endif
}
/** I can't get this to work !
class Mul: boost::function<double(const double&, const double&)> {
inline double operator()(const double& a, const double& b) {
return a * b;
}
};
// If second argument of binary op is Leaf
template<typename L>
typename DecisionTree<L, double>::Node::Ptr DecisionTree<L, double>::Choice::apply_fC_op_gL(
Cache& cache, const Leaf& gL, Mul op) const {
Ptr h(new Choice(label(), cardinality()));
BOOST_FOREACH(const NodePtr& branch, branches_)
h->push_back(branch->apply_f_op_g(cache, gL, op));
return Unique(cache, h);
}
*/
/* ******************************************************************************** */
// instrumented operators
/* ******************************************************************************** */
size_t muls = 0, adds = 0;
boost::timer timer;
void resetCounts() {
muls = 0;
adds = 0;
timer.restart();
}
void printCounts(const string& s) {
#ifndef DISABLE_TIMING
cout << boost::format("%s: %3d muls, %3d adds, %g ms.") % s % muls % adds
% (1000 * timer.elapsed()) << endl;
#endif
resetCounts();
}
double mul(const double& a, const double& b) {
muls++;
return a * b;
}
double add_(const double& a, const double& b) {
adds++;
return a + b;
}
/* ******************************************************************************** */
// test ADT
TEST(ADT, example3)
{
// Create labels
DiscreteKey A(0,2), B(1,2), C(2,2), D(3,2), E(4,2);
// Literals
ADT a(A, 0.5, 0.5);
ADT notb(B, 1, 0);
ADT c(C, 0.1, 0.9);
ADT d(D, 0.1, 0.9);
ADT note(E, 0.9, 0.1);
ADT cnotb = c * notb;
dot(cnotb, "ADT-cnotb");
// a.print("a: ");
// cnotb.print("cnotb: ");
ADT acnotb = a * cnotb;
// acnotb.print("acnotb: ");
// acnotb.printCache("acnotb Cache:");
dot(acnotb, "ADT-acnotb");
ADT big = apply(apply(d, note, &mul), acnotb, &add_);
dot(big, "ADT-big");
}
/* ******************************************************************************** */
// Asia Bayes Network
/* ******************************************************************************** */
/** Convert Signature into CPT */
ADT create(const Signature& signature) {
ADT p(signature.discreteKeysParentsFirst(), signature.cpt());
static size_t count = 0;
const DiscreteKey& key = signature.key();
string dotfile = (boost::format("CPT-%03d-%d") % ++count % key.first).str();
dot(p, dotfile);
return p;
}
/* ************************************************************************* */
// test Asia Joint
TEST(ADT, joint)
{
DiscreteKey A(0, 2), S(1, 2), T(2, 2), L(3, 2), B(4, 2), E(5, 2), X(6, 2), D(7, 2);
#ifdef BOOST_HAVE_PARSER
resetCounts();
ADT pA = create(A % "99/1");
ADT pS = create(S % "50/50");
ADT pT = create(T | A = "99/1 95/5");
ADT pL = create(L | S = "99/1 90/10");
ADT pB = create(B | S = "70/30 40/60");
ADT pE = create((E | T, L) = "F T T T");
ADT pX = create(X | E = "95/5 2/98");
ADT pD = create((D | E, B) = "9/1 2/8 3/7 1/9");
printCounts("Asia CPTs");
// Create joint
resetCounts();
ADT joint = pA;
dot(joint, "Asia-A");
joint = apply(joint, pS, &mul);
dot(joint, "Asia-AS");
joint = apply(joint, pT, &mul);
dot(joint, "Asia-AST");
joint = apply(joint, pL, &mul);
dot(joint, "Asia-ASTL");
joint = apply(joint, pB, &mul);
dot(joint, "Asia-ASTLB");
joint = apply(joint, pE, &mul);
dot(joint, "Asia-ASTLBE");
joint = apply(joint, pX, &mul);
dot(joint, "Asia-ASTLBEX");
joint = apply(joint, pD, &mul);
dot(joint, "Asia-ASTLBEXD");
EXPECT_LONGS_EQUAL(346, muls);
printCounts("Asia joint");
ADT pASTL = pA;
pASTL = apply(pASTL, pS, &mul);
pASTL = apply(pASTL, pT, &mul);
pASTL = apply(pASTL, pL, &mul);
// test combine
ADT fAa = pASTL.combine(L, &add_).combine(T, &add_).combine(S, &add_);
EXPECT(assert_equal(pA, fAa));
ADT fAb = pASTL.combine(S, &add_).combine(T, &add_).combine(L, &add_);
EXPECT(assert_equal(pA, fAb));
#endif
}
/* ************************************************************************* */
// test Inference with joint
TEST(ADT, inference)
{
DiscreteKey A(0,2), D(1,2),//
B(2,2), L(3,2), E(4,2), S(5,2), T(6,2), X(7,2);
#ifdef BOOST_HAVE_PARSER
resetCounts();
ADT pA = create(A % "99/1");
ADT pS = create(S % "50/50");
ADT pT = create(T | A = "99/1 95/5");
ADT pL = create(L | S = "99/1 90/10");
ADT pB = create(B | S = "70/30 40/60");
ADT pE = create((E | T, L) = "F T T T");
ADT pX = create(X | E = "95/5 2/98");
ADT pD = create((D | E, B) = "9/1 2/8 3/7 1/9");
// printCounts("Inference CPTs");
// Create joint
resetCounts();
ADT joint = pA;
dot(joint, "Joint-Product-A");
joint = apply(joint, pS, &mul);
dot(joint, "Joint-Product-AS");
joint = apply(joint, pT, &mul);
dot(joint, "Joint-Product-AST");
joint = apply(joint, pL, &mul);
dot(joint, "Joint-Product-ASTL");
joint = apply(joint, pB, &mul);
dot(joint, "Joint-Product-ASTLB");
joint = apply(joint, pE, &mul);
dot(joint, "Joint-Product-ASTLBE");
joint = apply(joint, pX, &mul);
dot(joint, "Joint-Product-ASTLBEX");
joint = apply(joint, pD, &mul);
dot(joint, "Joint-Product-ASTLBEXD");
EXPECT_LONGS_EQUAL(370, muls); // different ordering
printCounts("Asia product");
ADT marginal = joint;
marginal = marginal.combine(X, &add_);
dot(marginal, "Joint-Sum-ADBLEST");
marginal = marginal.combine(T, &add_);
dot(marginal, "Joint-Sum-ADBLES");
marginal = marginal.combine(S, &add_);
dot(marginal, "Joint-Sum-ADBLE");
marginal = marginal.combine(E, &add_);
dot(marginal, "Joint-Sum-ADBL");
EXPECT_LONGS_EQUAL(161, adds);
printCounts("Asia sum");
#endif
}
/* ************************************************************************* */
TEST(ADT, factor_graph)
{
DiscreteKey B(0,2), L(1,2), E(2,2), S(3,2), T(4,2), X(5,2);
#ifdef BOOST_HAVE_PARSER
resetCounts();
ADT pS = create(S % "50/50");
ADT pT = create(T % "95/5");
ADT pL = create(L | S = "99/1 90/10");
ADT pE = create((E | T, L) = "F T T T");
ADT pX = create(X | E = "95/5 2/98");
ADT pD = create(B | E = "1/8 7/9");
ADT pB = create(B | S = "70/30 40/60");
// printCounts("Create CPTs");
// Create joint
resetCounts();
ADT fg = pS;
fg = apply(fg, pT, &mul);
fg = apply(fg, pL, &mul);
fg = apply(fg, pB, &mul);
fg = apply(fg, pE, &mul);
fg = apply(fg, pX, &mul);
fg = apply(fg, pD, &mul);
dot(fg, "FactorGraph");
EXPECT_LONGS_EQUAL(158, muls);
printCounts("Asia FG");
fg = fg.combine(X, &add_);
dot(fg, "Marginalized-6X");
fg = fg.combine(T, &add_);
dot(fg, "Marginalized-5T");
fg = fg.combine(S, &add_);
dot(fg, "Marginalized-4S");
fg = fg.combine(E, &add_);
dot(fg, "Marginalized-3E");
fg = fg.combine(L, &add_);
dot(fg, "Marginalized-2L");
EXPECT(adds = 54);
printCounts("marginalize");
// BLESTX
// Eliminate X
ADT fE = pX;
dot(fE, "Eliminate-01-fEX");
fE = fE.combine(X, &add_);
dot(fE, "Eliminate-02-fE");
printCounts("Eliminate X");
// Eliminate T
ADT fLE = pT;
fLE = apply(fLE, pE, &mul);
dot(fLE, "Eliminate-03-fLET");
fLE = fLE.combine(T, &add_);
dot(fLE, "Eliminate-04-fLE");
printCounts("Eliminate T");
// Eliminate S
ADT fBL = pS;
fBL = apply(fBL, pL, &mul);
fBL = apply(fBL, pB, &mul);
dot(fBL, "Eliminate-05-fBLS");
fBL = fBL.combine(S, &add_);
dot(fBL, "Eliminate-06-fBL");
printCounts("Eliminate S");
// Eliminate E
ADT fBL2 = fE;
fBL2 = apply(fBL2, fLE, &mul);
fBL2 = apply(fBL2, pD, &mul);
dot(fBL2, "Eliminate-07-fBLE");
fBL2 = fBL2.combine(E, &add_);
dot(fBL2, "Eliminate-08-fBL2");
printCounts("Eliminate E");
// Eliminate L
ADT fB = fBL;
fB = apply(fB, fBL2, &mul);
dot(fB, "Eliminate-09-fBL");
fB = fB.combine(L, &add_);
dot(fB, "Eliminate-10-fB");
printCounts("Eliminate L");
#endif
}
/* ************************************************************************* */
// test equality
TEST(ADT, equality_noparser)
{
DiscreteKey A(0,2), B(1,2);
Signature::Table tableA, tableB;
Signature::Row rA, rB;
rA += 80, 20; rB += 60, 40;
tableA += rA; tableB += rB;
// Check straight equality
ADT pA1 = create(A % tableA);
ADT pA2 = create(A % tableA);
EXPECT(pA1 == pA2); // should be equal
// Check equality after apply
ADT pB = create(B % tableB);
ADT pAB1 = apply(pA1, pB, &mul);
ADT pAB2 = apply(pB, pA1, &mul);
EXPECT(pAB2 == pAB1);
}
/* ************************************************************************* */
#ifdef BOOST_HAVE_PARSER
// test equality
TEST(ADT, equality_parser)
{
DiscreteKey A(0,2), B(1,2);
// Check straight equality
ADT pA1 = create(A % "80/20");
ADT pA2 = create(A % "80/20");
EXPECT(pA1 == pA2); // should be equal
// Check equality after apply
ADT pB = create(B % "60/40");
ADT pAB1 = apply(pA1, pB, &mul);
ADT pAB2 = apply(pB, pA1, &mul);
EXPECT(pAB2 == pAB1);
}
#endif
/* ******************************************************************************** */
// Factor graph construction
// test constructor from strings
TEST(ADT, constructor)
{
DiscreteKey v0(0,2), v1(1,3);
Assignment<Index> x00, x01, x02, x10, x11, x12;
x00[0] = 0, x00[1] = 0;
x01[0] = 0, x01[1] = 1;
x02[0] = 0, x02[1] = 2;
x10[0] = 1, x10[1] = 0;
x11[0] = 1, x11[1] = 1;
x12[0] = 1, x12[1] = 2;
ADT f1(v0 & v1, "0 1 2 3 4 5");
EXPECT_DOUBLES_EQUAL(0, f1(x00), 1e-9);
EXPECT_DOUBLES_EQUAL(1, f1(x01), 1e-9);
EXPECT_DOUBLES_EQUAL(2, f1(x02), 1e-9);
EXPECT_DOUBLES_EQUAL(3, f1(x10), 1e-9);
EXPECT_DOUBLES_EQUAL(4, f1(x11), 1e-9);
EXPECT_DOUBLES_EQUAL(5, f1(x12), 1e-9);
ADT f2(v1 & v0, "0 1 2 3 4 5");
EXPECT_DOUBLES_EQUAL(0, f2(x00), 1e-9);
EXPECT_DOUBLES_EQUAL(2, f2(x01), 1e-9);
EXPECT_DOUBLES_EQUAL(4, f2(x02), 1e-9);
EXPECT_DOUBLES_EQUAL(1, f2(x10), 1e-9);
EXPECT_DOUBLES_EQUAL(3, f2(x11), 1e-9);
EXPECT_DOUBLES_EQUAL(5, f2(x12), 1e-9);
DiscreteKey z0(0,5), z1(1,4), z2(2,3), z3(3,2);
vector<double> table(5 * 4 * 3 * 2);
double x = 0;
BOOST_FOREACH(double& t, table)
t = x++;
ADT f3(z0 & z1 & z2 & z3, table);
Assignment<Index> assignment;
assignment[0] = 0;
assignment[1] = 0;
assignment[2] = 0;
assignment[3] = 1;
EXPECT_DOUBLES_EQUAL(1, f3(assignment), 1e-9);
}
/* ************************************************************************* */
// test conversion to integer indices
// Only works if DiscreteKeys are binary, as size_t has binary cardinality!
TEST(ADT, conversion)
{
DiscreteKey X(0,2), Y(1,2);
ADT fDiscreteKey(X & Y, "0.2 0.5 0.3 0.6");
dot(fDiscreteKey, "conversion-f1");
std::map<size_t, size_t> ordering;
ordering[0] = 5;
ordering[1] = 2;
AlgebraicDecisionTree<size_t> fIndexKey(fDiscreteKey, ordering);
// f1.print("f1");
// f2.print("f2");
dot(fIndexKey, "conversion-f2");
Assignment<size_t> x00, x01, x02, x10, x11, x12;
x00[5] = 0, x00[2] = 0;
x01[5] = 0, x01[2] = 1;
x10[5] = 1, x10[2] = 0;
x11[5] = 1, x11[2] = 1;
EXPECT_DOUBLES_EQUAL(0.2, fIndexKey(x00), 1e-9);
EXPECT_DOUBLES_EQUAL(0.5, fIndexKey(x01), 1e-9);
EXPECT_DOUBLES_EQUAL(0.3, fIndexKey(x10), 1e-9);
EXPECT_DOUBLES_EQUAL(0.6, fIndexKey(x11), 1e-9);
}
/* ******************************************************************************** */
// test operations in elimination
TEST(ADT, elimination)
{
DiscreteKey A(0,2), B(1,3), C(2,2);
ADT f1(A & B & C, "1 2 3 4 5 6 1 8 3 3 5 5");
dot(f1, "elimination-f1");
{
// sum out lower key
ADT actualSum = f1.sum(C);
ADT expectedSum(A & B, "3 7 11 9 6 10");
CHECK(assert_equal(expectedSum,actualSum));
// normalize
ADT actual = f1 / actualSum;
vector<double> cpt;
cpt += 1.0 / 3, 2.0 / 3, 3.0 / 7, 4.0 / 7, 5.0 / 11, 6.0 / 11, //
1.0 / 9, 8.0 / 9, 3.0 / 6, 3.0 / 6, 5.0 / 10, 5.0 / 10;
ADT expected(A & B & C, cpt);
CHECK(assert_equal(expected,actual));
}
{
// sum out lower 2 keys
ADT actualSum = f1.sum(C).sum(B);
ADT expectedSum(A, 21, 25);
CHECK(assert_equal(expectedSum,actualSum));
// normalize
ADT actual = f1 / actualSum;
vector<double> cpt;
cpt += 1.0 / 21, 2.0 / 21, 3.0 / 21, 4.0 / 21, 5.0 / 21, 6.0 / 21, //
1.0 / 25, 8.0 / 25, 3.0 / 25, 3.0 / 25, 5.0 / 25, 5.0 / 25;
ADT expected(A & B & C, cpt);
CHECK(assert_equal(expected,actual));
}
}
/* ******************************************************************************** */
// Test non-commutative op
TEST(ADT, div)
{
DiscreteKey A(0,2), B(1,2);
// Literals
ADT a(A, 8, 16);
ADT b(B, 2, 4);
ADT expected_a_div_b(A & B, "4 2 8 4"); // 8/2 8/4 16/2 16/4
ADT expected_b_div_a(A & B, "0.25 0.5 0.125 0.25"); // 2/8 4/8 2/16 4/16
EXPECT(assert_equal(expected_a_div_b, a / b));
EXPECT(assert_equal(expected_b_div_a, b / a));
}
/* ******************************************************************************** */
// test zero shortcut
TEST(ADT, zero)
{
DiscreteKey A(0,2), B(1,2);
// Literals
ADT a(A, 0, 1);
ADT notb(B, 1, 0);
ADT anotb = a * notb;
// GTSAM_PRINT(anotb);
Assignment<Index> x00, x01, x10, x11;
x00[0] = 0, x00[1] = 0;
x01[0] = 0, x01[1] = 1;
x10[0] = 1, x10[1] = 0;
x11[0] = 1, x11[1] = 1;
EXPECT_DOUBLES_EQUAL(0, anotb(x00), 1e-9);
EXPECT_DOUBLES_EQUAL(0, anotb(x01), 1e-9);
EXPECT_DOUBLES_EQUAL(1, anotb(x10), 1e-9);
EXPECT_DOUBLES_EQUAL(0, anotb(x11), 1e-9);
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,224 @@
/*
* testCSP.cpp
* @brief develop code for CSP solver
* @date Feb 5, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/CSP.h>
#include <gtsam/discrete/Domain.h>
#include <CppUnitLite/TestHarness.h>
#include <iostream>
#include <fstream>
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
TEST_UNSAFE( BinaryAllDif, allInOne)
{
// Create keys and ordering
size_t nrColors = 2;
// DiscreteKey ID("Idaho", nrColors), UT("Utah", nrColors), AZ("Arizona", nrColors);
DiscreteKey ID(0, nrColors), UT(2, nrColors), AZ(1, nrColors);
// Check construction and conversion
BinaryAllDiff c1(ID, UT);
DecisionTreeFactor f1(ID & UT, "0 1 1 0");
EXPECT(assert_equal(f1,(DecisionTreeFactor)c1));
// Check construction and conversion
BinaryAllDiff c2(UT, AZ);
DecisionTreeFactor f2(UT & AZ, "0 1 1 0");
EXPECT(assert_equal(f2,(DecisionTreeFactor)c2));
DecisionTreeFactor f3 = f1*f2;
EXPECT(assert_equal(f3,c1*f2));
EXPECT(assert_equal(f3,c2*f1));
}
/* ************************************************************************* */
TEST_UNSAFE( CSP, allInOne)
{
// Create keys and ordering
size_t nrColors = 2;
DiscreteKey ID(0, nrColors), UT(2, nrColors), AZ(1, nrColors);
// Create the CSP
CSP csp;
csp.addAllDiff(ID,UT);
csp.addAllDiff(UT,AZ);
// Check an invalid combination, with ID==UT==AZ all same color
DiscreteFactor::Values invalid;
invalid[ID.first] = 0;
invalid[UT.first] = 0;
invalid[AZ.first] = 0;
EXPECT_DOUBLES_EQUAL(0, csp(invalid), 1e-9);
// Check a valid combination
DiscreteFactor::Values valid;
valid[ID.first] = 0;
valid[UT.first] = 1;
valid[AZ.first] = 0;
EXPECT_DOUBLES_EQUAL(1, csp(valid), 1e-9);
// Just for fun, create the product and check it
DecisionTreeFactor product = csp.product();
// product.dot("product");
DecisionTreeFactor expectedProduct(ID & AZ & UT, "0 1 0 0 0 0 1 0");
EXPECT(assert_equal(expectedProduct,product));
// Solve
CSP::sharedValues mpe = csp.optimalAssignment();
CSP::Values expected;
insert(expected)(ID.first, 1)(UT.first, 0)(AZ.first, 1);
EXPECT(assert_equal(expected,*mpe));
EXPECT_DOUBLES_EQUAL(1, csp(*mpe), 1e-9);
}
/* ************************************************************************* */
TEST_UNSAFE( CSP, WesternUS)
{
// Create keys
size_t nrColors = 4;
DiscreteKey
// Create ordering according to example in ND-CSP.lyx
WA(0, nrColors), OR(3, nrColors), CA(1, nrColors),NV(2, nrColors),
ID(8, nrColors), UT(9, nrColors), AZ(10, nrColors),
MT(4, nrColors), WY(5, nrColors), CO(7, nrColors), NM(6, nrColors);
// Create the CSP
CSP csp;
csp.addAllDiff(WA,ID);
csp.addAllDiff(WA,OR);
csp.addAllDiff(OR,ID);
csp.addAllDiff(OR,CA);
csp.addAllDiff(OR,NV);
csp.addAllDiff(CA,NV);
csp.addAllDiff(CA,AZ);
csp.addAllDiff(ID,MT);
csp.addAllDiff(ID,WY);
csp.addAllDiff(ID,UT);
csp.addAllDiff(ID,NV);
csp.addAllDiff(NV,UT);
csp.addAllDiff(NV,AZ);
csp.addAllDiff(UT,WY);
csp.addAllDiff(UT,CO);
csp.addAllDiff(UT,NM);
csp.addAllDiff(UT,AZ);
csp.addAllDiff(AZ,CO);
csp.addAllDiff(AZ,NM);
csp.addAllDiff(MT,WY);
csp.addAllDiff(WY,CO);
csp.addAllDiff(CO,NM);
// Solve
CSP::sharedValues mpe = csp.optimalAssignment();
// GTSAM_PRINT(*mpe);
CSP::Values expected;
insert(expected)
(WA.first,1)(CA.first,1)(NV.first,3)(OR.first,0)
(MT.first,1)(WY.first,0)(NM.first,3)(CO.first,2)
(ID.first,2)(UT.first,1)(AZ.first,0);
EXPECT(assert_equal(expected,*mpe));
EXPECT_DOUBLES_EQUAL(1, csp(*mpe), 1e-9);
// Write out the dual graph for hmetis
#ifdef DUAL
VariableIndex index(csp);
index.print("index");
ofstream os("/Users/dellaert/src/hmetis-1.5-osx-i686/US-West-dual.txt");
index.outputMetisFormat(os);
#endif
}
/* ************************************************************************* */
TEST_UNSAFE( CSP, AllDiff)
{
// Create keys and ordering
size_t nrColors = 3;
DiscreteKey ID(0, nrColors), UT(2, nrColors), AZ(1, nrColors);
// Create the CSP
CSP csp;
vector<DiscreteKey> dkeys;
dkeys += ID,UT,AZ;
csp.addAllDiff(dkeys);
csp.addSingleValue(AZ,2);
//GTSAM_PRINT(csp);
// Check construction and conversion
SingleValue s(AZ,2);
DecisionTreeFactor f1(AZ,"0 0 1");
EXPECT(assert_equal(f1,(DecisionTreeFactor)s));
// Check construction and conversion
AllDiff alldiff(dkeys);
DecisionTreeFactor actual = (DecisionTreeFactor)alldiff;
// GTSAM_PRINT(actual);
// actual.dot("actual");
DecisionTreeFactor f2(ID & AZ & UT,
"0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0");
EXPECT(assert_equal(f2,actual));
// Check an invalid combination, with ID==UT==AZ all same color
DiscreteFactor::Values invalid;
invalid[ID.first] = 0;
invalid[UT.first] = 1;
invalid[AZ.first] = 0;
EXPECT_DOUBLES_EQUAL(0, csp(invalid), 1e-9);
// Check a valid combination
DiscreteFactor::Values valid;
valid[ID.first] = 0;
valid[UT.first] = 1;
valid[AZ.first] = 2;
EXPECT_DOUBLES_EQUAL(1, csp(valid), 1e-9);
// Solve
CSP::sharedValues mpe = csp.optimalAssignment();
CSP::Values expected;
insert(expected)(ID.first, 1)(UT.first, 0)(AZ.first, 2);
EXPECT(assert_equal(expected,*mpe));
EXPECT_DOUBLES_EQUAL(1, csp(*mpe), 1e-9);
// Arc-consistency
vector<Domain> domains;
domains += Domain(ID), Domain(AZ), Domain(UT);
SingleValue singleValue(AZ,2);
EXPECT(singleValue.ensureArcConsistency(1,domains));
EXPECT(alldiff.ensureArcConsistency(0,domains));
EXPECT(!alldiff.ensureArcConsistency(1,domains));
EXPECT(alldiff.ensureArcConsistency(2,domains));
LONGS_EQUAL(2,domains[0].nrValues());
LONGS_EQUAL(1,domains[1].nrValues());
LONGS_EQUAL(2,domains[2].nrValues());
// Parial application, version 1
DiscreteFactor::Values known;
known[AZ.first] = 2;
DiscreteFactor::shared_ptr reduced1 = alldiff.partiallyApply(known);
DecisionTreeFactor f3(ID & UT, "0 1 1 1 0 1 1 1 0");
EXPECT(assert_equal(f3,reduced1->operator DecisionTreeFactor()));
DiscreteFactor::shared_ptr reduced2 = singleValue.partiallyApply(known);
DecisionTreeFactor f4(AZ, "0 0 1");
EXPECT(assert_equal(f4,reduced2->operator DecisionTreeFactor()));
// Parial application, version 2
DiscreteFactor::shared_ptr reduced3 = alldiff.partiallyApply(domains);
EXPECT(assert_equal(f3,reduced3->operator DecisionTreeFactor()));
DiscreteFactor::shared_ptr reduced4 = singleValue.partiallyApply(domains);
EXPECT(assert_equal(f4,reduced4->operator DecisionTreeFactor()));
// full arc-consistency test
csp.runArcConsistency(nrColors);
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,226 @@
/*
* @file testDecisionTree.cpp
* @brief Develop DecisionTree
* @author Frank Dellaert
* @author Can Erdogan
* @date Jan 30, 2012
*/
#include <boost/timer.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/Signature.h>
//#define DT_DEBUG_MEMORY
//#define DT_NO_PRUNING
#define DISABLE_DOT
#include <gtsam/discrete/DecisionTree-inl.h>
using namespace std;
using namespace gtsam;
template<typename T>
void dot(const T&f, const string& filename) {
#ifndef DISABLE_DOT
f.dot(filename);
#endif
}
#define DOT(x)(dot(x,#x))
/* ******************************************************************************** */
// Test string labels and int range
/* ******************************************************************************** */
typedef DecisionTree<string, int> DT;
struct Ring {
static inline int zero() {
return 0;
}
static inline int one() {
return 1;
}
static inline int add(const int& a, const int& b) {
return a + b;
}
static inline int mul(const int& a, const int& b) {
return a * b;
}
};
/* ******************************************************************************** */
// test DT
TEST(DT, example)
{
// Create labels
string A("A"), B("B"), C("C");
// create a value
Assignment<string> x00, x01, x10, x11;
x00[A] = 0, x00[B] = 0;
x01[A] = 0, x01[B] = 1;
x10[A] = 1, x10[B] = 0;
x11[A] = 1, x11[B] = 1;
// A
DT a(A, 0, 5);
LONGS_EQUAL(0,a(x00))
LONGS_EQUAL(5,a(x10))
DOT(a);
// pruned
DT p(A, 2, 2);
LONGS_EQUAL(2,p(x00))
LONGS_EQUAL(2,p(x10))
DOT(p);
// \neg B
DT notb(B, 5, 0);
LONGS_EQUAL(5,notb(x00))
LONGS_EQUAL(5,notb(x10))
DOT(notb);
// apply, two nodes, in natural order
DT anotb = apply(a, notb, &Ring::mul);
LONGS_EQUAL(0,anotb(x00))
LONGS_EQUAL(0,anotb(x01))
LONGS_EQUAL(25,anotb(x10))
LONGS_EQUAL(0,anotb(x11))
DOT(anotb);
// check pruning
DT pnotb = apply(p, notb, &Ring::mul);
LONGS_EQUAL(10,pnotb(x00))
LONGS_EQUAL( 0,pnotb(x01))
LONGS_EQUAL(10,pnotb(x10))
LONGS_EQUAL( 0,pnotb(x11))
DOT(pnotb);
// check pruning
DT zeros = apply(DT(A, 0, 0), notb, &Ring::mul);
LONGS_EQUAL(0,zeros(x00))
LONGS_EQUAL(0,zeros(x01))
LONGS_EQUAL(0,zeros(x10))
LONGS_EQUAL(0,zeros(x11))
DOT(zeros);
// apply, two nodes, in switched order
DT notba = apply(a, notb, &Ring::mul);
LONGS_EQUAL(0,notba(x00))
LONGS_EQUAL(0,notba(x01))
LONGS_EQUAL(25,notba(x10))
LONGS_EQUAL(0,notba(x11))
DOT(notba);
// Test choose 0
DT actual0 = notba.choose(A, 0);
EXPECT(assert_equal(DT(0.0), actual0));
DOT(actual0);
// Test choose 1
DT actual1 = notba.choose(A, 1);
EXPECT(assert_equal(DT(B, 25, 0), actual1));
DOT(actual1);
// apply, two nodes at same level
DT a_and_a = apply(a, a, &Ring::mul);
LONGS_EQUAL(0,a_and_a(x00))
LONGS_EQUAL(0,a_and_a(x01))
LONGS_EQUAL(25,a_and_a(x10))
LONGS_EQUAL(25,a_and_a(x11))
DOT(a_and_a);
// create a function on C
DT c(C, 0, 5);
// and a model assigning stuff to C
Assignment<string> x101;
x101[A] = 1, x101[B] = 0, x101[C] = 1;
// mul notba with C
DT notbac = apply(notba, c, &Ring::mul);
LONGS_EQUAL(125,notbac(x101))
DOT(notbac);
// mul now in different order
DT acnotb = apply(apply(a, c, &Ring::mul), notb, &Ring::mul);
LONGS_EQUAL(125,acnotb(x101))
DOT(acnotb);
}
/* ******************************************************************************** */
// test Conversion
enum Label {
U, V, X, Y, Z
};
typedef DecisionTree<Label, bool> BDT;
bool convert(const int& y) {
return y != 0;
}
TEST(DT, conversion)
{
// Create labels
string A("A"), B("B");
// apply, two nodes, in natural order
DT f1 = apply(DT(A, 0, 5), DT(B, 5, 0), &Ring::mul);
// convert
map<string, Label> ordering;
ordering[A] = X;
ordering[B] = Y;
boost::function<bool(const int&)> op = convert;
BDT f2(f1, ordering, op);
// f1.print("f1");
// f2.print("f2");
// create a value
Assignment<Label> x00, x01, x10, x11;
x00[X] = 0, x00[Y] = 0;
x01[X] = 0, x01[Y] = 1;
x10[X] = 1, x10[Y] = 0;
x11[X] = 1, x11[Y] = 1;
EXPECT(!f2(x00));
EXPECT(!f2(x01));
EXPECT(f2(x10));
EXPECT(!f2(x11));
}
/* ******************************************************************************** */
// test Compose expansion
TEST(DT, Compose)
{
// Create labels
string A("A"), B("B"), C("C");
// Put two stumps on A together
DT f1(B, DT(A, 0, 1), DT(A, 2, 3));
// Create from string
vector<DT::LabelC> keys;
keys += DT::LabelC(A,2), DT::LabelC(B,2);
DT f2(keys, "0 2 1 3");
EXPECT(assert_equal(f2, f1, 1e-9));
// Put this AB tree together with another one
DT f3(keys, "4 6 5 7");
DT f4(C, f1, f3);
DOT(f4);
// a bigger tree
keys += DT::LabelC(C,2);
DT f5(keys, "0 4 2 6 1 5 3 7");
EXPECT(assert_equal(f5, f4, 1e-9));
DOT(f5);
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,96 @@
/*
* testDecisionTreeFactor.cpp
*
* @date Feb 5, 2012
* @author Frank Dellaert
* @author Duy-Nguyen Ta
*/
#include <gtsam/discrete/Signature.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/base/Testable.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
using namespace boost::assign;
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
TEST( DecisionTreeFactor, constructors)
{
DiscreteKey X(0,2), Y(1,3), Z(2,2);
DecisionTreeFactor f1(X, "2 8");
DecisionTreeFactor f2(X & Y, "2 5 3 6 4 7");
DecisionTreeFactor f3(X & Y & Z, "2 5 3 6 4 7 25 55 35 65 45 75");
EXPECT_LONGS_EQUAL(1,f1.size());
EXPECT_LONGS_EQUAL(2,f2.size());
EXPECT_LONGS_EQUAL(3,f3.size());
// f1.print("f1:");
// f2.print("f2:");
// f3.print("f3:");
DecisionTreeFactor::Values values;
values[0] = 1; // x
values[1] = 2; // y
values[2] = 1; // z
EXPECT_DOUBLES_EQUAL(8, f1(values), 1e-9);
EXPECT_DOUBLES_EQUAL(7, f2(values), 1e-9);
EXPECT_DOUBLES_EQUAL(75, f3(values), 1e-9);
}
/* ************************************************************************* */
TEST_UNSAFE( DecisionTreeFactor, multiplication)
{
// Declare a bunch of keys
DiscreteKey v0(0,2), v1(1,2), v2(2,2);
// Create a factor
DecisionTreeFactor f1(v0 & v1, "1 2 3 4");
DecisionTreeFactor f2(v1 & v2, "5 6 7 8");
// f1.print("f1:");
// f2.print("f2:");
DecisionTreeFactor expected(v0 & v1 & v2, "5 6 14 16 15 18 28 32");
DecisionTreeFactor actual = f1 * f2;
// actual.print("actual: ");
CHECK(assert_equal(expected, actual));
}
/* ************************************************************************* */
TEST( DecisionTreeFactor, sum_max)
{
// Declare a bunch of keys
DiscreteKey v0(0,3), v1(1,2);
// Create a factor
DecisionTreeFactor f1(v0 & v1, "1 2 3 4 5 6");
DecisionTreeFactor expected(v1, "9 12");
DecisionTreeFactor::shared_ptr actual = f1.sum(1);
CHECK(assert_equal(expected, *actual, 1e-5));
// f1.print("f1:");
// actual->print("actual: ");
// actual->printCache("actual cache: ");
DecisionTreeFactor expected2(v1, "5 6");
DecisionTreeFactor::shared_ptr actual2 = f1.max(1);
CHECK(assert_equal(expected2, *actual2));
DecisionTreeFactor f2(v1 & v0, "1 2 3 4 5 6");
DecisionTreeFactor::shared_ptr actual22 = f2.sum(1);
// f2.print("f2: ");
// actual22->print("actual22: ");
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,128 @@
/*
* testDiscreteBayesNet.cpp
*
* @date Feb 27, 2011
* @author Frank Dellaert
*/
#include <gtsam/discrete/DiscreteBayesNet.h>
#include <gtsam/discrete/DiscreteSequentialSolver.h>
#include <gtsam/base/Testable.h>
#include <gtsam/base/debug.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
using namespace boost::assign;
#include <boost/version.hpp> // for checking whether we are using boost 1.40
#if BOOST_VERSION >= 104200
#define BOOST_HAVE_PARSER
#endif
#include <iostream>
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
TEST(DiscreteBayesNet, Asia)
{
DiscreteBayesNet asia;
// DiscreteKey A("Asia"), S("Smoking"), T("Tuberculosis"), L("LungCancer"), B(
// "Bronchitis"), E("Either"), X("XRay"), D("Dyspnoea");
DiscreteKey A(0,2), S(4,2), T(3,2), L(6,2), B(7,2), E(5,2), X(2,2), D(1,2);
// TODO: make a version that doesn't use the parser
#ifdef BOOST_HAVE_PARSER
add_front(asia, A % "99/1");
add_front(asia, S % "50/50");
add_front(asia, T | A = "99/1 95/5");
add_front(asia, L | S = "99/1 90/10");
add_front(asia, B | S = "70/30 40/60");
add_front(asia, (E | T, L) = "F T T T");
add_front(asia, X | E = "95/5 2/98");
// next lines are same as add_front(asia, (D | E, B) = "9/1 2/8 3/7 1/9");
DiscreteConditional::shared_ptr actual =
boost::make_shared<DiscreteConditional>((D | E, B) = "9/1 2/8 3/7 1/9");
asia.push_front(actual);
// GTSAM_PRINT(asia);
// Convert to factor graph
DiscreteFactorGraph fg(asia);
// GTSAM_PRINT(fg);
LONGS_EQUAL(3,fg.front()->size());
Potentials::ADT expected(B & D & E, "0.9 0.3 0.1 0.7 0.2 0.1 0.8 0.9");
CHECK(assert_equal(expected,(Potentials::ADT)*actual));
// Create solver and eliminate
DiscreteSequentialSolver solver(fg);
DiscreteBayesNet::shared_ptr chordal = solver.eliminate();
// GTSAM_PRINT(*chordal);
DiscreteConditional expected2(B % "11/9");
CHECK(assert_equal(expected2,*chordal->back()));
// solve
DiscreteFactor::sharedValues actualMPE = optimize(*chordal);
DiscreteFactor::Values expectedMPE;
insert(expectedMPE)(A.first, 0)(D.first, 0)(X.first, 0)(T.first, 0)(S.first,
0)(E.first, 0)(L.first, 0)(B.first, 0);
EXPECT(assert_equal(expectedMPE, *actualMPE));
// add evidence, we were in Asia and we have Dispnoea
fg.add(A, "0 1");
fg.add(D, "0 1");
// fg.product().dot("fg");
// solve again, now with evidence
DiscreteSequentialSolver solver2(fg);
DiscreteBayesNet::shared_ptr chordal2 = solver2.eliminate();
// GTSAM_PRINT(*chordal2);
DiscreteFactor::sharedValues actualMPE2 = optimize(*chordal2);
DiscreteFactor::Values expectedMPE2;
insert(expectedMPE2)(A.first, 1)(D.first, 1)(X.first, 0)(T.first, 0)(S.first,
1)(E.first, 0)(L.first, 0)(B.first, 1);
EXPECT(assert_equal(expectedMPE2, *actualMPE2));
// now sample from it
DiscreteFactor::Values expectedSample;
SETDEBUG("DiscreteConditional::sample", false);
insert(expectedSample)(A.first, 1)(D.first, 1)(X.first, 0)(T.first, 0)(
S.first, 1)(E.first, 0)(L.first, 0)(B.first, 1);
DiscreteFactor::sharedValues actualSample = sample(*chordal2);
EXPECT(assert_equal(expectedSample, *actualSample));
#endif
}
/* ************************************************************************* */
TEST_UNSAFE(DiscreteBayesNet, Sugar)
{
DiscreteKey T(0,2), L(1,2), E(2,2), D(3,2), C(8,3), S(7,2);
DiscreteBayesNet bn;
#ifdef BOOST_HAVE_PARSER
// test some mistakes
// add(bn, D);
// add(bn, D | E);
// add(bn, D | E = "blah");
// try logic
add(bn, (E | T, L) = "OR");
add(bn, (E | T, L) = "AND");
// // try multivalued
add(bn, C % "1/1/2");
add(bn, C | S = "1/1/2 5/2/3");
#endif
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,86 @@
/*
* @file testDecisionTreeFactor.cpp
* @brief unit tests for DiscreteConditional
* @author Duy-Nguyen Ta
* @date Feb 14, 2011
*/
#include <boost/make_shared.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/DiscreteConditional.h>
#include <boost/version.hpp> // for checking whether we are using boost 1.40
#if BOOST_VERSION >= 104200
#define BOOST_HAVE_PARSER
#endif
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
TEST( DiscreteConditionalTest, constructors)
{
DiscreteKey X(0, 2), Y(2, 3), Z(1, 2); // watch ordering !
#ifdef BOOST_HAVE_PARSER
DiscreteConditional::shared_ptr expected1 = //
boost::make_shared<DiscreteConditional>(X | Y = "1/1 2/3 1/4");
#else
Signature::Table table;
Signature::Row r1, r2, r3;
r1 += 1.0, 1.0; r2 += 2.0, 3.0; r3 += 1.0, 4.0;
table += r1, r2, r3;
DiscreteConditional::shared_ptr expected1 = //
boost::make_shared<DiscreteConditional>(X | Y = table);
#endif
EXPECT(expected1);
DecisionTreeFactor f1(X & Y, "0.5 0.4 0.2 0.5 0.6 0.8");
DiscreteConditional actual1(1, f1);
EXPECT(assert_equal(*expected1, actual1, 1e-9));
DecisionTreeFactor f2(X & Y & Z,
"0.2 0.5 0.3 0.6 0.4 0.7 0.25 0.55 0.35 0.65 0.45 0.75");
DiscreteConditional actual2(1, f2);
DecisionTreeFactor::shared_ptr actual2factor = actual2.toFactor();
// EXPECT(assert_equal(f2, *actual2factor, 1e-9));
}
/* ************************************************************************* */
TEST( DiscreteConditionalTest, constructors2)
{
#ifdef BOOST_HAVE_PARSER
// Declare keys and ordering
DiscreteKey C(0,2), B(1,2);
DecisionTreeFactor expected(C & B, "0.8 0.75 0.2 0.25");
Signature signature((C | B) = "4/1 3/1");
DiscreteConditional actual(signature);
DecisionTreeFactor::shared_ptr actualFactor = actual.toFactor();
EXPECT(assert_equal(expected, *actualFactor));
#endif
}
/* ************************************************************************* */
TEST( DiscreteConditionalTest, constructors3)
{
#ifdef BOOST_HAVE_PARSER
// Declare keys and ordering
DiscreteKey C(0,2), B(1,2), A(2,2);
DecisionTreeFactor expected(C & B & A, "0.8 0.5 0.5 0.2 0.2 0.5 0.5 0.8");
Signature signature((C | B, A) = "4/1 1/1 1/1 1/4");
DiscreteConditional actual(signature);
DecisionTreeFactor::shared_ptr actualFactor = actual.toFactor();
EXPECT(assert_equal(expected, *actualFactor));
#endif
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,23 @@
/*
* testDiscreteFactor.cpp
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/DiscreteFactor.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
using namespace boost::assign;
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,359 @@
/*
* testDiscreteFactorGraph.cpp
*
* @date Feb 14, 2011
* @author Duy-Nguyen Ta
*/
#include <gtsam/discrete/DiscreteFactor.h>
#include <gtsam/discrete/DiscreteFactorGraph.h>
#include <gtsam/discrete/DiscreteSequentialSolver.h>
#include <gtsam/inference/GenericMultifrontalSolver.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/map.hpp>
using namespace boost::assign;
#include <boost/version.hpp> // for checking whether we are using boost 1.40
#if BOOST_VERSION >= 104200
#define BOOST_HAVE_PARSER
#endif
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
TEST_UNSAFE( DiscreteFactorGraph, debugScheduler) {
DiscreteKey PC(0,4), ME(1, 4), AI(2, 4), A(3, 3);
DiscreteFactorGraph graph;
graph.add(AI, "1 0 0 1");
graph.add(AI, "1 1 1 0");
graph.add(A & AI, "1 1 1 0 1 1 1 1 0 1 1 1");
graph.add(ME, "0 1 0 0");
graph.add(ME, "1 1 1 0");
graph.add(A & ME, "1 1 1 0 1 1 1 1 0 1 1 1");
graph.add(PC, "1 0 1 0");
graph.add(PC, "1 1 1 0");
graph.add(A & PC, "1 1 1 0 1 1 1 1 0 1 1 1");
graph.add(ME & AI, "0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0");
graph.add(PC & ME, "0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0");
graph.add(PC & AI, "0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0");
// graph.print("Graph: ");
DecisionTreeFactor product = graph.product();
DecisionTreeFactor::shared_ptr sum = product.sum(1);
// sum->print("Debug SUM: ");
DiscreteConditional::shared_ptr cond(new DiscreteConditional(product, *sum));
// cond->print("marginal:");
// pair<DiscreteBayesNet::shared_ptr, DiscreteFactor::shared_ptr> result = EliminateDiscrete(graph, 1);
// result.first->print("BayesNet: ");
// result.second->print("New factor: ");
//
DiscreteSequentialSolver solver(graph);
// solver.print("solver:");
EliminationTree<DiscreteFactor> eliminationTree = solver.eliminationTree();
// eliminationTree.print("Elimination tree: ");
eliminationTree.eliminate(EliminateDiscrete);
// solver.optimize();
// DiscreteBayesNet::shared_ptr bayesNet = solver.eliminate();
}
/* ************************************************************************* */
/// Test the () operator of DiscreteFactorGraph
TEST_UNSAFE( DiscreteFactorGraph, DiscreteFactorGraphEvaluationTest) {
// Three keys P1 and P2
DiscreteKey P1(0,2), P2(1,2), P3(2,3);
// Create the DiscreteFactorGraph
DiscreteFactorGraph graph;
graph.add(P1, "0.9 0.3");
graph.add(P2, "0.9 0.6");
graph.add(P1 & P2, "4 1 10 4");
// Instantiate Values
DiscreteFactor::Values values;
values[0] = 1;
values[1] = 1;
// Check if graph evaluation works ( 0.3*0.6*4 )
EXPECT_DOUBLES_EQUAL( .72, graph(values), 1e-9);
// Creating a new test with third node and adding unary and ternary factors on it
graph.add(P3, "0.9 0.2 0.5");
graph.add(P1 & P2 & P3, "1 2 3 4 5 6 7 8 9 10 11 12");
// Below values lead to selecting the 8th index in the ternary factor table
values[0] = 1;
values[1] = 0;
values[2] = 1;
// Check if graph evaluation works (0.3*0.9*1*0.2*8)
EXPECT_DOUBLES_EQUAL( 4.32, graph(values), 1e-9);
// Below values lead to selecting the 3rd index in the ternary factor table
values[0] = 0;
values[1] = 1;
values[2] = 0;
// Check if graph evaluation works (0.9*0.6*1*0.9*4)
EXPECT_DOUBLES_EQUAL( 1.944, graph(values), 1e-9);
// Check if graph product works
DecisionTreeFactor product = graph.product();
EXPECT_DOUBLES_EQUAL( 1.944, product(values), 1e-9);
}
/* ************************************************************************* */
TEST( DiscreteFactorGraph, test)
{
// Declare keys and ordering
DiscreteKey C(0,2), B(1,2), A(2,2);
// A simple factor graph (A)-fAC-(C)-fBC-(B)
// with smoothness priors
DiscreteFactorGraph graph;
graph.add(A & C, "3 1 1 3");
graph.add(C & B, "3 1 1 3");
// Test EliminateDiscrete
// FIXME: apparently Eliminate returns a conditional rather than a net
DiscreteConditional::shared_ptr conditional;
DecisionTreeFactor::shared_ptr newFactor;
boost::tie(conditional, newFactor) =//
EliminateDiscrete(graph, 1);
#ifdef BOOST_HAVE_PARSER
// Check Bayes net
CHECK(conditional);
DiscreteBayesNet expected;
Signature signature((C | B, A) = "9/1 1/1 1/1 1/9");
// cout << signature << endl;
DiscreteConditional expectedConditional(signature);
EXPECT(assert_equal(expectedConditional, *conditional));
add(expected, signature);
// Check Factor
CHECK(newFactor);
DecisionTreeFactor expectedFactor(B & A, "10 6 6 10");
EXPECT(assert_equal(expectedFactor, *newFactor));
// Create solver
DiscreteSequentialSolver solver(graph);
// add conditionals to complete expected Bayes net
add(expected, B | A = "5/3 3/5");
add(expected, A % "1/1");
// GTSAM_PRINT(expected);
// Test elimination tree
const EliminationTree<DiscreteFactor>& etree = solver.eliminationTree();
DiscreteBayesNet::shared_ptr actual = etree.eliminate(&EliminateDiscrete);
EXPECT(assert_equal(expected, *actual));
// Test solver
DiscreteBayesNet::shared_ptr actual2 = solver.eliminate();
EXPECT(assert_equal(expected, *actual2));
// Test optimization
DiscreteFactor::Values expectedValues;
insert(expectedValues)(0, 0)(1, 0)(2, 0);
DiscreteFactor::sharedValues actualValues = solver.optimize();
EXPECT(assert_equal(expectedValues, *actualValues));
#endif
}
/* ************************************************************************* */
TEST( DiscreteFactorGraph, testMPE)
{
// Declare a bunch of keys
DiscreteKey C(0,2), A(1,2), B(2,2);
// Create Factor graph
DiscreteFactorGraph graph;
graph.add(C & A, "0.2 0.8 0.3 0.7");
graph.add(C & B, "0.1 0.9 0.4 0.6");
// graph.product().print();
// DiscreteSequentialSolver(graph).eliminate()->print();
DiscreteFactor::sharedValues actualMPE =
DiscreteSequentialSolver(graph).optimize();
DiscreteFactor::Values expectedMPE;
insert(expectedMPE)(0, 0)(1, 1)(2, 1);
EXPECT(assert_equal(expectedMPE, *actualMPE));
}
/* ************************************************************************* */
TEST( DiscreteFactorGraph, testMPE_Darwiche09book_p244)
{
// The factor graph in Darwiche09book, page 244
DiscreteKey A(4,2), C(3,2), S(2,2), T1(0,2), T2(1,2);
// Create Factor graph
DiscreteFactorGraph graph;
graph.add(S, "0.55 0.45");
graph.add(S & C, "0.05 0.95 0.01 0.99");
graph.add(C & T1, "0.80 0.20 0.20 0.80");
graph.add(S & C & T2, "0.80 0.20 0.20 0.80 0.95 0.05 0.05 0.95");
graph.add(T1 & T2 & A, "1 0 0 1 0 1 1 0");
graph.add(A, "1 0");// evidence, A = yes (first choice in Darwiche)
//graph.product().print("Darwiche-product");
// graph.product().potentials().dot("Darwiche-product");
// DiscreteSequentialSolver(graph).eliminate()->print();
DiscreteFactor::Values expectedMPE;
insert(expectedMPE)(4, 0)(2, 0)(3, 1)(0, 1)(1, 1);
// Use the solver machinery.
DiscreteBayesNet::shared_ptr chordal =
DiscreteSequentialSolver(graph).eliminate();
DiscreteFactor::sharedValues actualMPE = optimize(*chordal);
EXPECT(assert_equal(expectedMPE, *actualMPE));
// DiscreteConditional::shared_ptr root = chordal->back();
// EXPECT_DOUBLES_EQUAL(0.4, (*root)(*actualMPE), 1e-9);
#ifdef OLD
// Let us create the Bayes tree here, just for fun, because we don't use it now
typedef JunctionTree<DiscreteFactorGraph> JT;
GenericMultifrontalSolver<DiscreteFactor, JT> solver(graph);
JT::BayesTree::shared_ptr bayesTree = solver.eliminate(&EliminateDiscrete);
bayesTree->print("Bayes Tree");
tictoc_print();
}
// Create the elimination tree manually
VariableIndex structure(graph);
typedef EliminationTree<DiscreteFactor> ETree;
ETree::shared_ptr eTree = ETree::Create(graph, structure);
//eTree->print(">>>>>>>>>>> Elimination Tree <<<<<<<<<<<<<<<<<");
// eliminate normally and check solution
DiscreteBayesNet::shared_ptr bayesNet = eTree->eliminate(&EliminateDiscrete);
// bayesNet->print(">>>>>>>>>>>>>> Bayes Net <<<<<<<<<<<<<<<<<<");
DiscreteFactor::sharedValues actualMPE = optimize(*bayesNet);
EXPECT(assert_equal(expectedMPE, *actualMPE));
// Approximate and check solution
// DiscreteBayesNet::shared_ptr approximateNet = eTree->approximate();
// approximateNet->print(">>>>>>>>>>>>>> Approximate Net <<<<<<<<<<<<<<<<<<");
// EXPECT(assert_equal(expectedMPE, *actualMPE));
#endif
}
#ifdef OLD
/* ************************************************************************* */
/**
* Key type for discrete conditionals
* Includes name and cardinality
*/
class Key2 {
private:
std::string wff_;
size_t cardinality_;
public:
/** Constructor, defaults to binary */
Key2(const std::string& name, size_t cardinality = 2) :
wff_(name), cardinality_(cardinality) {
}
const std::string& name() const {
return wff_;
}
/** provide streaming */
friend std::ostream& operator <<(std::ostream &os, const Key2 &key);
};
struct Factor2 {
std::string wff_;
Factor2() :
wff_("@") {
}
Factor2(const std::string& s) :
wff_(s) {
}
Factor2(const Key2& key) :
wff_(key.name()) {
}
friend std::ostream& operator <<(std::ostream &os, const Factor2 &f);
friend Factor2 operator -(const Key2& key);
};
std::ostream& operator <<(std::ostream &os, const Factor2 &f) {
os << f.wff_;
return os;
}
/** negation */
Factor2 operator -(const Key2& key) {
return Factor2("-" + key.name());
}
/** OR */
Factor2 operator ||(const Factor2 &factor1, const Factor2 &factor2) {
return Factor2(std::string("(") + factor1.wff_ + " || " + factor2.wff_ + ")");
}
/** AND */
Factor2 operator &&(const Factor2 &factor1, const Factor2 &factor2) {
return Factor2(std::string("(") + factor1.wff_ + " && " + factor2.wff_ + ")");
}
/** implies */
Factor2 operator >>(const Factor2 &factor1, const Factor2 &factor2) {
return Factor2(std::string("(") + factor1.wff_ + " >> " + factor2.wff_ + ")");
}
struct Graph2: public std::list<Factor2> {
/** Add a factor graph*/
// void operator +=(const Graph2& graph) {
// BOOST_FOREACH(const Factor2& f, graph)
// push_back(f);
// }
friend std::ostream& operator <<(std::ostream &os, const Graph2& graph);
};
/** Add a factor */
//Graph2 operator +=(Graph2& graph, const Factor2& factor) {
// graph.push_back(factor);
// return graph;
//}
std::ostream& operator <<(std::ostream &os, const Graph2& graph) {
BOOST_FOREACH(const Factor2& f, graph)
os << f << endl;
return os;
}
/* ************************************************************************* */
TEST(DiscreteFactorGraph, Sugar)
{
Key2 M("Mythical"), I("Immortal"), A("Mammal"), H("Horned"), G("Magical");
// Test this desired construction
Graph2 unicorns;
unicorns += M >> -A;
unicorns += (-M) >> (-I && A);
unicorns += (I || A) >> H;
unicorns += H >> G;
// should be done by adapting boost::assign:
// unicorns += (-M) >> (-I && A), (I || A) >> H , H >> G;
cout << unicorns;
}
#endif
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,153 @@
/*
* @file testPotentialTable.cpp
* @brief Develop recursive potential operations
* @author Frank Dellaert
* @date Mar 6, 2011
*/
#include <boost/foreach.hpp>
#include <boost/assign/std/vector.hpp> // for operator +=
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <gtsam/discrete/PotentialTable.h>
using namespace std;
using namespace gtsam;
/* ******************************************************************************** */
TEST( PotentialTable, Iterator)
{
PotentialTable::Cardinalities cs;
cs += 2, 3;
PotentialTable::Iterator it(cs);
LONGS_EQUAL(0,it[0]);
LONGS_EQUAL(0,it[1]);
++it;
LONGS_EQUAL(0,it[0]);
LONGS_EQUAL(1,it[1]);
++it;
LONGS_EQUAL(0,it[0]);
LONGS_EQUAL(2,it[1]);
++it;
LONGS_EQUAL(1,it[0]);
LONGS_EQUAL(0,it[1]);
++it;
LONGS_EQUAL(1,it[0]);
LONGS_EQUAL(1,it[1]);
++it;
LONGS_EQUAL(1,it[0]);
LONGS_EQUAL(2,it[1]);
++it;
LONGS_EQUAL(0,it[0]);
LONGS_EQUAL(0,it[1]);
}
/* ******************************************************************************** */
#include <boost/unordered_map.hpp>
TEST( PotentialTable, unordered_map)
{
boost::unordered_map<bool, int> x;
x[false] = 7;
}
/* ******************************************************************************** */
struct Factor {
vector<double> table_;
vector<Index> keys_;
bool operator==(const Factor& f) const {
return table_ == f.table_ && keys_ == f.keys_;
}
};
Factor operator*(const double& s, const Factor& f) {
Factor r = f;
BOOST_FOREACH(double& ri, r.table_)
ri *= s;
return r;
}
Factor operator*(const Factor& f, const double& s) {
Factor r = f;
BOOST_FOREACH(double& ri, r.table_)
ri *= s;
return r;
}
Factor operator*(const Factor& f1, const Factor& f2) {
Factor r;
// base case 1, both tables start with same key
if (f1.keys_.front() == f2.keys_.front()) {
}
return r;
}
/* ******************************************************************************** */
// f(5)*f(5) = f0*f0 @ f1*f1
TEST( PotentialTable, baseCase1a)
{
Factor f1, f2, expected;
f1.table_ += 00, 01;
f2.table_ += 20, 21;
f1.keys_ += 5;
f2.keys_ += 5;
expected.table_ += 00 * 20, 01 * 21;
expected.keys_ += 5;
CHECK(f1*f2==expected)
}
/* ******************************************************************************** */
// f(0,1)*f(0) = f0(1)*f0 @ f1(1)*f1
TEST( PotentialTable, baseCase1b)
{
Factor f1, f2, expected;
f1.table_ += 00, 01, 10, 11;
f2.table_ += 20, 21;
f1.keys_ += 0, 1;
f2.keys_ += 0;
expected.table_ += 00 * 20, 00 * 21, 01 * 20, 01 * 21, 10 * 20, 10 * 21, 11
* 20, 11 * 21;
expected.keys_ += 0, 1, 2;
CHECK(f1*f2==expected)
}
/* ******************************************************************************** */
// f0(1)*f(2) = f00*f(2) @ f01*f(2)
TEST( PotentialTable, baseCase2)
{
Factor f1, f2, expected;
f1.table_ += 00, 01;
f2.table_ += 20, 21;
f1.keys_ += 1;
f2.keys_ += 2;
expected.table_ += 00 * 20, 00 * 21, 01 * 20, 01 * 21;
expected.keys_ += 1, 2;
CHECK(f1*f2==expected)
}
/* ******************************************************************************** */
// f(0,1)*f(2) = f0(1)*f(2) @ f1(1)*f(2)
// f0(1)*f(2) = f00*f(2) @ f01*f(2)
TEST( PotentialTable, multiplication)
{
Factor f1, f2, expected;
f1.table_ += 00, 01, 10, 11;
f2.table_ += 20, 21;
f1.keys_ += 0, 1;
f2.keys_ += 2;
expected.table_ += 00 * 20, 00 * 21, 01 * 20, 01 * 21, 10 * 20, 10 * 21, 11
* 20, 11 * 21;
expected.keys_ += 0, 1, 2;
CHECK(f1*f2==expected)
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,183 @@
/*
* testScheduler.cpp
* @date March 25, 2011
* @author Frank Dellaert
*/
//#define ENABLE_TIMING
#include <gtsam/discrete/Scheduler.h>
#include <gtsam/base/Testable.h>
#include <gtsam/base/timing.h>
#include <CppUnitLite/TestHarness.h>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
using namespace boost::assign;
using namespace std;
using namespace gtsam;
/* ************************************************************************* */
// Create the expected graph of constraints
DiscreteFactorGraph createExpected() {
// Start building
size_t nrFaculty = 4, nrTimeSlots = 3;
// variables assigning a time to a student:
// Akansel and Jake
DiscreteKey A(6, nrTimeSlots), J(7, nrTimeSlots);
// variables assigning a faculty member to a student area
// Akansel:AI,ME,PC and Jake:HR,CT,AI
DiscreteKey A1(0, nrFaculty), J1(3, nrFaculty);
DiscreteKey A2(1, nrFaculty), J2(4, nrFaculty);
DiscreteKey A3(2, nrFaculty), J3(5, nrFaculty);
CSP expected;
// Area constraints
string faculty_in_A = "1 0 0 1";
string faculty_in_C = "0 0 1 0";
string faculty_in_H = "0 0 0 1";
string faculty_in_M = "0 1 0 0";
string faculty_in_P = "1 0 1 0";
string available = "1 1 1 0 1 1 1 1 0 1 1 1";
// Akansel
expected.add(A1, faculty_in_A); // Area 1
expected.add(A1, "1 1 1 0"); // Advisor
expected.add(A & A1, available);
expected.add(A2, faculty_in_M); // Area 2
expected.add(A2, "1 1 1 0"); // Advisor
expected.add(A & A2, available);
expected.add(A3, faculty_in_P); // Area 3
expected.add(A3, "1 1 1 0"); // Advisor
expected.add(A & A3, available);
// Mutual exclusion for faculty
expected.addAllDiff(A1 & A2 & A3);
// Jake
expected.add(J1, faculty_in_H); // Area 1
expected.add(J1, "1 0 1 1"); // Advisor
expected.add(J & J1, available);
expected.add(J2, faculty_in_C); // Area 2
expected.add(J2, "1 0 1 1"); // Advisor
expected.add(J & J2, available);
expected.add(J3, faculty_in_A); // Area 3
expected.add(J3, "1 0 1 1"); // Advisor
expected.add(J & J3, available);
// Mutual exclusion for faculty
expected.addAllDiff(J1 & J2 & J3);
// Mutual exclusion for students
expected.addAllDiff(A & J);
return expected;
}
/* ************************************************************************* */
TEST( schedulingExample, test)
{
Scheduler s(2);
// add faculty
s.addFaculty("Frank");
s.addFaculty("Harvey");
s.addFaculty("Magnus");
s.addFaculty("Andrea");
// add time slots
s.addSlot("Mon");
s.addSlot("Wed");
s.addSlot("Fri");
// add areas
s.addArea("Frank", "AI");
s.addArea("Frank", "PC");
s.addArea("Harvey", "ME");
s.addArea("Magnus", "CT");
s.addArea("Magnus", "PC");
s.addArea("Andrea", "AI");
s.addArea("Andrea", "HR");
// add availability, nrTimeSlots * nrFaculty
string available = "1 1 1 0 1 1 1 1 0 1 1 1";
s.setAvailability(available);
// add students
s.addStudent("Akansel", "AI", "ME", "PC", "Andrea");
s.addStudent("Jake", "HR", "CT", "AI", "Harvey");
// BUILD THE GRAPH !
s.buildGraph();
// s.print();
// Check graph
DiscreteFactorGraph expected = createExpected();
EXPECT(assert_equal(expected, (DiscreteFactorGraph)s));
// Do brute force product and output that to file
DecisionTreeFactor product = s.product();
//product.dot("scheduling", false);
// Do exact inference
tic(1, "small");
DiscreteFactor::sharedValues MPE = s.optimalAssignment();
toc(1, "small");
// print MPE, commented out as unit tests don't print
// s.printAssignment(MPE);
// Commented out as does not work yet
// s.runArcConsistency(8,10,true);
// find the assignment of students to slots with most possible committees
// Commented out as not implemented yet
// sharedValues bestSchedule = s.bestSchedule();
// GTSAM_PRINT(*bestSchedule);
// find the corresponding most desirable committee assignment
// Commented out as not implemented yet
// sharedValues bestAssignment = s.bestAssignment(bestSchedule);
// GTSAM_PRINT(*bestAssignment);
}
/* ************************************************************************* */
TEST( schedulingExample, smallFromFile)
{
string path("../../../gtsam/discrete/examples/");
Scheduler s(2, path + "small.csv");
// add areas
s.addArea("Frank", "AI");
s.addArea("Frank", "PC");
s.addArea("Harvey", "ME");
s.addArea("Magnus", "CT");
s.addArea("Magnus", "PC");
s.addArea("Andrea", "AI");
s.addArea("Andrea", "HR");
// add students
s.addStudent("Akansel", "AI", "ME", "PC", "Andrea");
s.addStudent("Jake", "HR", "CT", "AI", "Harvey");
// s.print();
// BUILD THE GRAPH !
s.buildGraph();
// Check graph
DiscreteFactorGraph expected = createExpected();
EXPECT(assert_equal(expected, (DiscreteFactorGraph)s));
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,61 @@
/**
* @file testSignature
* @brief Tests focusing on the details of Signatures to evaluate boost compliance
* @author Alex Cunningham
* @date Sept 19th 2011
*/
#include <boost/assign/std/vector.hpp>
#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/Signature.h>
using namespace std;
using namespace gtsam;
using namespace boost::assign;
DiscreteKey X(0,2), Y(1,3), Z(2,2);
#ifdef BOOST_HAVE_PARSER
/* ************************************************************************* */
TEST(testSignature, simple_conditional) {
Signature sig(X | Y = "1/1 2/3 1/4");
DiscreteKey actKey = sig.key();
LONGS_EQUAL(X.first, actKey.first);
DiscreteKeys actKeys = sig.discreteKeysParentsFirst();
LONGS_EQUAL(2, actKeys.size());
LONGS_EQUAL(Y.first, actKeys.front().first);
LONGS_EQUAL(X.first, actKeys.back().first);
vector<double> actCpt = sig.cpt();
EXPECT_LONGS_EQUAL(6, actCpt.size());
}
#endif
/* ************************************************************************* */
TEST(testSignature, simple_conditional_nonparser) {
Signature::Table table;
Signature::Row row1, row2, row3;
row1 += 1.0, 1.0;
row2 += 2.0, 3.0;
row3 += 1.0, 4.0;
table += row1, row2, row3;
Signature sig(X | Y = table);
DiscreteKey actKey = sig.key();
EXPECT_LONGS_EQUAL(X.first, actKey.first);
DiscreteKeys actKeys = sig.discreteKeysParentsFirst();
LONGS_EQUAL(2, actKeys.size());
LONGS_EQUAL(Y.first, actKeys.front().first);
LONGS_EQUAL(X.first, actKeys.back().first);
vector<double> actCpt = sig.cpt();
EXPECT_LONGS_EQUAL(6, actCpt.size());
}
/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */

View File

@ -0,0 +1,215 @@
/*
* testSudoku.cpp
* @brief develop code for Sudoku CSP solver
* @date Jan 29, 2012
* @author Frank Dellaert
*/
#include <gtsam/discrete/CSP.h>
#include <CppUnitLite/TestHarness.h>
#include <iostream>
#include <sstream>
#include <stdarg.h>
using namespace std;
using namespace gtsam;
class Sudoku: public CSP {
/// sudoku size
size_t n_;
/// discrete keys
typedef std::pair<size_t, size_t> IJ;
std::map<IJ, DiscreteKey> dkeys_;
public:
/// return DiscreteKey for cell(i,j)
const DiscreteKey& dkey(size_t i, size_t j) const {
return dkeys_.at(IJ(i, j));
}
/// return Index for cell(i,j)
Index key(size_t i, size_t j) const {
return dkey(i, j).first;
}
/// Constructor
Sudoku(size_t n, ...) :
n_(n) {
// Create variables, ordering, and unary constraints
va_list ap;
va_start(ap, n);
Index k=0;
for (size_t i = 0; i < n; ++i) {
for (size_t j = 0; j < n; ++j, ++k) {
// create the key
IJ ij(i, j);
dkeys_[ij] = DiscreteKey(k, n);
// get the unary constraint, if any
int value = va_arg(ap, int);
// cout << value << " ";
if (value != 0) addSingleValue(dkeys_[ij], value - 1);
}
//cout << endl;
}
va_end(ap);
// add row constraints
for (size_t i = 0; i < n; i++) {
DiscreteKeys dkeys;
for (size_t j = 0; j < n; j++)
dkeys += dkey(i, j);
addAllDiff(dkeys);
}
// add col constraints
for (size_t j = 0; j < n; j++) {
DiscreteKeys dkeys;
for (size_t i = 0; i < n; i++)
dkeys += dkey(i, j);
addAllDiff(dkeys);
}
// add box constraints
size_t N = sqrt(n), i0 = 0;
for (size_t I = 0; I < N; I++) {
size_t j0 = 0;
for (size_t J = 0; J < N; J++) {
// Box I,J
DiscreteKeys dkeys;
for (size_t i = i0; i < i0 + N; i++)
for (size_t j = j0; j < j0 + N; j++)
dkeys += dkey(i, j);
addAllDiff(dkeys);
j0 += N;
}
i0 += N;
}
}
/// Print readable form of assignment
void printAssignment(DiscreteFactor::sharedValues assignment) const {
for (size_t i = 0; i < n_; i++) {
for (size_t j = 0; j < n_; j++) {
Index k = key(i, j);
cout << 1 + assignment->at(k) << " ";
}
cout << endl;
}
}
/// solve and print solution
void printSolution() {
DiscreteFactor::sharedValues MPE = optimalAssignment();
printAssignment(MPE);
}
};
/* ************************************************************************* */
TEST_UNSAFE( Sudoku, small)
{
Sudoku csp(4,
1,0, 0,4,
0,0, 0,0,
4,0, 2,0,
0,1, 0,0);
// Do BP
csp.runArcConsistency(4);
// optimize and check
CSP::sharedValues solution = csp.optimalAssignment();
CSP::Values expected;
insert(expected)
(csp.key(0,0), 0)(csp.key(0,1), 1)(csp.key(0,2), 2)(csp.key(0,3), 3)
(csp.key(1,0), 2)(csp.key(1,1), 3)(csp.key(1,2), 0)(csp.key(1,3), 1)
(csp.key(2,0), 3)(csp.key(2,1), 2)(csp.key(2,2), 1)(csp.key(2,3), 0)
(csp.key(3,0), 1)(csp.key(3,1), 0)(csp.key(3,2), 3)(csp.key(3,3), 2);
EXPECT(assert_equal(expected,*solution));
//csp.printAssignment(solution);
}
/* ************************************************************************* */
TEST_UNSAFE( Sudoku, easy)
{
Sudoku sudoku(9,
0,0,5, 0,9,0, 0,0,1,
0,0,0, 0,0,2, 0,7,3,
7,6,0, 0,0,8, 2,0,0,
0,1,2, 0,0,9, 0,0,4,
0,0,0, 2,0,3, 0,0,0,
3,0,0, 1,0,0, 9,6,0,
0,0,1, 9,0,0, 0,5,8,
9,7,0, 5,0,0, 0,0,0,
5,0,0, 0,3,0, 7,0,0);
// Do BP
sudoku.runArcConsistency(4);
// sudoku.printSolution(); // don't do it
}
/* ************************************************************************* */
TEST_UNSAFE( Sudoku, extreme)
{
Sudoku sudoku(9,
0,0,9, 7,4,8, 0,0,0,
7,0,0, 0,0,0, 0,0,0,
0,2,0, 1,0,9, 0,0,0,
0,0,7, 0,0,0, 2,4,0,
0,6,4, 0,1,0, 5,9,0,
0,9,8, 0,0,0, 3,0,0,
0,0,0, 8,0,3, 0,2,0,
0,0,0, 0,0,0, 0,0,6,
0,0,0, 2,7,5, 9,0,0);
// Do BP
sudoku.runArcConsistency(9,10,false);
#ifdef METIS
VariableIndex index(sudoku);
index.print("index");
ofstream os("/Users/dellaert/src/hmetis-1.5-osx-i686/extreme-dual.txt");
index.outputMetisFormat(os);
#endif
//sudoku.printSolution(); // don't do it
}
/* ************************************************************************* */
TEST_UNSAFE( Sudoku, AJC_3star_Feb8_2012)
{
Sudoku sudoku(9,
9,5,0, 0,0,6, 0,0,0,
0,8,4, 0,7,0, 0,0,0,
6,2,0, 5,0,0, 4,0,0,
0,0,0, 2,9,0, 6,0,0,
0,9,0, 0,0,0, 0,2,0,
0,0,2, 0,6,3, 0,0,0,
0,0,9, 0,0,7, 0,6,8,
0,0,0, 0,3,0, 2,9,0,
0,0,0, 1,0,0, 0,3,7);
// Do BP
sudoku.runArcConsistency(9,10,true);
//sudoku.printSolution(); // don't do it
}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,54 @@
/*
* @file testTypedDiscreteFactor.cpp
* @brief Typed f1s use discrete keys
* @author Duy-Nguyen Ta
* @date Mar 5, 2011
*/
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/TypedDiscreteFactor.h>
using namespace std;
using namespace gtsam;
/* ******************************************************************************** */
// initialize some common test values
DiscreteKey v0("v0"), v1("v1"), v2("v2", 3);
TypedDiscreteFactor::Values values;
void init() {
values[v0] = 0;
values[v1] = 0;
values[v2] = 1;
}
/* ******************************************************************************** */
TEST( TypedDiscreteFactor, constructors)
{
TypedDiscreteFactor f1(v1 & v2, "0.210 0.333 0.457 0.811 0.000 0.189");
EXPECT_LONGS_EQUAL(2, f1.size());
// f1.print();
double expectedP001 = 0.333;
EXPECT_DOUBLES_EQUAL(expectedP001, f1(values), 1e-9);
vector<double> ys;
ys += 0.210, 0.333, 0.457, 0.811, 0.000, 0.189;
TypedDiscreteFactor f2(v1 & v2, ys);
EXPECT(assert_equal(f1, f2, 1e-9));
EXPECT_LONGS_EQUAL(2, f1.size());
EXPECT_DOUBLES_EQUAL(expectedP001, f2(values), 1e-9);
}
/* ************************************************************************* */
int main() {
init();
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,200 @@
/*
* testTypedDiscreteFactorGraph.cpp
* @brief test readable factor graphs
* @author Duy-Nguyen Ta
* @author Frank Dellaert
* @date Feb 14, 2011
*/
//#include <map>
//#include <fstream>
#include <boost/foreach.hpp>
#include <CppUnitLite/TestHarness.h>
//#include <gtsam/inference/JunctionTree.h>
//#include <gtsam/inference/JunctionTree-inl.h>
#include <gtsam/discrete/TypedDiscreteFactorGraph.h>
//#include <gtsam/discrete/DiscreteSequentialSolver.h>
using namespace std;
using namespace gtsam;
/* ******************************************************************************** */
// initialize some common test values
DiscreteKey v0("v0"), v1("v1"), v2("v2", 3);
TypedDiscreteFactor::Values values;
void init() {
values[v0] = 0;
values[v1] = 0;
values[v2] = 1;
}
string path("../../../gtsam/discrete/tests/data/");
/* ************************************************************************* */
TEST( TypedDiscreteFactorGraph, parseUAI)
{
// This reads in a small factor graph on discrete variables v0, v1, and v2
TypedDiscreteFactorGraph graph(path + "UAI/sampleMARKOV.uai");
// GTSAM_PRINT(graph);
LONGS_EQUAL(3,graph.nrFactors())
double expectedP001 = 0.436 * 0.128 * 0.333;
double actualP001 = graph(values);
DOUBLES_EQUAL(expectedP001,actualP001,1e-9)
}
/* ************************************************************************* */
TEST( TypedDiscreteFactorGraph, parseUAI1)
{
// This reads in a big graph from UAI 2008
TypedDiscreteFactorGraph graph(path + "UAI/uai08_test1.uai");
// GTSAM_PRINT(graph);
LONGS_EQUAL(54,graph.nrFactors())
}
/* ************************************************************************* */
TEST( TypedDiscreteFactorGraph, parseUAI2)
{
// This reads in a big graph from UAI 2008
TypedDiscreteFactorGraph graph(path + "UAI/uai08_test2.uai");
// GTSAM_PRINT(graph);
LONGS_EQUAL(21,graph.nrFactors())
}
/* ************************************************************************* */
TEST( TypedDiscreteFactorGraph, parseUAI3)
{
// This reads in a big graph from UAI 2008
TypedDiscreteFactorGraph graph(path + "UAI/uai08_test3.uai");
// GTSAM_PRINT(graph);
LONGS_EQUAL(13,graph.nrFactors())
}
///* ******************************************************************************** */
//// global test data
//
//string graphFilename(path + "UAI/uai08_test2.uai");
//string evidFilename (path + "UAI/uai08_test2.uai.evid");
//
///**
// * [Cluster] Ordering splitted from libDAI
// * {x9}, {x10}, {x11}, {x12}, {x13}, {x14}, {x15}, {x16}, {x17}, {x18}, {x19}, {x20},
// * {x0, x1, x8}, {x2, x6, x7}, {x4, x6, x8},
// * {x1, x5, x7}, {x1, x3, x7, x8}, {x3, x6, x7, x8})
// *
// */
//size_t ordering[21] = {9,10,11,12,13,14,15,16,17,18,19,20,0,2,4,5,1,3,6,7,8};
//vector<Index> vOrdering;
//
//// Container for all data read from files.
//TypedDiscreteFactorGraph container;
//
//// The factor graph generated from the data, after assigning the elimination ordering
//// for each variable
//DiscreteFactorGraph::shared_ptr graph;
//
///* ******************************************************************************** */
//// Initialize all test data
//void initTestData()
//{
// container.readFromFile_UAI(graphFilename);
// container.readEvidence_UAI(evidFilename);
// for (size_t i = 0; i<21; i++) vOrdering.push_back(ordering[i]);
// container.setOrdering(vOrdering);
// graph = container.generateFactorGraph();
//}
//
//
///* ******************************************************************************** */
//// Test reading .fg file from libDAI
//TEST( TypedDiscreteFactorGraph, readFG)
//{
// TypedDiscreteFactorGraph graph;
// graph.readFromFile_FG(path + "FG/alarm.fg");
//// graph.print();
//}
//
///* ******************************************************************************** */
//TEST( TypedDiscreteFactorGraph, testSequentialSolver)
//{
//// tic(0, "Sequential Solver");
//
// boost::shared_ptr<PotentialTable::MapAssignment> actualMPE
// = DiscreteSequentialSolver(*graph).optimize();
// BOOST_FOREACH(const PotentialTable::MapAssignment::value_type asg, *actualMPE)
// cout << vOrdering[asg.first] << ": " << asg.second << endl;
//
//// toc(0, "Sequential Solver");
// tictoc_print();
//
//}
//
///* ******************************************************************************** */
//void backSubstitute(const BayesTree<DiscreteConditional>::sharedClique currentClique,
// PotentialTable::MapAssignment& assignments) {
//
// // solve the bayes net in the current node
// DiscreteBayesNet::const_reverse_iterator it = currentClique->rbegin();
// for (; it!=currentClique->rend(); ++it) {
// size_t val = (*it)->solve(assignments); // Solve for that variable
// assignments[(*it)->key()] = val; // store result in partial solution
// }
//
// // solve the bayes nets in the child nodes
// BOOST_FOREACH(const BayesTree<DiscreteConditional>::sharedClique& child,
// currentClique->children()) {
// backSubstitute(child, assignments);
// }
//}
//
//
//void optimizeMultiFrontal(DiscreteFactorGraph::shared_ptr graph) {
//
// VariableIndex::shared_ptr structure(new VariableIndex(*graph));
// JunctionTree<DiscreteFactorGraph>::shared_ptr junctionTree(new JunctionTree<DiscreteFactorGraph>(*graph, *structure));
// BayesTree<DiscreteConditional>::sharedClique rootClique = junctionTree->eliminate();
//
//// toc(1, "GJT eliminate");
//
//// tictoc_print();
//
//// // Allocate solution vector
//// tic(2, "allocate VectorValues");
//// vector<size_t> dims(rootClique->back()->key() + 1, 0);
//// countDims(rootClique, dims);
//// VectorValues result(dims);
//// toc(2, "allocate VectorValues");
////
//// // back-substitution
//// tic(3, "back-substitute");
//// btreeBackSubstitute(rootClique, result);
//// toc(3, "back-substitute");
//// return result;
//}
//
//
///* ******************************************************************************** */
//
//TEST( TypedDiscreteFactorGraph, multifrontalSolver)
//{
// tic(0, "Multifrontal Solver");
// optimizeMultiFrontal(graph);
//
// toc(0, "Multifrontal Solver");
// tictoc_print();
//}
/* ************************************************************************* */
int main() { /*initTestData(); */
init();
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

View File

@ -0,0 +1,69 @@
/*
* testTypedDiscreteVariable.cpp
*
* @date March 2, 2011
* @author Duy-Nguyen Ta
*/
#include <CppUnitLite/TestHarness.h>
using namespace std;
/* ******************************************************************************** */
class DiscreteVariable {
int v_;
public:
DiscreteVariable(int v) :
v_(v) {
}
bool operator ==(const DiscreteVariable& other) const {
return v_ == other.v_;
}
bool operator !=(const DiscreteVariable& other) const {
return v_ != other.v_;
}
};
class Color: public DiscreteVariable {
public:
enum Value {
red, green, blue
};
Color(Value v) :
DiscreteVariable(v) {
}
};
class Flavor: public DiscreteVariable {
public:
enum Value {
sweet, sour
};
Flavor(Value v) :
DiscreteVariable(v) {
}
};
//TEST( TypedDiscreteFactorGraph, simple)
//{
// Color v1(Color::red), v2(Color::green);
// CHECK(v1!=v2);
// CHECK(v1==v1);
//
// // Declare a bunch of keys
// DiscreteKey<Color> C("Color");
// DiscreteKey<Flavor> F("Flavor");
//
// // Create a factor saying red is associated with sweet,
// // green with sour, blue with both
// TypedDiscreteFactor factor(C, F, "1 0 0 1 1 1");
//}
/* ************************************************************************* */
int main() {
TestResult tr;
return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */

Some files were not shown because too many files have changed in this diff Show More