Ticket #7304 (needs_info enhancement)

Opened 4 years ago

Last modified 6 months ago

Contract edge in graph

Reported by: AJonsson Owned by: rlm
Priority: major Milestone: sage-5.10
Component: graph theory Keywords:
Cc: brunellus, lkeough Work issues:
Report Upstream: N/A Reviewers: Tom Boothby
Authors: Merged in:
Dependencies: #9362 Stopgaps:

Description

This patch contract an edge (u,v) in a graph. In the resulting graph vertex u is merged into vertex v.

The variables u and v can be passed as variables, a tuple (u,v) or a 3-tuple (u,v,'label'). The last allows us to use an element from G.edges() for contraction.

Attachments

trac_7304.patch Download (3.4 KB) - added by AJonsson 4 years ago.
Initial patch for review
trac_7304_contract_edge.patch Download (5.7 KB) - added by brunellus 12 months ago.

Change History

Changed 4 years ago by AJonsson

Initial patch for review

comment:1 Changed 4 years ago by AJonsson

  • Status changed from new to needs_review
  • Type changed from defect to enhancement

comment:2 follow-up: ↓ 6 Changed 4 years ago by AJonsson

  • Status changed from needs_review to closed
  • Resolution set to duplicate

Duplicate of #7159 . That ticket is about vertex merging, but it is basically the same thing.

comment:3 Changed 4 years ago by mhansen

  • Milestone changed from sage-4.2.1 to sage-duplicate/invalid/wontfix

comment:4 Changed 4 years ago by AJonsson

  • Status changed from closed to new
  • Resolution duplicate deleted
  • Milestone changed from sage-duplicate/invalid/wontfix to sage-4.2.1

On second thought, reopening.

Merging vertices gives a slightly different result for certain cases that are important in deletion-contraction algorithms, so this function has a place to fill as well.

Example of case that contract_edge() handles differently:

If we have two vertices A, B, with two parallel edges between them, a merging of A and B results in a single vertex with no edge or loops. If we instead choose to contract one of the two parallel edges (and allow loops), we will end up with a single vertex which has a loop.

comment:5 Changed 4 years ago by AJonsson

  • Status changed from new to needs_review

comment:6 in reply to: ↑ 2 ; follow-up: ↓ 7 Changed 4 years ago by mvngu

Replying to AJonsson:

Duplicate of #7159 . That ticket is about vertex merging, but it is basically the same thing.

Anders, please don't close tickets. That's the job of the release manager. See this section of the Developer's Guide for conventions on closing tickets.

comment:7 in reply to: ↑ 6 Changed 4 years ago by AJonsson

Replying to mvngu:

Anders, please don't close tickets. That's the job of the release manager. See this section of the Developer's Guide for conventions on closing tickets.

Whoops. Hadn't seen that section. Won't happen again.

comment:8 follow-up: ↓ 10 Changed 4 years ago by ncohen

I understand your point, but do you think it useful to have 2 different functions to merge vertices, instead of having just one with more options ? It could be a bit confusing...

Nathann

comment:9 Changed 4 years ago by ncohen

  • Status changed from needs_review to needs_info

comment:10 in reply to: ↑ 8 Changed 4 years ago by AJonsson

Replying to ncohen:

I understand your point, but do you think it useful to have 2 different functions to merge vertices, instead of having just one with more options ? It could be a bit confusing...

Nathann

I don't feel too strongly about it. As long as full functionality exists, it matters little to me if it is in one or two functions.

comment:11 Changed 4 years ago by ncohen

My advice exactly !

Could you then write a patch to modify #7159 as soon as it will be merged ? You could also directly modify the trac ticket as it is not merged yet, but then we would be looking for someone else to review it, as for #7814...

As you said, I do not mind as long as the two behaviours exist.. If you think your version of merging should be the default one, it's up to you ! :-)

comment:12 Changed 4 years ago by AJonsson

  • Status changed from needs_info to needs_work

Ok, will look closer into a modification of #7159 to be added after that ticket has been merged to Sage.

comment:13 follow-up: ↓ 14 Changed 3 years ago by ncohen

  • Report Upstream set to N/A

should we keep this ticket open, or close it and open a new one with your modification of #7159 ?

comment:14 in reply to: ↑ 13 Changed 3 years ago by AJonsson

  • Summary changed from [With patch, needs review] Contract edge in graph to Contract edge in graph

Replying to ncohen:

should we keep this ticket open, or close it and open a new one with your modification of #7159 ?

Let's keep it open, otherwise we would just open an almost identical ticket. I will see if I get the time to finish the function sometime next week.

comment:16 Changed 2 years ago by Stefan

There's a spam link above here that needs removing.

As a matroid theorist, I look at deletion and contraction a bit differently. It bothers me that I cannot write something along the lines of

H = G.delete((1,2)).contract([(3,5),(6,7)])

without modifying G.

comment:17 Changed 2 years ago by ncohen

What would your code do ? Are your pairs edges or vertices ? Right now your have a merge_vertices commands in Graph that lets you contract any set of vertices.

Nathann

comment:18 follow-up: ↓ 19 Changed 2 years ago by Stefan

My pairs would be edges. In an even more ideal world, I would refer to them by their labels. For comparison, if M is a matroid with elements 'e', 'f', 'g', I currently have some experimental code allowing me to write

N = M / e? \ ['f', 'g']

resulting in the matroid with e contracted and f,g deleted. From a matroid-theoretic point of view, if you contract an edge, all edges parallel to it should turn into loops. The current merge_vertices doesn't do that, even if I call G.allow_loops(True) first. With this behavior, contracting a loop should probably equal deleting a loop.

Anyway, my main point is that I feel there should be methods for deletion and contraction that return a new graph, rather than modifying the graph itself.

