public bool CompareTraces(ByteDcrGraph graph)
        {
            ResetValues();
            FindUniqueTraces(graph, new ComparableList<int>());

            return _comparisonResult && (_uniqueTraceSet.Count == _compareSet.Count);
        }
        private void FindUniqueTraces(ByteDcrGraph inputGraph, ComparableList<int> currentTrace)
        {
            //compare trace length with desired depth
            foreach (var activity in inputGraph.GetRunnableIndexes())
            {
                if (currentTrace.Count == 100)
                {
                    var test = 252354;
                }

                var inputGraphCopy = new ByteDcrGraph(inputGraph);
                var currentTraceCopy = new ComparableList<int>(currentTrace);

                inputGraphCopy.ExecuteActivity(activity);

                //add event to trace
                currentTraceCopy.Add(activity);

                if (ByteDcrGraph.IsFinalState(inputGraphCopy.State))
                {
                    _uniqueTraceSet.Add(currentTraceCopy);

                    if(_compareSet != null &&
                        (!_compareSet.Contains(currentTraceCopy)))
                    {
                        _comparisonResult = false;
                        return;
                    }
                }
                //if we have not seen the state before
                if (!_seenStates.Contains(inputGraphCopy.State))
                {
                    if (_compareStates != null
                        && !_compareStates.Contains(inputGraphCopy.StateWithNonRunnableActivitiesEqual(inputGraphCopy.State)))
                    {
                        _comparisonResult = false;
                        return;
                    }
                    _seenStates.Add(inputGraphCopy.State);
                    FindUniqueTraces(inputGraphCopy,currentTraceCopy);
                }
            }
        }
        private HashSet<ComparableList<int>> SetUniqueTraces(ByteDcrGraph graph)
        {
            ResetValues();

            FindUniqueTraces(graph, new ComparableList<int>());
            _compareSet = _uniqueTraceSet;
            _compareStates = new HashSet<byte[]>(_seenStates.Select(graph.StateWithNonRunnableActivitiesEqual), new ByteArrayComparer());

            return _uniqueTraceSet;
        }
 public UniqueTraceFinder(ByteDcrGraph graph)
 {
     SetUniqueTraces(graph);
 }
        private static void FindUniqueStatesInclRunnableActivityCountDepthFirstBytes(ByteDcrGraph inputGraph)
        {
            Counter++;
            var activitiesToRun = inputGraph.GetRunnableIndexes();

            var clone = new byte[inputGraph.State.Length];
            inputGraph.State.CopyTo(clone, 0);
            _seenStatesWithRunnableActivityCount.Add(clone, activitiesToRun.Count);

            foreach (var activityIdx in activitiesToRun)
            {
                // Spawn new work
                var inputGraphCopy = new ByteDcrGraph(inputGraph);
                inputGraphCopy.ExecuteActivity(activityIdx);

                var stateSeen = _seenStatesWithRunnableActivityCount.ContainsKey(inputGraphCopy.State);

                if (!stateSeen)
                {
                    // Register wish to continue
                    FindUniqueStatesInclRunnableActivityCountDepthFirstBytes(inputGraphCopy);
                }
            }
        }
        public DcrGraph RemoveRedundancy(DcrGraph inputGraph, BackgroundWorker worker = null)
        {
            _worker = worker;
            #if DEBUG
            Console.WriteLine("Started redundancy removal:");
            #endif

            //TODO: use an algorithm to check if the graph is connected and if not then recursively remove redundancy on the subgraphs.
            //temporarily remove flower activities.
            var copy = inputGraph.Copy();

            var removedActivities =
                copy.GetActivities().Where(x => (x.Included && !copy.ActivityHasRelations(x))).ToList();

            foreach (var a in removedActivities)
            {
                copy.RemoveActivity(a.Id);
            }

            var byteDcrGraph = new ByteDcrGraph(copy);

            _uniqueTraceFinder = new UniqueTraceFinder(byteDcrGraph);

            _originalInputDcrGraph = copy.Copy();
            OutputDcrGraph = copy;

            // Remove relations and see if the unique traces acquired are the same as the original. If so, the relation is clearly redundant and is removed immediately
            // All the following calls potentially alter the OutputDcrGraph

            RemoveRedundantRelations(RelationType.Response);

            RemoveRedundantRelations(RelationType.Condition);

            RemoveRedundantRelations(RelationType.InclusionExclusion);

            RemoveRedundantRelations(RelationType.Milestone);

            foreach (var activity in OutputDcrGraph.GetActivities())
            {
                var graphCopy = new ByteDcrGraph(byteDcrGraph);

                graphCopy.RemoveActivity(activity.Id);

                ReportProgress?.Invoke("Removing Activity " + activity.Id);

                // Compare unique traces - if equal activity is redundant
                if (_uniqueTraceFinder.CompareTraces(graphCopy))
                {
                    // The relation is redundant, replace  copy with current copy (with the relation removed)
                    OutputDcrGraph.RemoveActivity(activity.Id);
                }

            }

            foreach (var a in removedActivities)
            {
                OutputDcrGraph.AddActivity(a.Id, a.Name);
                OutputDcrGraph.SetIncluded(true, a.Id);
                OutputDcrGraph.SetPending(a.Pending, a.Id);
            }
            var nested = OutputDcrGraph.ExportToXml();

            return OutputDcrGraph;
        }