Esempio n. 1
0
        /// <summary>
        /// Tries to perform at most given number of steps of word evaluation.
        /// </summary>
        /// <param name="numberOfSteps">if zero, the evaluation continues until it is complete</param>
        public void Evaluate(int numberOfSteps)
        {
            if (!IsConstructionFinished())
            {
                throw new InvalidOperationException("cannot evaluate word when the fsm is not yet completely constructed");
            }

            if (numberOfSteps <= 0)
            {
                numberOfSteps = -1;
            }
            while (numberOfSteps != 0 && !IsEvaluationFinished())
            {
                // remove single letter
                var letter = evaluatedWordRemainingFragment[0].ToString();

                MachineTransition transition = transitions.FirstOrNull(
                    x => x.InitialStateId == currentState && x.ContainsLetter(letter));
                //try
                //{
                //	transition = transitions.First(x => x.InitialStateId == currentState && x.ContainsLetter(letter));
                //}
                //catch (InvalidOperationException)
                //{
                //	// silent catch, matching transition was not found
                //}

                evaluatedWordProcessedFragment = new StringBuilder(evaluatedWordProcessedFragment)
                                                 .Append(letter).ToString();

                evaluatedWordRemainingFragment = evaluatedWordRemainingFragment.Substring(1);

                previousState = currentState;
                if (transition == null)
                {
                    currentState = -1;
                    break;
                }
                currentState = transition.ResultingStateId;

                if (numberOfSteps > 0)
                {
                    --numberOfSteps;
                }
            }
        }
