How to remove vertices from a graph?












8














I have 2 lists: list 1 is a list of vertices of a graph, says, {1,2,3,4,5} and list 2 keeps track of edges (i.e which vertex connects to which) such as {{1,2}, {2,3},{3,4},{4,1},{2,5}}. Now I want to remove some vertices in list 1 and I want that any edges in list 2 that have an end same as one of the removed vertices will also be removed. What would be the best way to do this in Mathematica? (I can do this easily in other languages like vb.net, but I still am trying to get my head on Mathematica)










share|improve this question





























    8














    I have 2 lists: list 1 is a list of vertices of a graph, says, {1,2,3,4,5} and list 2 keeps track of edges (i.e which vertex connects to which) such as {{1,2}, {2,3},{3,4},{4,1},{2,5}}. Now I want to remove some vertices in list 1 and I want that any edges in list 2 that have an end same as one of the removed vertices will also be removed. What would be the best way to do this in Mathematica? (I can do this easily in other languages like vb.net, but I still am trying to get my head on Mathematica)










    share|improve this question



























      8












      8








      8


      3





      I have 2 lists: list 1 is a list of vertices of a graph, says, {1,2,3,4,5} and list 2 keeps track of edges (i.e which vertex connects to which) such as {{1,2}, {2,3},{3,4},{4,1},{2,5}}. Now I want to remove some vertices in list 1 and I want that any edges in list 2 that have an end same as one of the removed vertices will also be removed. What would be the best way to do this in Mathematica? (I can do this easily in other languages like vb.net, but I still am trying to get my head on Mathematica)










      share|improve this question















      I have 2 lists: list 1 is a list of vertices of a graph, says, {1,2,3,4,5} and list 2 keeps track of edges (i.e which vertex connects to which) such as {{1,2}, {2,3},{3,4},{4,1},{2,5}}. Now I want to remove some vertices in list 1 and I want that any edges in list 2 that have an end same as one of the removed vertices will also be removed. What would be the best way to do this in Mathematica? (I can do this easily in other languages like vb.net, but I still am trying to get my head on Mathematica)







      list-manipulation graphs-and-networks






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 days ago









      Henrik Schumacher

      49k467139




      49k467139










      asked Dec 31 '18 at 22:39









      N.T.C

      37917




      37917






















          4 Answers
          4






          active

          oldest

          votes


















          9














          These are done easily with graph functions:



          g = Graph[Range[5], {1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 2 <-> 5}];


          enter image description here



          g2 = VertexDelete[g, 1];


          enter image description here



          EdgeList[g2]


          (*



          {2 <-> 3, 3 <-> 4, 2 <-> 5}



          *)



          Of course this works as well if you want to delete more than one vertex, e.g., vertices 1 and 5:



          g2 = VertexDelete[g, {1, 5}];





          share|improve this answer































            7














            Although using Graph and VertexDelete is tempting (and every sane person would try that first), it is by no means an efficient way of doing this. Here is a method that circumvents Graph and works directly on sparse adjacency matrices:



            edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};
            vertdel = {1, 4};

            A = SparseArray[edges -> 1, {1, 1} Max[edges]];
            a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
            SparseArray[a.A.a]["NonzeroPositions"]



            {{2, 3}, {2, 5}}




            Here A is the (nonsymmetric) adjacency matrix of the underlying graph and a is the diagonal matrix carrying the indicator function of the new index set on the diagonal. Then a.A.a is the (nonsymmetric) adjacency matrix of the resulting graph; we need to wrap it with SparseArray in order to enforce recomputation of the sparse array pattern so that the list of nonzero positions of the matrix corresponds to edges of the new graph.
            (For those who are interested: The undocumented "SparseArray`" context contains many graph-related algorithms that work directly on (weighted) adjacency matrices and that are usually much faster than the Graph-based implementations.)





            With a timing example, it is easier to realize that this is more efficient than applying MemberQ or to use Graph (and that Graph is so slow should be utterly embarassing for WRI).



            Of course, using SparseArray for the adjacency matrix, I assume that the adjacency matrix is sparse...



            Let's create the edge set of a random graph:



            n = 10000;
            m = 100000;
            ndel = 1000;
            G = RandomGraph[{n, m}];
            edges = Developer`ToPackedArray[List @@@ EdgeList[G]];
            vertdel = RandomSample[Span[1, n], ndel];


            Here are the timings:



            First@AbsoluteTiming[
            MemberQedges = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]];
            ]



            131.84




            First@AbsoluteTiming[
            g = Graph[Range[n], UndirectedEdge @@@ edges];
            gedges = EdgeList[VertexDelete[g, vertdel]];
            ]



            9.80492




            First@AbsoluteTiming[
            A = SparseArray[edges -> 1, {1, 1} Max[edges]];
            a = DiagonalMatrix[ SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
            spedges = SparseArray[a.A.a]["NonzeroPositions"];
            ]



            0.006572




            Of course, we have to check whether all methods return essentially the same result:



            Sort[spedges] == Sort[MemberQedges] == Sort[List @@@ gedges]



            True




            Actually, already constructing the (old) graph g takes 20 times(!) longer than computing the edges of the new graph with the sparse matrix method...



            Finally, as in all Graph-related threads, it is almost obligatory to mention Szabolcs' "IGraphM`" package. There we find the function IGWeightedVertexDelete that accomplishes the task with more acceptable speed. It may be slower than the SparseArray method but it preserves also a lot of structure of the old graph; this may be very useful in practice and comes -- of course -- at a certain cost.



            Needs["IGraphM`"]
            First@AbsoluteTiming[
            g2 = IGWeightedVertexDelete[g, vertdel];
            ]
            EdgeList[g2] == gedges



            0.0746



            True







            share|improve this answer



















            • 1




              @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
              – Henrik Schumacher
              2 days ago










            • This solution makes me realize how much there is to learn about Wolfram this year
              – FredrikD
              2 days ago










            • As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
              – geordie
              2 days ago



















            6














            Update: An alternative way to use SparseArray with a better speed:



            Using Henrik's timing setup



            First@AbsoluteTiming[A2 = SparseArray[edges -> 1, {1, 1} Max[edges]]; 
            A2[[All, vertdel]] = A2[[vertdel, All]] = 0;
            spedges2 = A2["NonzeroPositions"];]



            0.00570508




            versus



            First@AbsoluteTiming[A = SparseArray[edges -> 1, {1, 1} Max[edges]];
            a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
            spedges = SparseArray[a.A.a]["NonzeroPositions"];]



            0.0119241




            spedges == spedges2



            True




            Original answer:



            edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};


            A few more alternatives:



            Select[edges, FreeQ[1]]
            Pick[edges, FreeQ[1] /@ edges]
            DeleteCases[edges, {_, 1} | {1, _}]
            List @@@ EdgeList[VertexDelete[edges, 1]]


            all give




            {{2, 3}, {3, 4}, {2, 5}}







            share|improve this answer























            • Your first three suggestions only work for removing a single vertex.
              – geordie
              Dec 31 '18 at 23:38






            • 2




              @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
              – kglr
              2 days ago





















            3














            The following works for removing several vertices and corresponding edges:



            verts = {1, 2, 3, 4, 5};
            edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};

            vertdel = {1, 4}
            verts2 = Complement[verts, vertdel]
            edges2 = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]]



            {1, 4}



            {2, 3, 5}



            {{2, 3}, {2, 5}}







            share|improve this answer





















              Your Answer





              StackExchange.ifUsing("editor", function () {
              return StackExchange.using("mathjaxEditing", function () {
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
              });
              });
              }, "mathjax-editing");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "387"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f188657%2fhow-to-remove-vertices-from-a-graph%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              9














              These are done easily with graph functions:



              g = Graph[Range[5], {1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 2 <-> 5}];


              enter image description here



              g2 = VertexDelete[g, 1];


              enter image description here



              EdgeList[g2]


              (*



              {2 <-> 3, 3 <-> 4, 2 <-> 5}



              *)



              Of course this works as well if you want to delete more than one vertex, e.g., vertices 1 and 5:



              g2 = VertexDelete[g, {1, 5}];





              share|improve this answer




























                9














                These are done easily with graph functions:



                g = Graph[Range[5], {1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 2 <-> 5}];


                enter image description here



                g2 = VertexDelete[g, 1];


                enter image description here



                EdgeList[g2]


                (*



                {2 <-> 3, 3 <-> 4, 2 <-> 5}



                *)



                Of course this works as well if you want to delete more than one vertex, e.g., vertices 1 and 5:



                g2 = VertexDelete[g, {1, 5}];





                share|improve this answer


























                  9












                  9








                  9






                  These are done easily with graph functions:



                  g = Graph[Range[5], {1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 2 <-> 5}];


                  enter image description here



                  g2 = VertexDelete[g, 1];


                  enter image description here



                  EdgeList[g2]


                  (*



                  {2 <-> 3, 3 <-> 4, 2 <-> 5}



                  *)



                  Of course this works as well if you want to delete more than one vertex, e.g., vertices 1 and 5:



                  g2 = VertexDelete[g, {1, 5}];





                  share|improve this answer














                  These are done easily with graph functions:



                  g = Graph[Range[5], {1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 2 <-> 5}];


                  enter image description here



                  g2 = VertexDelete[g, 1];


                  enter image description here



                  EdgeList[g2]


                  (*



                  {2 <-> 3, 3 <-> 4, 2 <-> 5}



                  *)



                  Of course this works as well if you want to delete more than one vertex, e.g., vertices 1 and 5:



                  g2 = VertexDelete[g, {1, 5}];






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 31 '18 at 23:38

























                  answered Dec 31 '18 at 22:58









                  David G. Stork

                  23.3k22051




                  23.3k22051























                      7














                      Although using Graph and VertexDelete is tempting (and every sane person would try that first), it is by no means an efficient way of doing this. Here is a method that circumvents Graph and works directly on sparse adjacency matrices:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};
                      vertdel = {1, 4};

                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      SparseArray[a.A.a]["NonzeroPositions"]



                      {{2, 3}, {2, 5}}




                      Here A is the (nonsymmetric) adjacency matrix of the underlying graph and a is the diagonal matrix carrying the indicator function of the new index set on the diagonal. Then a.A.a is the (nonsymmetric) adjacency matrix of the resulting graph; we need to wrap it with SparseArray in order to enforce recomputation of the sparse array pattern so that the list of nonzero positions of the matrix corresponds to edges of the new graph.
                      (For those who are interested: The undocumented "SparseArray`" context contains many graph-related algorithms that work directly on (weighted) adjacency matrices and that are usually much faster than the Graph-based implementations.)





                      With a timing example, it is easier to realize that this is more efficient than applying MemberQ or to use Graph (and that Graph is so slow should be utterly embarassing for WRI).



                      Of course, using SparseArray for the adjacency matrix, I assume that the adjacency matrix is sparse...



                      Let's create the edge set of a random graph:



                      n = 10000;
                      m = 100000;
                      ndel = 1000;
                      G = RandomGraph[{n, m}];
                      edges = Developer`ToPackedArray[List @@@ EdgeList[G]];
                      vertdel = RandomSample[Span[1, n], ndel];


                      Here are the timings:



                      First@AbsoluteTiming[
                      MemberQedges = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]];
                      ]



                      131.84




                      First@AbsoluteTiming[
                      g = Graph[Range[n], UndirectedEdge @@@ edges];
                      gedges = EdgeList[VertexDelete[g, vertdel]];
                      ]



                      9.80492




                      First@AbsoluteTiming[
                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[ SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];
                      ]



                      0.006572




                      Of course, we have to check whether all methods return essentially the same result:



                      Sort[spedges] == Sort[MemberQedges] == Sort[List @@@ gedges]



                      True




                      Actually, already constructing the (old) graph g takes 20 times(!) longer than computing the edges of the new graph with the sparse matrix method...



                      Finally, as in all Graph-related threads, it is almost obligatory to mention Szabolcs' "IGraphM`" package. There we find the function IGWeightedVertexDelete that accomplishes the task with more acceptable speed. It may be slower than the SparseArray method but it preserves also a lot of structure of the old graph; this may be very useful in practice and comes -- of course -- at a certain cost.



                      Needs["IGraphM`"]
                      First@AbsoluteTiming[
                      g2 = IGWeightedVertexDelete[g, vertdel];
                      ]
                      EdgeList[g2] == gedges



                      0.0746



                      True







                      share|improve this answer



















                      • 1




                        @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                        – Henrik Schumacher
                        2 days ago










                      • This solution makes me realize how much there is to learn about Wolfram this year
                        – FredrikD
                        2 days ago










                      • As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                        – geordie
                        2 days ago
















                      7














                      Although using Graph and VertexDelete is tempting (and every sane person would try that first), it is by no means an efficient way of doing this. Here is a method that circumvents Graph and works directly on sparse adjacency matrices:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};
                      vertdel = {1, 4};

                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      SparseArray[a.A.a]["NonzeroPositions"]



                      {{2, 3}, {2, 5}}




                      Here A is the (nonsymmetric) adjacency matrix of the underlying graph and a is the diagonal matrix carrying the indicator function of the new index set on the diagonal. Then a.A.a is the (nonsymmetric) adjacency matrix of the resulting graph; we need to wrap it with SparseArray in order to enforce recomputation of the sparse array pattern so that the list of nonzero positions of the matrix corresponds to edges of the new graph.
                      (For those who are interested: The undocumented "SparseArray`" context contains many graph-related algorithms that work directly on (weighted) adjacency matrices and that are usually much faster than the Graph-based implementations.)





                      With a timing example, it is easier to realize that this is more efficient than applying MemberQ or to use Graph (and that Graph is so slow should be utterly embarassing for WRI).



                      Of course, using SparseArray for the adjacency matrix, I assume that the adjacency matrix is sparse...



                      Let's create the edge set of a random graph:



                      n = 10000;
                      m = 100000;
                      ndel = 1000;
                      G = RandomGraph[{n, m}];
                      edges = Developer`ToPackedArray[List @@@ EdgeList[G]];
                      vertdel = RandomSample[Span[1, n], ndel];


                      Here are the timings:



                      First@AbsoluteTiming[
                      MemberQedges = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]];
                      ]



                      131.84




                      First@AbsoluteTiming[
                      g = Graph[Range[n], UndirectedEdge @@@ edges];
                      gedges = EdgeList[VertexDelete[g, vertdel]];
                      ]



                      9.80492




                      First@AbsoluteTiming[
                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[ SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];
                      ]



                      0.006572




                      Of course, we have to check whether all methods return essentially the same result:



                      Sort[spedges] == Sort[MemberQedges] == Sort[List @@@ gedges]



                      True




                      Actually, already constructing the (old) graph g takes 20 times(!) longer than computing the edges of the new graph with the sparse matrix method...



                      Finally, as in all Graph-related threads, it is almost obligatory to mention Szabolcs' "IGraphM`" package. There we find the function IGWeightedVertexDelete that accomplishes the task with more acceptable speed. It may be slower than the SparseArray method but it preserves also a lot of structure of the old graph; this may be very useful in practice and comes -- of course -- at a certain cost.



                      Needs["IGraphM`"]
                      First@AbsoluteTiming[
                      g2 = IGWeightedVertexDelete[g, vertdel];
                      ]
                      EdgeList[g2] == gedges



                      0.0746



                      True







                      share|improve this answer



















                      • 1




                        @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                        – Henrik Schumacher
                        2 days ago










                      • This solution makes me realize how much there is to learn about Wolfram this year
                        – FredrikD
                        2 days ago










                      • As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                        – geordie
                        2 days ago














                      7












                      7








                      7






                      Although using Graph and VertexDelete is tempting (and every sane person would try that first), it is by no means an efficient way of doing this. Here is a method that circumvents Graph and works directly on sparse adjacency matrices:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};
                      vertdel = {1, 4};

                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      SparseArray[a.A.a]["NonzeroPositions"]



                      {{2, 3}, {2, 5}}




                      Here A is the (nonsymmetric) adjacency matrix of the underlying graph and a is the diagonal matrix carrying the indicator function of the new index set on the diagonal. Then a.A.a is the (nonsymmetric) adjacency matrix of the resulting graph; we need to wrap it with SparseArray in order to enforce recomputation of the sparse array pattern so that the list of nonzero positions of the matrix corresponds to edges of the new graph.
                      (For those who are interested: The undocumented "SparseArray`" context contains many graph-related algorithms that work directly on (weighted) adjacency matrices and that are usually much faster than the Graph-based implementations.)





                      With a timing example, it is easier to realize that this is more efficient than applying MemberQ or to use Graph (and that Graph is so slow should be utterly embarassing for WRI).



                      Of course, using SparseArray for the adjacency matrix, I assume that the adjacency matrix is sparse...



                      Let's create the edge set of a random graph:



                      n = 10000;
                      m = 100000;
                      ndel = 1000;
                      G = RandomGraph[{n, m}];
                      edges = Developer`ToPackedArray[List @@@ EdgeList[G]];
                      vertdel = RandomSample[Span[1, n], ndel];


                      Here are the timings:



                      First@AbsoluteTiming[
                      MemberQedges = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]];
                      ]



                      131.84




                      First@AbsoluteTiming[
                      g = Graph[Range[n], UndirectedEdge @@@ edges];
                      gedges = EdgeList[VertexDelete[g, vertdel]];
                      ]



                      9.80492




                      First@AbsoluteTiming[
                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[ SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];
                      ]



                      0.006572




                      Of course, we have to check whether all methods return essentially the same result:



                      Sort[spedges] == Sort[MemberQedges] == Sort[List @@@ gedges]



                      True




                      Actually, already constructing the (old) graph g takes 20 times(!) longer than computing the edges of the new graph with the sparse matrix method...



                      Finally, as in all Graph-related threads, it is almost obligatory to mention Szabolcs' "IGraphM`" package. There we find the function IGWeightedVertexDelete that accomplishes the task with more acceptable speed. It may be slower than the SparseArray method but it preserves also a lot of structure of the old graph; this may be very useful in practice and comes -- of course -- at a certain cost.



                      Needs["IGraphM`"]
                      First@AbsoluteTiming[
                      g2 = IGWeightedVertexDelete[g, vertdel];
                      ]
                      EdgeList[g2] == gedges



                      0.0746



                      True







                      share|improve this answer














                      Although using Graph and VertexDelete is tempting (and every sane person would try that first), it is by no means an efficient way of doing this. Here is a method that circumvents Graph and works directly on sparse adjacency matrices:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};
                      vertdel = {1, 4};

                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      SparseArray[a.A.a]["NonzeroPositions"]



                      {{2, 3}, {2, 5}}




                      Here A is the (nonsymmetric) adjacency matrix of the underlying graph and a is the diagonal matrix carrying the indicator function of the new index set on the diagonal. Then a.A.a is the (nonsymmetric) adjacency matrix of the resulting graph; we need to wrap it with SparseArray in order to enforce recomputation of the sparse array pattern so that the list of nonzero positions of the matrix corresponds to edges of the new graph.
                      (For those who are interested: The undocumented "SparseArray`" context contains many graph-related algorithms that work directly on (weighted) adjacency matrices and that are usually much faster than the Graph-based implementations.)





                      With a timing example, it is easier to realize that this is more efficient than applying MemberQ or to use Graph (and that Graph is so slow should be utterly embarassing for WRI).



                      Of course, using SparseArray for the adjacency matrix, I assume that the adjacency matrix is sparse...



                      Let's create the edge set of a random graph:



                      n = 10000;
                      m = 100000;
                      ndel = 1000;
                      G = RandomGraph[{n, m}];
                      edges = Developer`ToPackedArray[List @@@ EdgeList[G]];
                      vertdel = RandomSample[Span[1, n], ndel];


                      Here are the timings:



                      First@AbsoluteTiming[
                      MemberQedges = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]];
                      ]



                      131.84




                      First@AbsoluteTiming[
                      g = Graph[Range[n], UndirectedEdge @@@ edges];
                      gedges = EdgeList[VertexDelete[g, vertdel]];
                      ]



                      9.80492




                      First@AbsoluteTiming[
                      A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[ SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];
                      ]



                      0.006572




                      Of course, we have to check whether all methods return essentially the same result:



                      Sort[spedges] == Sort[MemberQedges] == Sort[List @@@ gedges]



                      True




                      Actually, already constructing the (old) graph g takes 20 times(!) longer than computing the edges of the new graph with the sparse matrix method...



                      Finally, as in all Graph-related threads, it is almost obligatory to mention Szabolcs' "IGraphM`" package. There we find the function IGWeightedVertexDelete that accomplishes the task with more acceptable speed. It may be slower than the SparseArray method but it preserves also a lot of structure of the old graph; this may be very useful in practice and comes -- of course -- at a certain cost.



                      Needs["IGraphM`"]
                      First@AbsoluteTiming[
                      g2 = IGWeightedVertexDelete[g, vertdel];
                      ]
                      EdgeList[g2] == gedges



                      0.0746



                      True








                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited 2 days ago

























                      answered 2 days ago









                      Henrik Schumacher

                      49k467139




                      49k467139








                      • 1




                        @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                        – Henrik Schumacher
                        2 days ago










                      • This solution makes me realize how much there is to learn about Wolfram this year
                        – FredrikD
                        2 days ago










                      • As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                        – geordie
                        2 days ago














                      • 1




                        @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                        – Henrik Schumacher
                        2 days ago










                      • This solution makes me realize how much there is to learn about Wolfram this year
                        – FredrikD
                        2 days ago










                      • As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                        – geordie
                        2 days ago








                      1




                      1




                      @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                      – Henrik Schumacher
                      2 days ago




                      @chris Thanks for the reminder. I wrote that in -- as J.M. would say -- gedanken Mathematica.
                      – Henrik Schumacher
                      2 days ago












                      This solution makes me realize how much there is to learn about Wolfram this year
                      – FredrikD
                      2 days ago




                      This solution makes me realize how much there is to learn about Wolfram this year
                      – FredrikD
                      2 days ago












                      As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                      – geordie
                      2 days ago




                      As someone who hadn't quite understood the purpose of sparse arrays (until now) this is fascinating.
                      – geordie
                      2 days ago











                      6














                      Update: An alternative way to use SparseArray with a better speed:



                      Using Henrik's timing setup



                      First@AbsoluteTiming[A2 = SparseArray[edges -> 1, {1, 1} Max[edges]]; 
                      A2[[All, vertdel]] = A2[[vertdel, All]] = 0;
                      spedges2 = A2["NonzeroPositions"];]



                      0.00570508




                      versus



                      First@AbsoluteTiming[A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];]



                      0.0119241




                      spedges == spedges2



                      True




                      Original answer:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};


                      A few more alternatives:



                      Select[edges, FreeQ[1]]
                      Pick[edges, FreeQ[1] /@ edges]
                      DeleteCases[edges, {_, 1} | {1, _}]
                      List @@@ EdgeList[VertexDelete[edges, 1]]


                      all give




                      {{2, 3}, {3, 4}, {2, 5}}







                      share|improve this answer























                      • Your first three suggestions only work for removing a single vertex.
                        – geordie
                        Dec 31 '18 at 23:38






                      • 2




                        @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                        – kglr
                        2 days ago


















                      6














                      Update: An alternative way to use SparseArray with a better speed:



                      Using Henrik's timing setup



                      First@AbsoluteTiming[A2 = SparseArray[edges -> 1, {1, 1} Max[edges]]; 
                      A2[[All, vertdel]] = A2[[vertdel, All]] = 0;
                      spedges2 = A2["NonzeroPositions"];]



                      0.00570508




                      versus



                      First@AbsoluteTiming[A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];]



                      0.0119241




                      spedges == spedges2



                      True




                      Original answer:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};


                      A few more alternatives:



                      Select[edges, FreeQ[1]]
                      Pick[edges, FreeQ[1] /@ edges]
                      DeleteCases[edges, {_, 1} | {1, _}]
                      List @@@ EdgeList[VertexDelete[edges, 1]]


                      all give




                      {{2, 3}, {3, 4}, {2, 5}}







                      share|improve this answer























                      • Your first three suggestions only work for removing a single vertex.
                        – geordie
                        Dec 31 '18 at 23:38






                      • 2




                        @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                        – kglr
                        2 days ago
















                      6












                      6








                      6






                      Update: An alternative way to use SparseArray with a better speed:



                      Using Henrik's timing setup



                      First@AbsoluteTiming[A2 = SparseArray[edges -> 1, {1, 1} Max[edges]]; 
                      A2[[All, vertdel]] = A2[[vertdel, All]] = 0;
                      spedges2 = A2["NonzeroPositions"];]



                      0.00570508




                      versus



                      First@AbsoluteTiming[A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];]



                      0.0119241




                      spedges == spedges2



                      True




                      Original answer:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};


                      A few more alternatives:



                      Select[edges, FreeQ[1]]
                      Pick[edges, FreeQ[1] /@ edges]
                      DeleteCases[edges, {_, 1} | {1, _}]
                      List @@@ EdgeList[VertexDelete[edges, 1]]


                      all give




                      {{2, 3}, {3, 4}, {2, 5}}







                      share|improve this answer














                      Update: An alternative way to use SparseArray with a better speed:



                      Using Henrik's timing setup



                      First@AbsoluteTiming[A2 = SparseArray[edges -> 1, {1, 1} Max[edges]]; 
                      A2[[All, vertdel]] = A2[[vertdel, All]] = 0;
                      spedges2 = A2["NonzeroPositions"];]



                      0.00570508




                      versus



                      First@AbsoluteTiming[A = SparseArray[edges -> 1, {1, 1} Max[edges]];
                      a = DiagonalMatrix[SparseArray[Partition[vertdel, 1] -> 0, {Length[A]}, 1]];
                      spedges = SparseArray[a.A.a]["NonzeroPositions"];]



                      0.0119241




                      spedges == spedges2



                      True




                      Original answer:



                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};


                      A few more alternatives:



                      Select[edges, FreeQ[1]]
                      Pick[edges, FreeQ[1] /@ edges]
                      DeleteCases[edges, {_, 1} | {1, _}]
                      List @@@ EdgeList[VertexDelete[edges, 1]]


                      all give




                      {{2, 3}, {3, 4}, {2, 5}}








                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited yesterday

























                      answered Dec 31 '18 at 23:04









                      kglr

                      177k9198406




                      177k9198406












                      • Your first three suggestions only work for removing a single vertex.
                        – geordie
                        Dec 31 '18 at 23:38






                      • 2




                        @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                        – kglr
                        2 days ago




















                      • Your first three suggestions only work for removing a single vertex.
                        – geordie
                        Dec 31 '18 at 23:38






                      • 2




                        @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                        – kglr
                        2 days ago


















                      Your first three suggestions only work for removing a single vertex.
                      – geordie
                      Dec 31 '18 at 23:38




                      Your first three suggestions only work for removing a single vertex.
                      – geordie
                      Dec 31 '18 at 23:38




                      2




                      2




                      @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                      – kglr
                      2 days ago






                      @geordie, if you want to remove a list of vertices, say {1,2}, you can use 1|2 instead of 1.
                      – kglr
                      2 days ago













                      3














                      The following works for removing several vertices and corresponding edges:



                      verts = {1, 2, 3, 4, 5};
                      edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};

                      vertdel = {1, 4}
                      verts2 = Complement[verts, vertdel]
                      edges2 = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]]



                      {1, 4}



                      {2, 3, 5}



                      {{2, 3}, {2, 5}}







                      share|improve this answer


























                        3














                        The following works for removing several vertices and corresponding edges:



                        verts = {1, 2, 3, 4, 5};
                        edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};

                        vertdel = {1, 4}
                        verts2 = Complement[verts, vertdel]
                        edges2 = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]]



                        {1, 4}



                        {2, 3, 5}



                        {{2, 3}, {2, 5}}







                        share|improve this answer
























                          3












                          3








                          3






                          The following works for removing several vertices and corresponding edges:



                          verts = {1, 2, 3, 4, 5};
                          edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};

                          vertdel = {1, 4}
                          verts2 = Complement[verts, vertdel]
                          edges2 = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]]



                          {1, 4}



                          {2, 3, 5}



                          {{2, 3}, {2, 5}}







                          share|improve this answer












                          The following works for removing several vertices and corresponding edges:



                          verts = {1, 2, 3, 4, 5};
                          edges = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {2, 5}};

                          vertdel = {1, 4}
                          verts2 = Complement[verts, vertdel]
                          edges2 = Complement[edges, Flatten[Select[edges, MemberQ[#]] & /@ vertdel, 1]]



                          {1, 4}



                          {2, 3, 5}



                          {{2, 3}, {2, 5}}








                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Dec 31 '18 at 23:37









                          geordie

                          2,0031530




                          2,0031530






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Mathematica Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f188657%2fhow-to-remove-vertices-from-a-graph%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                              Alcedinidae

                              Can an atomic nucleus contain both particles and antiparticles? [duplicate]