Skip to main content

bugs - Removing edge weights from a Graph


Bug introduced in 8.0 and persisting through 12.0




How can I remove EdgeWeights from a Graph without affecting any other properties of the graph?


Let's construct a graph with weights:


g = RandomGraph[{10, 20}, EdgeWeight -> ConstantArray[1, 20]]


Based on the documentation I would expect the following to return Automatic (the same thing it returns for a graph that has no edge weights):


PropertyValue[RemoveProperty[g, EdgeWeight], EdgeWeight]

(* ==> {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} *)

However, it returns the weights that were originally set.


The following seems to work, but it removes other properties as well


PropertyValue[RemoveProperty[g], EdgeWeight]

(* ==> Automatic *)


Extracting the edges and vertices, then re-building the graph will discard other properties as well. Graph objects are atomic, and they don't have a Mathematica-expression form, so trying to modify them at the expression level is not a possibility either.


How can one then remove EdgeWeights from a Graph without modifying any other properties of the Graph?


Update: It turns out WeightedGraphQ@RemoveProperty[g] still returns True. So even though the weight values are removed, the system still considers the graph to be weighted.



Answer



This has to be a bug. I think Graph never really associates EdgeWeight with corresponding edges.


Here is a simplified example.


g = Graph[{1, 2, 3}, {
Property[1 <-> 2, EdgeWeight -> x],
1 <-> 3,

Property[2 <-> 3, EdgeWeight -> y]
}];

gNew = RemoveProperty[{g, 1 <-> 2}, EdgeWeight];
gNew2 = SetProperty[{g, 1 <-> 2}, EdgeWeight -> Missing["Nonexistent"]];


Outer[
PropertyValue[{#1, #2}, EdgeWeight] &,
{g, gNew, gNew2},

{1 <-> 2, 1 <-> 3, 2 <-> 3}
] // TableForm[#,
TableHeadings -> {{"g", "gNew", "gNew2"},
{1 <-> 2, 1 <-> 3, 2 <-> 3}}] & // Quiet

comparison of EdgeWeight list after removing


Notice the gNew row, how EdgeWeights are mis-aligned when the preceding one (i.e. x) deleted. And the 3rd column gives us a clue how PropertyValue extracts EdgeWeight -- that is, by Part.


I would definitely call this a bug.




The workaround I can come up with are two ways. The easy way is as I did for gNew2 -- instead of removing it, replacing it with a placeholder. While the hard way is to permute the to-be-delete edge to the end of edge-list before performing the delete:



myRemoveEdgeWeight[g_, e_] :=
Module[{vl = VertexList[g], el = EdgeList[g], pos, ewl, ew},
pos = Position[el, e];
el = Insert[Delete[el, pos], e, -1];
ewl = PropertyValue[g, EdgeWeight];
ew = Extract[ewl, pos][[1]];
ewl = Insert[Delete[ewl, pos], ew, -1];
Graph[vl, el, EdgeWeight -> ewl] //
RemoveProperty[{#, e}, EdgeWeight] &
]


PropertyValue[{myRemoveEdgeWeight[g, 1 <-> 2], #}, EdgeWeight] & /@
{1 <-> 2, 1 <-> 3, 2 <-> 3}


{{1, y}[[3]], 1, y}

Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?