microsoft / automatic-graph-layout

A set of tools for graph layout and viewing
Other
1.34k stars 301 forks source link

Different layout every time we run the app #342

Open Cussa opened 1 year ago

Cussa commented 1 year ago

I am creating an app that loads some data and draw the graph. However, every time I run the app with the same data, it generates a different graph.

Is there any way to set the layout parameters and make it generate the same layout everytime?

levnach commented 1 year ago

What layout do you use?

levnach commented 1 year ago

Also make sure that the order of the nodes in the graph is the same.

Cussa commented 1 year ago

I am using a simple Graph object, which is attached to a GraphViewer. I am always adding the elements in the same order. I did not defined the Layout property.

I will generate some logs later today to show the behaviour and share the findings here.

Cussa commented 1 year ago

Sorry that it took some time for me to come with an update, but I did a complete refactory on how I was generating the graph.

Different from the examples, I was adding the nodes and then adding the edges between them. All the examples create the edges first and work on the node later, if necessary.

So, with the current change, I can confirm that the behaviour is not the same: every run there is a different result.

To confirm what I was doing, I generated a small log that shows the connections being added to the diagram.

Here are the results for two runs. There was no change on the code or the source of the diagrams. I just closed the application and run again. As you can see by the logs, all edges were inserted exactly on the same order. 20230328193717.log 20230328193756.log

However, this is the diagram generated for the fist run: image

This is the diagram for the second run: image

As you can see, even with both diagrams being generated from the same source and on the same order, it seems that there is something happening that results on a different diagram.

I tried to play with the LayoutAlgorithmSettings, but got always a different results on run. Right now, I am not defining this property.

And another point that I believe is important to mention is that this is happening in the WPF graph.

Please, let me know if there is any other information that you need to help me.

Thanks in advance

levnach commented 1 year ago

The logs are identical. @Cussa, can you do experiment for me? When you have your graph ready, use method graph.Write("fileName") to save the graph to a file. See, that you get an identical file content every time.

Cussa commented 1 year ago

20230328201709.graph.log 20230328201709.log 20230328201749.graph.log 20230328201749.log

Here are the files. The graph.log are renamed, as the Github does not accept the msagl file.

I can see that on the file that asked me to generate, the nodes are created in different order.

Cussa commented 1 year ago

Tyring to add more info to help. This is how I am generating my graph:

public class Item
{
    public Guid Id {get;set;}
    public List<Guid> Children {get;set;}
}

...

    private List<Item> _list;

    private void AddEdges(Graph graph, Guid id)
    {
        var current = _list.First(x => x.Id == id);
        foreach (var child in current.Children)
        {
            if (graph.Edges.Any(x => x.Source == id.ToString() && x.Target == child.ToString()))
                continue;

            _sb.AppendLine($"{id} - {child}");
            graph.AddEdge(id.ToString(), child.ToString());
            AddEdges(graph, child);
        }
    }
levnach commented 1 year ago

I hope MSAGL layout is deterministic: when I run TestWpfViewer and reload the same graph I get the same drawing each time. I am not sure what is going on. Can you double check that your data is ordered the same way?

Cussa commented 1 year ago

I checked and yes, it is the same order. The logs that I shared show I was adding the edges in the same order in both cases.

Tomorrow I will try to create a small project to reproduce completely the error, so I can share it with you.

Cussa commented 1 year ago

GraphTester.zip

I took the example WPF project and created a small validator for the issue. One thing: as the Nuget packages are outdated, I cloned the repository, build it in release mode and copied the dlls to a lib folder. When you open this project, it will probably complain that it can't find the dlls. Please, remove my reference and add to your local build dlls. It uses the log file that I generated in my app as the source to add the edges, so we can be sure that the data is always added in the same order.

This is one run: image 20230329082200.msagl.log

This is another run: image 20230329082250.msagl.log

Please, let me know if I can share any more info to help with this issue.

Cussa commented 1 year ago

I did more tests here to check if the problem was how I was adding the child items (in theory, I went through a whole "brach" before going to the next one. However, that produced the same result.

levnach commented 1 year ago

Sorry, I could not get to it yet. As I understand the issue is still open. I suspect the problem is that I use Hashtable.

levnach commented 1 year ago

Fixed by https://github.com/microsoft/automatic-graph-layout/commit/ede35ec01ba97ff97fd037db387b8706935f5178. The reason was the usage of Hashtable in Drawing.Graph.