Real use case: the other day I was wondering about maximal planar subgraphs of a small graph G. In that case you want to explore: first delete edge 'e', then delete edge 'f', then 'f' and 'g', then 'f' and 'h', and finally only edge 'h'. The current implementation makes such exploration of minors a bit cumbersome: you frequently make copies of G, which you then modify.

comment:19 in reply to: ↑ 18 Changed 2 years ago by ncohen

Anyway, my main point is that I feel there should be methods for deletion and contraction that return a new graph, rather than modifying the graph itself.

Would you be interested in mixing the two ? Like sometimes calling a delete_edge function which returns a graph, and some other times a method which modifies the graph ?

The current behaviour is necessary for many functions, and replacing it would mean a huge loss in efficiency. It is possible to add a keyword to all those methods so that a graph will be returned instead of modifying the current graph. I don't quite like this, as it would mean some additional tests for each of all those very fundamental functions, but then again... On the other hand, if you are not interested in mixing the two type of operations, perhaps the best is to work on an immutable graph class. Many people have asked this already, and when working on an immutable graph class having a default behaviour of "returning an immutable copy of the graph modified as requested" does not seem too unnatural. What about this then ? :-)

Nathann

comment:20 follow-ups: ↓ 21 ↓ 22 Changed 2 years ago by Stefan

I'm not at all in favor of having two different behaviors encoded in one function. One option would be to implement the div and _backslash_ operators to do, respectively, contraction and deletion without changing the object.

comment:21 in reply to: ↑ 20 Changed 2 years ago by ncohen

I'm not at all in favor of having two different behaviors encoded in one function. One option would be to implement the div and _backslash_ operators to do, respectively, contraction and deletion without changing the object.

Got it !

This being said, I understand that's how matroid theory is written "on the paper", but do you think it would be possible to write useful code using only those symbols when any of them means copying the whole structure ? But perhaps I do not know how you intend to code it, and how much such operations could cost in memory and time ...

Nathann

comment:22 in reply to: ↑ 20 ; follow-up: ↓ 23 Changed 2 years ago by rlm

Replying to Stefan:

I'm not at all in favor of having two different behaviors encoded in one function.

This is often the case. For example many graph functions in Sage have an inplace option, which provides exactly this choice.

comment:23 in reply to: ↑ 22 Changed 2 years ago by Stefan

Replying to rlm:

Replying to Stefan:

I'm not at all in favor of having two different behaviors encoded in one function.

This is often the case. For example many graph functions in Sage have an inplace option, which provides exactly this choice.

Indeed it does! I'm not sure that this happens often, but so far I found subgraph() and relabel(). The former defaults to inplace=False; the latter defaults to inplace=True.

In that case it would be preferable not to have extra methods (the list is quite long enough as it stands). Defining the forward and backslashes might still be a neat addition.

Nathann, typical work with matroids is on relatively small ground sets. I don't expect intensive calculations on graphs with more than, say, a few dozen edges. We would wrap the graph in a GraphicMatroid? object anyway, so it's easy to compensate for any functionality in the graph code that is not entirely fit for our purpose. So you need not worry about our needs for the time being.

What remains is the question of contracting one edge from a parallel pair (see above).

comment:24 Changed 16 months ago by brunellus

  • Cc brunellus added
  • Status changed from needs_work to needs_review

So, what do you say to my patch? It provides

  1. loops handling (see #9807)
  2. contract_edge option
  3. inplace option

comment:25 Changed 16 months ago by brunellus

  • Dependencies set to #7304

comment:26 Changed 16 months ago by brunellus

  • Dependencies changed from #7304 to #9362

comment:27 Changed 15 months ago by davidloeffler

Apply trac_7304_contract_edge.patch

(for patchbot)

comment:28 Changed 14 months ago by boothby

Brunellus,

This isn't quite there, and you haven't tested everything.

Graphs have a copy method -- g = g.copy() is faster than g=copy(g). There are two problems with the block

        if vertices and vertices[0] is None: 
	    vertices[0] = g.add_vertex()

first off, this assumes that g.add_vertex() returns the label of the added vertex. It does not. Second, it modifies vertices for no good reason (what if the users passes in a tuple, set, or generator?)

comment:29 Changed 14 months ago by boothby

  • Status changed from needs_review to needs_work
  • Reviewers set to Tom Boothby

comment:30 Changed 14 months ago by boothby

Ah, I see that g.add_vertex() indeed returns the label for the current alpha of 5.0. Please update this to not modify the users's input with

    vertices = list(vertices)

and use g.copy() instead of copy, and I'll give this a positive review.

comment:31 Changed 12 months ago by brunellus

Thanks for the review! I will update the patch right now.

Changed 12 months ago by brunellus

comment:32 Changed 12 months ago by brunellus

  • Status changed from needs_work to needs_review

comment:33 Changed 10 months ago by lkeough

  • Cc lkeough added

comment:34 Changed 10 months ago by lkeough

I have been working on getting the Tutte polynomial into Sage (#1314). The Tutte polynomial needs contraction with keeping any resulting multiedges and loops (but removing the edge you contracted). It seems your code does this if you allow multiedges and loops and use the contract_edge feature.

I think they may have had this discussion above, but I can't tell what was concluded: Would adding an option like "simplegraph = True" be a reasonable thing to do?

comment:35 Changed 10 months ago by jdemeyer

Please fill in your real name as Author.

comment:36 Changed 6 months ago by ncohen

  • Status changed from needs_review to needs_info

Ok.... Which is the patch that needs to be reviewed ? Is it trac_7304_contract_edge.patch Download ?

Nathann

Note: See TracTickets for help on using tickets.