Local Open Scope nat.
(** * Properties of subgraphs and degrees *)
(** ** Subgraph predicate [g'] is a subgraph of [g] if: - the vertex set of [g'] is a subset of the vertex set of [g] - the adjacency set of every [v] in [g'] is a subset of adjacency set of every [v] in [g] *)
Definition is_subgraph (g' g : graph) :=
S.Subset (nodes g') (nodes g) /\ forall v, S.Subset (adj g' v) (adj g v).
(** * Induced subgraphs *)
(** ** Definition *)
Definition subgraph_of (g : graph) (s : S.t) :=
M.fold (fun v adj g' => if S.mem v s then M.add v (S.inter s adj) g' else g') g empty_graph.
(** ** Edges of an induced subgraph are a subset of the original graph *)
(** Note that this is defined pointwise: the adjacency set is a subset for every vertex. *)
(** ** Induced subgraph is subgraph *)
(** * Removal of nodes *)
(** ** Removing a distinct vertex from a graph *)
(** If [i] and [j] are distinct vertices then removing [j] from the graph doesn't affect [i]'s membership. *)
(** If [i] is in the graph with [j] removed then [i] is not equal to [j]. *)
(** ** Removing a node results in a subgraph *)
(** ** Remove a set of vertices from a graph *)
(** To make it easier to prove things about it, - first restrict the graph by [S.diff (Mdomain g) s] - then map subtracting s from every adj set *)
Definition remove_nodes (g : graph) (s : nodeset) :=
M.map (fun ve => S.diff ve s) (restrict g (S.diff (nodes g) s)).
(** ** Every vertex in the removing set is not in the resulting graph *)
(** ** Removing a non-empty set of vertices decreases the size of the graph *)
(** ** Removing a subgraph preserves undirectedness *)
(** ** Removing a subgraph preserves irreflexivity *)
(** ** Removing a node preserves undirectedness *)
(** ** Removing a node preserves irreflexivity *)

Lemma remove_node_no_selfloop : forall g i, no_selfloop g -> no_selfloop (remove_node i g).