/// <summary>
        /// Adds another PetriNet to this at the given Transition (since the other PetriNet should start with a place).
        /// Keep in mind to close all open sinks afterwards!
        /// </summary>
        /// <param name="petriNet">The other PetriNet</param>
        /// <param name="atTransition">A transition in THIS PetriNet, where the added net will be connected</param>
        /// <author>Jannik Arndt</author>
        public void MergeWithPetriNet(PetriNet petriNet, Transition atTransition)
        {
            List <Node> sources = petriNet.GetSources();

            if (sources.Count > 0)
            {
                atTransition.OutgoingPlaces.Add((sources[0] as Place));
                atTransition.OutgoingPlaces[0].AppendIncomingTransition(atTransition);
                Transitions.AddRange(petriNet.Transitions);
                Places.AddRange(petriNet.Places);
            }
        }
        /// <param name="tNet">Petri net of the trace</param>
        /// <param name="pNet">Petri net of the model</param>
        /// <param name="traceMoveCost">Trace move cost</param>
        /// <param name="modelMoveCost">Model move cost</param>
        public SynchronousProductNet(IPetriNet tNet, IPetriNet pNet, int traceMoveCost = 1, int modelMoveCost = 1)
        {
            StartPlaces.Add(tNet.StartPlace);
            StartPlaces.Add(pNet.StartPlace);
            EndPlaces.Add(tNet.EndPlace);
            EndPlaces.Add(pNet.EndPlace);
            Places.AddRange(tNet.Places.Union(pNet.Places));

            PlacesToTransitions = Places.ToDictionary(p => p, p => new List <int>());

            InitTransitionsFromPNet(tNet, traceMoveCost, false);
            InitTransitionsFromPNet(pNet, modelMoveCost, true);

            //Add transitions for synchronous move as cost 0 + addition to make all costs positive
            foreach (var t1 in tNet.Transitions)
            {
                foreach (var t2 in pNet.Transitions)
                {
                    if (!t1.Activity.Equals(t2.Activity))
                    {
                        continue;
                    }
                    var transition = new Transition($"({t1.Id},{t2.Id})", t1.Activity);
                    transition.InputPlaces.AddRange(t1.InputPlaces.Union(t2.InputPlaces));
                    transition.OutputPlaces.AddRange(t1.OutputPlaces.Union(t2.OutputPlaces));
                    var syncTransition = new STransition(transition, 0);

                    foreach (var place in transition.InputPlaces)
                    {
                        PlacesToTransitions[place].Add(Transitions.Count);
                    }

                    Transitions.Add(syncTransition);
                }
            }
        }