Esempio n. 2
0
        public void Draw(Canvas canvas, bool constructionMode, IList <RegularExpression> highlightedStates,
                         IList <MachineTransition> highlightedTransitions, bool evaluationMode, int previousState,
                         int currentState, bool evaluationEnded)
        {
            if (canvas == null)
            {
                throw new ArgumentNullException("canvas");
            }

            canvas.Clear();

            double maxX = 0;
            double maxY = 0;

            {
                double startAngle = FindMostFreeAngle(0, true, false, 315);

                if (constructionMode && highlightedStates.Any(x => states.IndexOf(x) == 0))
                {
                    DrawStartArrow(canvas, HighlightedEdgeBrush, HighlightedEdgeBorderBrush, vertices[0], startAngle);
                }
                else
                {
                    DrawStartArrow(canvas, EdgeBrush, EdgeBorderBrush, vertices[0], startAngle);
                }
            }

            string text = String.Empty;

            for (int i = 0; i < vertices.Count; ++i)
            {
                var location = vertices[i];

                int transitionIndex = -1;
                foreach (var transition in transitions)
                {
                    ++transitionIndex;
                    if (transition.InitialStateId != i)
                    {
                        continue;
                    }

                    var letters = new TextBlock();
                    letters.Height = TextBlockHeight;
                    //letters.Width = double.NaN; // Auto, goes to 100%
                    letters.Width         = transition.Item2.Count * TextBlockHeight;
                    letters.Text          = String.Join(" ", transition.Item2);
                    letters.TextAlignment = TextAlignment.Center;

                    Brush edgeBrush       = null;
                    Brush edgeBorderBrush = null;
                    Brush edgeLabelBrush  = null;
                    if (constructionMode && highlightedTransitions.Any(x => x.InitialStateId == transition.InitialStateId &&
                                                                       x.ResultingStateId == transition.ResultingStateId))
                    {
                        edgeBrush       = HighlightedEdgeBrush;
                        edgeBorderBrush = HighlightedEdgeBorderBrush;
                        edgeLabelBrush  = HighlightedEdgeLabelBrush;
                    }
                    else if (evaluationMode && transition.InitialStateId == previousState &&
                             transition.ResultingStateId == currentState)
                    {
                        edgeBrush       = HighlightedEdgeBrush;
                        edgeBorderBrush = HighlightedEdgeBorderBrush;
                        edgeLabelBrush  = HighlightedEdgeLabelBrush;
                    }
                    else
                    {
                        edgeBrush       = EdgeBrush;
                        edgeBorderBrush = EdgeBorderBrush;
                        edgeLabelBrush  = EdgeLabelBrush;
                    }

                    letters.Foreground = edgeLabelBrush;

                    if (transition.Item3 == i)
                    {
                        // loop, i.e. directed edge to self

                        double angle = edges[transition].Item1;

                        DrawLoop(canvas, edgeBrush, edgeBorderBrush, edgeLabelBrush, location, angle);

                        Point translatePoint = new Point(0, 0).MoveTo(angle, LoopHeight);

                        if (angle > 90 && angle <= 270)
                        {
                            angle -= 180;
                        }

                        var rotateTransform    = new RotateTransform(angle, letters.Width / 2, TextBlockHeight / 2);
                        var translateTransform = new TranslateTransform(translatePoint.X, translatePoint.Y);
                        var transforms         = new TransformGroup();
                        transforms.Children.Add(rotateTransform);
                        transforms.Children.Add(translateTransform);
                        letters.RenderTransform = transforms;

                        canvas.Add(letters, location.X - letters.Width / 2, location.Y - TextBlockHeight / 2, 0);
                    }
                    else
                    {
                        // normal edge
                        Point endpoint = vertices[transition.Item3];

                        double angle = edges[transition].Item1 - 90;
                        // double angle = location.Angle(endpoint) - 90; // already got it
                        Point translatePoint;

                        Point middle = new Point((location.X + endpoint.X) / 2, (location.Y + endpoint.Y) / 2);

                        List <Point> intersections = new List <Point>();
                        if (layoutScore.IntersectingEdges.Count > 0)
                        {
                            // detect intersections with other edges to move label to the longest uninterrupted segment
                            foreach (var intr in layoutScore.IntersectingEdges)
                            {
                                if (intr.Item1 != transitionIndex)
                                {
                                    continue;
                                }
                                MachineTransition intersectingTransition = transitions[intr.Item2];
                                Point             p1 = vertices[intersectingTransition.InitialStateId];
                                Point             p2 = vertices[intersectingTransition.ResultingStateId];

                                Point intersection = location.FindIntersectionAssumingItExists(endpoint, p1, p2);

                                intersections.Add(intersection);
                            }

                            // detect overlapping vertices to move label away from them
                            foreach (var intr in layoutScore.VerticesOnEdges)
                            {
                                // the vertex must be near currently evaluated transition
                                if (intr.Item2 != transitionIndex)
                                {
                                    continue;
                                }

                                //double angle = location.Angle(endpoint); // already got it

                                Point intersection = vertices[intr.Item1].MoveTo(angle, intr.Item3);

                                if (intersection.DistanceToLine(location, endpoint) > intr.Item3)
                                {
                                    intersection = vertices[intr.Item1].MoveTo(angle + 180, intr.Item3);
                                }

                                intersections.Add(intersection);
                            }

                            if (intersections.Count > 0)
                            {
                                intersections.Add(location.MoveTo(endpoint, StateEllipseDiameter / 2));
                                intersections.Add(endpoint.MoveTo(location, StateEllipseDiameter / 2));
                                intersections.Sort((a, b) => a.X.CompareTo(b.X));
                            }
                        }
                        if (intersections.Count > 0)
                        {
                            var intersectionDistances = intersections.Zip(intersections.Skip(1), (x, y) => y.Distance(x)).ToArray();
                            //Console.Out.WriteLine(String.Join("; ", intersectionDistances));

                            // find the best position for the label
                            // i.e. the longest fragment without intersections
                            int    index = intersectionDistances.IndexOfMax();
                            double max   = intersectionDistances[index];
                            middle = intersections[index].MoveTo(intersections[index + 1], max / 2);

                            //DrawDot(canvas, Brushes.Red, middle);
                        }

                        //TODO: take bent edges into account (i.e. case of two transitions: q1->q2 and q2->q1)
                        // because in such cases labels are sometimes too close to the edges they belong to

                        if (transitions.Any(x => x.InitialStateId == transition.ResultingStateId &&
                                            x.ResultingStateId == transition.InitialStateId))
                        {
                            if (angle > 90 && angle <= 270)
                            {
                                angle         -= 180;
                                translatePoint = new Point(0, 0).MoveTo(angle, TextBlockHeight / 2 + 4);
                            }
                            else
                            {
                                translatePoint = new Point(0, 0).MoveTo(angle, -TextBlockHeight / 2 - 4);
                            }

                            DrawEdge(canvas, edgeBrush, edgeBorderBrush, edgeLabelBrush,
                                     location, edges[transition].Item1, endpoint, edges[transition].Item2);
                        }
                        else
                        {
                            DrawEdge(canvas, edgeBrush, edgeBorderBrush, edgeLabelBrush, location, endpoint);

                            if (angle > 90 && angle <= 270)
                            {
                                angle -= 180;
                            }
                            translatePoint = new Point(0, 0).MoveTo(angle, TextBlockHeight / 2 - 2);
                        }

                        var rotateTransform    = new RotateTransform(angle, letters.Width / 2, TextBlockHeight / 2);
                        var translateTransform = new TranslateTransform(translatePoint.X, translatePoint.Y);
                        var transforms         = new TransformGroup();
                        transforms.Children.Add(rotateTransform);
                        transforms.Children.Add(translateTransform);
                        letters.RenderTransform = transforms;

                        canvas.Add(letters, middle.X - letters.Width / 2, middle.Y - TextBlockHeight / 2, 0);
                    }
                }

                Brush vertexBrush           = null;
                Brush vertexBackgroundBrush = null;
                Brush vertexLabelBrush      = null;
                if (constructionMode && highlightedStates.Any(x => states.IndexOf(x) == i))
                {
                    vertexBrush           = HighlightedVertexBrush;
                    vertexBackgroundBrush = HighlightedVertexBackgroundBrush;
                    vertexLabelBrush      = HighlightedVertexLabelBrush;
                }
                else if (evaluationMode)
                {
                    if (currentState == i)
                    {
                        if (evaluationEnded)
                        {
                            vertexBrush           = VertexBrush;
                            vertexBackgroundBrush = WordAcceptedStateBackgroundBrush;
                            vertexLabelBrush      = VertexLabelBrush;
                        }
                        else
                        {
                            vertexBrush           = HighlightedVertexBrush;
                            vertexBackgroundBrush = HighlightedVertexBackgroundBrush;
                            vertexLabelBrush      = HighlightedVertexLabelBrush;
                        }
                    }
                    else if (previousState == i && currentState == -1)
                    {
                        vertexBrush           = VertexBrush;
                        vertexBackgroundBrush = WordRejectedStateBackgroundBrush;
                        vertexLabelBrush      = VertexLabelBrush;
                    }
                    else
                    {
                        vertexBrush           = VertexBrush;
                        vertexBackgroundBrush = VertexBackgroundBrush;
                        vertexLabelBrush      = VertexLabelBrush;
                    }
                }
                else
                {
                    vertexBrush           = VertexBrush;
                    vertexBackgroundBrush = VertexBackgroundBrush;
                    vertexLabelBrush      = VertexLabelBrush;
                }

                DrawState(canvas, vertexBrush, vertexBackgroundBrush, vertexLabelBrush, location,
                          String.Format("q{0}", i), acceptingStates.Any(x => x == states[i]));

                if (location.X > maxX)
                {
                    maxX = location.X;
                }
                if (location.Y > maxY)
                {
                    maxY = location.Y;
                }
            }
            canvas.Width  = maxX + LayoutOffset;
            canvas.Height = maxY + LayoutOffset;
        }
