@@ -28,6 +28,8 @@ pub enum GraphClass {
2828 Dag ,
2929 /// Partially Directed Acyclic Graph (`-->`, `---`)
3030 Pdag ,
31+ /// Maximally Oriented Partially Directed Acyclic Graph (Meek-closed PDAG)
32+ Mpdag ,
3133 /// Undirected Graph (only `---`)
3234 Ug ,
3335 /// Acyclic Directed Mixed Graph (`-->`, `<->`)
@@ -47,6 +49,7 @@ impl std::str::FromStr for GraphClass {
4749 match s. to_lowercase ( ) . as_str ( ) {
4850 "dag" => Ok ( GraphClass :: Dag ) ,
4951 "pdag" | "cpdag" => Ok ( GraphClass :: Pdag ) ,
52+ "mpdag" => Ok ( GraphClass :: Mpdag ) ,
5053 "ug" => Ok ( GraphClass :: Ug ) ,
5154 "admg" => Ok ( GraphClass :: Admg ) ,
5255 "ag" | "mag" | "pag" => Ok ( GraphClass :: Ag ) ,
@@ -62,6 +65,7 @@ impl GraphClass {
6265 match self {
6366 GraphClass :: Dag => "DAG" ,
6467 GraphClass :: Pdag => "PDAG" ,
68+ GraphClass :: Mpdag => "MPDAG" ,
6569 GraphClass :: Ug => "UG" ,
6670 GraphClass :: Admg => "ADMG" ,
6771 GraphClass :: Ag => "AG" ,
@@ -480,6 +484,14 @@ impl GraphSession {
480484 let pdag = Pdag :: new ( core) . map_err ( |e| self . map_error ( e) ) ?;
481485 Ok ( GraphView :: Pdag ( Arc :: new ( pdag) ) )
482486 }
487+ GraphClass :: Mpdag => {
488+ let pdag = Pdag :: new ( core) . map_err ( |e| self . map_error ( e) ) ?;
489+ if pdag. is_meek_closed ( ) {
490+ Ok ( GraphView :: Pdag ( Arc :: new ( pdag) ) )
491+ } else {
492+ Err ( "graph is not MPDAG (not closed under Meek rules)" . to_string ( ) )
493+ }
494+ }
483495 GraphClass :: Ug => {
484496 let ug = Ug :: new ( core) . map_err ( |e| self . map_error ( e) ) ?;
485497 Ok ( GraphView :: Ug ( Arc :: new ( ug) ) )
@@ -694,6 +706,14 @@ impl GraphSession {
694706 Pdag :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . map_err ( |e| self . map_error ( e) ) ?;
695707 Ok ( GraphClass :: Pdag )
696708 }
709+ GraphClass :: Mpdag => {
710+ let pdag = Pdag :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . map_err ( |e| self . map_error ( e) ) ?;
711+ if pdag. is_meek_closed ( ) {
712+ Ok ( GraphClass :: Mpdag )
713+ } else {
714+ Err ( "graph is not MPDAG (not closed under Meek rules)" . to_string ( ) )
715+ }
716+ }
697717 GraphClass :: Ug => {
698718 Ug :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . map_err ( |e| self . map_error ( e) ) ?;
699719 Ok ( GraphClass :: Ug )
@@ -712,8 +732,12 @@ impl GraphSession {
712732 Ok ( GraphClass :: Dag )
713733 } else if Ug :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . is_ok ( ) {
714734 Ok ( GraphClass :: Ug )
715- } else if Pdag :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . is_ok ( ) {
716- Ok ( GraphClass :: Pdag )
735+ } else if let Ok ( pdag) = Pdag :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) {
736+ if pdag. is_meek_closed ( ) {
737+ Ok ( GraphClass :: Mpdag )
738+ } else {
739+ Ok ( GraphClass :: Pdag )
740+ }
717741 } else if Admg :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . is_ok ( ) {
718742 Ok ( GraphClass :: Admg )
719743 } else if Ag :: new ( Arc :: new ( core. as_ref ( ) . clone ( ) ) ) . is_ok ( ) {
@@ -1212,6 +1236,7 @@ mod tests {
12121236 fn graph_class_from_str_and_as_str ( ) {
12131237 assert_eq ! ( "dag" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Dag ) ;
12141238 assert_eq ! ( "CPDAG" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Pdag ) ;
1239+ assert_eq ! ( "mpdag" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Mpdag ) ;
12151240 assert_eq ! ( "ug" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Ug ) ;
12161241 assert_eq ! ( "admg" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Admg ) ;
12171242 assert_eq ! ( "mag" . parse:: <GraphClass >( ) . unwrap( ) , GraphClass :: Ag ) ;
@@ -1221,6 +1246,7 @@ mod tests {
12211246
12221247 assert_eq ! ( GraphClass :: Dag . as_str( ) , "DAG" ) ;
12231248 assert_eq ! ( GraphClass :: Pdag . as_str( ) , "PDAG" ) ;
1249+ assert_eq ! ( GraphClass :: Mpdag . as_str( ) , "MPDAG" ) ;
12241250 assert_eq ! ( GraphClass :: Ug . as_str( ) , "UG" ) ;
12251251 assert_eq ! ( GraphClass :: Admg . as_str( ) , "ADMG" ) ;
12261252 assert_eq ! ( GraphClass :: Ag . as_str( ) , "AG" ) ;
@@ -1516,6 +1542,22 @@ mod tests {
15161542 GraphClass :: Pdag
15171543 ) ;
15181544
1545+ let mut mpdag =
1546+ GraphSession :: from_snapshot ( Arc :: clone ( & snapshot) , 3 , true , GraphClass :: Mpdag ) ;
1547+ let mut mpdag_edges = EdgeBuffer :: new ( ) ;
1548+ mpdag_edges. push ( 0 , 2 , d) ;
1549+ mpdag_edges. push ( 1 , 2 , d) ;
1550+ mpdag. set_edges ( mpdag_edges) ;
1551+ assert ! ( matches!( & * mpdag. view( ) . unwrap( ) , GraphView :: Pdag ( _) ) ) ;
1552+ assert_eq ! (
1553+ mpdag. resolve_class( GraphClass :: Mpdag ) . unwrap( ) ,
1554+ GraphClass :: Mpdag
1555+ ) ;
1556+ assert_eq ! (
1557+ mpdag. resolve_class( GraphClass :: Auto ) . unwrap( ) ,
1558+ GraphClass :: Mpdag
1559+ ) ;
1560+
15191561 let mut ug = GraphSession :: from_snapshot ( Arc :: clone ( & snapshot) , 2 , true , GraphClass :: Ug ) ;
15201562 let mut ug_edges = EdgeBuffer :: new ( ) ;
15211563 ug_edges. push ( 0 , 1 , u) ;
0 commit comments