Esempio n. 3
0
        /// <summary>
        /// Derives next expression from the not-derived-expressions queue.
        /// </summary>
        /// <returns>true if any expression was derived during execution of this method</returns>
        private bool DeriveNextExpression()
        {
            if (notDerivedIds.Count == 0)
            {
                return(false);
            }

            var currentId = notDerivedIds[0];
            var current   = equivalentStatesGroups[currentId].Value[0];           // .First(x => x.Key == currentId)

            var alphabet = current.Alphabet;
            int count    = alphabet.Count;

            if (count > 0)
            {
                Thread[]            derivationThreads = new Thread[count];
                RegularExpression[] derivations       = new RegularExpression[count];

                #region obsolete manual parallelization

                /****
                *
                *  int processorsCount = count; // TODO: get total number of logical processing units
                *  Semaphore semaphore = new Semaphore(processorsCount, processorsCount);
                *
                *  // derive in parallel
                *  for (int i = 0; i < count; ++i)
                *  {
                *       Thread t = new Thread(new ParameterizedThreadStart((object obj) =>
                *       {
                *               int n = (int)obj;
                *               semaphore.WaitOne();
                *               derivations[n] = current.Derive(alphabet[n]);
                *               semaphore.Release();
                *       }));
                *       t.Name = "DerivationThread";
                *       t.Priority = ThreadPriority.Lowest;
                *       t.SetApartmentState(ApartmentState.STA);
                *       t.Start(i);
                *       derivationThreads[i] = t;
                *  }
                *
                *  // sync
                *  for (int i = 0; i < count; ++i)
                *       derivationThreads[i].Join();
                *
                ****/

                #endregion

                // derive in parallel
                if (count > 1)
                {
                    Parallel.For(0, count, (int n) =>
                    {
                        derivations[n] = current.Derive(alphabet[n]);
                    });
                }
                else
                {
                    derivations[0] = current.Derive(alphabet[0]);
                }

                // analyze results in sequence
                for (int i = 0; i < count; ++i)
                {
                    var derived = derivations[i];

                    if (derived == null)
                    {
                        continue;
                    }

                    var letter = alphabet[i];

                    var derivedId = equivalentStatesGroups.FindIndex(x => x.Value.Any(y => y.Equals(derived)));
                    if (derivedId >= 0)
                    {
                        var foundTransition = transitions.FindIndex(x => x.Item1 == currentId && x.Item3 == derivedId);
                        if (foundTransition >= 0)
                        {
                            transitions[foundTransition].AddLetter(letter);
                            latestTransitions.Add(transitions[foundTransition]);
                        }
                        else
                        {
                            var mt = new MachineTransition(currentId, letter, derivedId);
                            transitions.Add(mt);
                            latestTransitions.Add(mt);
                        }
                    }
                    else
                    {
                        notLabeled.Add(derived);
                        notOptimizedTransitions.Add(new Tuple <int, string, RegularExpression>(currentId, letter, derived));
                    }
                }
            }

            //foreach (var letter in current.Alphabet)
            //{
            //	//if (states.Any(x => x.IsEqual(current)))
            //	//	continue;
            //}

            notDerivedIds.RemoveAt(0);
            return(true);
        }
Esempio n. 4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="equivalentToExpression"></param>
        private void ManuallyLabelNextExpression(RegularExpression equivalentToExpression)
        {
            RegularExpression labeled = notLabeled[0];
            int labeledId             = -1;

            if (equivalentToExpression == null)
            {
                labeledId = equivalentStatesGroups.Count;
                notLabeled.RemoveAt(0);
                equivalentStatesGroups.Add(new KeyValuePair <int, List <RegularExpression> >(labeledId, new List <RegularExpression>()));
                equivalentStatesGroups[labeledId].Value.Add(labeled);

                latestStates.Add(labeled);

                if (labeled.GeneratesEmptyWord())
                {
                    acceptingStatesIds.Add(labeledId);
                }

                notDerivedIds.Add(labeledId);
            }
            else
            {
                foreach (var group in equivalentStatesGroups)
                {
                    if (!group.Value.Any(x => x.Equals(equivalentToExpression)))
                    {
                        continue;
                    }
                    labeledId = group.Key;
                    break;
                }

                if (labeledId < 0 && labeledId >= equivalentStatesGroups.Count)
                {
                    throw new ArgumentException("must be either null or an expression that is already labeled", "equivalentToExpression");
                }

                equivalentStatesGroups[labeledId].Value.Add(labeled);
            }

            if (notOptimizedTransitions == null || notOptimizedTransitions.Count == 0)
            {
                return;
            }

            var transitionsForOptimization = notOptimizedTransitions.FindAll(x => x.Item3.Equals(labeled));

            transitionsForOptimization.ForEach(x =>
            {
                var foundTransition = transitions.FindIndex(y => y.Item1 == x.Item1 && y.Item3 == labeledId);
                if (foundTransition >= 0)
                {
                    // this can happen if more than one transition is optimized in this step
                    transitions[foundTransition].AddLetter(x.Item2);
                }
                else
                {
                    MachineTransition transition = new MachineTransition(x.Item1, x.Item2, labeledId);
                    transitions.Add(transition);
                    latestTransitions.Add(transition);
                }
            });
            transitionsForOptimization.ForEach(x => notOptimizedTransitions.Remove(x));
        }