Beispiel #1
0
        /// <summary>
        ///     Creates a surface for the value provided expression
        /// </summary>
        /// <param name="namable"></param>
        /// <param name="xParam"></param>
        /// <param name="yParam"></param>
        /// <returns></returns>
        public static Surface createSurface(IValue namable, Parameter xParam, Parameter yParam)
        {
            Surface retVal = null;

            Function function = namable as Function;
            IValue   value    = namable as IValue;

            if (function != null)
            {
                if (function.Surface != null)
                {
                    retVal = function.Surface;
                }
                else if (function.Graph != null)
                {
                    retVal = new Surface(xParam, yParam);

                    // Extend the graph to a Surface
                    if (xParam != null)
                    {
                        foreach (Graph.Segment segment in function.Graph.Segments)
                        {
                            Graph graph = new Graph();
                            graph.AddSegment(new Graph.Segment(0, double.MaxValue, segment.Expression));
                            retVal.AddSegment(new Segment(segment.Start, segment.End, graph));
                        }
                    }
                    else if (yParam != null)
                    {
                        retVal.AddSegment(new Segment(0, double.MaxValue, function.Graph));
                    }
                }
                else
                {
                    throw new Exception("Cannot create graph for function");
                }
            }
            else if (value != null)
            {
                if (value != null)
                {
                    retVal = createSurface(Function.GetDoubleValue(value), xParam, yParam);
                }
            }
            else
            {
                throw new Exception("Cannot create surface for value " + namable);
            }

            return(retVal);
        }
Beispiel #2
0
        /// <summary>
        ///     Creates a surface for an Ivalue provided
        /// </summary>
        /// <param name="xParam"></param>
        /// <param name="yParam"></param>
        /// <param name="iValue"></param>
        /// <param name="explain"></param>
        /// <returns></returns>
        public static Surface createSurface(Parameter xParam, Parameter yParam, IValue iValue, ExplanationPart explain)
        {
            Surface retVal = null;

            if (retVal == null)
            {
                Function function = iValue as Function;
                if (function != null)
                {
                    retVal = function.Surface;
                    if (retVal == null)
                    {
                        Graph graph = function.Graph;
                        if (graph != null)
                        {
                            retVal = new Surface(xParam, yParam);
                            Segment segment = new Segment(0, double.MaxValue, graph);
                            retVal.AddSegment(segment);
                        }
                    }
                }
            }

            if (retVal == null)
            {
                retVal = new Surface(xParam, yParam);
                Segment segment = new Segment(0, double.MaxValue, Graph.createGraph(iValue, yParam, explain));
                retVal.AddSegment(segment);
            }

            return(retVal);
        }
        /// <summary>
        /// Extends the graph to a graph where the ranges are expressed on the Y axis
        /// </summary>
        /// <returns></returns>
        public Surface ToSurfaceY()
        {
            Surface retVal = new Surface(null, null);

            retVal.AddSegment(new Surface.Segment(0, double.MaxValue, this));

            return(retVal);
        }
Beispiel #4
0
        /// <summary>
        ///     Creates a surface for a single constant value
        /// </summary>
        /// <param name="value"></param>
        /// <param name="xParam"></param>
        /// <param name="yParam"></param>
        /// <returns></returns>
        public static Surface createSurface(double value, Parameter xParam, Parameter yParam)
        {
            Surface retVal = new Surface(xParam, yParam);

            Segment segment = new Segment(0, double.MaxValue, Graph.createGraph(value));

            retVal.AddSegment(segment);

            return(retVal);
        }
        /// <summary>
        /// Extends the graph to a graph where the ranges are expressed on the X axis
        /// </summary>
        /// <returns></returns>
        public Surface ToSurfaceX()
        {
            Surface retVal = new Surface(null, null);

            foreach (Graph.Segment segment in Segments)
            {
                Graph graph = new Graph();
                graph.addSegment(new Segment(0, double.MaxValue, new Segment.Curve(0, segment.Expression.v0, 0)));
                Surface.Segment newSegment = new Surface.Segment(segment.Start, segment.End, graph);

                retVal.AddSegment(newSegment);
            }

            return(retVal);
        }
        /// <summary>
        /// Reduces the X axis of the surface according to the preconditions of this case
        /// </summary>
        /// <param name="context">The context used to reduce the surface</param>
        /// <param name="cas">The case used to reduce the surface</param>
        /// <param name="surface">The surface to reduce</param>
        /// <param name="parameter">The parameter for which the reduction has been performed</param>
        /// <returns>The reduced surface</returns>
        private Surface ReduceSurface(Interpreter.InterpretationContext context, Case cas, Surface surface, out Parameter parameter)
        {
            Surface retVal;

            // Evaluate the axis
            parameter = null;
            foreach (Rules.PreCondition preCondition in cas.PreConditions)
            {
                List <Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter);
                if (boundaries.Count != 0 && !fullRange(boundaries))
                {
                    if (parameter != surface.YParameter)
                    {
                        parameter = surface.XParameter;
                    }
                    else
                    {
                        throw new Exception("Cannot reduce a graph on both X axis and Y axis on the same time (1)");
                    }
                }
                else
                {
                    boundaries = EvaluateBoundaries(context, preCondition, surface.YParameter);
                    if (boundaries.Count != 0 && !fullRange(boundaries))
                    {
                        if (parameter != surface.XParameter)
                        {
                            parameter = surface.YParameter;
                        }
                        else
                        {
                            throw new Exception("Cannot reduce a graph on both X axis and Y axis on the same time (2)");
                        }
                    }
                }
            }

            if (parameter == surface.XParameter)
            {
                // Reduce the surface on the X axis
                retVal = new Surface(surface.XParameter, surface.YParameter);
                foreach (Surface.Segment segment in surface.Segments)
                {
                    retVal.AddSegment(new Surface.Segment(segment));
                }

                // Reduces the segments according to this preconditions
                foreach (Rules.PreCondition preCondition in cas.PreConditions)
                {
                    List <Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter);
                    retVal.Reduce(boundaries);
                }
            }
            else if (parameter == surface.YParameter)
            {
                // Reduce the surface, for all segments of the X axis, on the Y axis
                retVal = new Surface(surface.XParameter, surface.YParameter);
                foreach (Surface.Segment segment in surface.Segments)
                {
                    // Reduces the segments according to this preconditions
                    foreach (Rules.PreCondition preCondition in cas.PreConditions)
                    {
                        List <Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.YParameter);
                        segment.Graph.Reduce(boundaries);
                    }
                    if (!segment.Empty())
                    {
                        retVal.AddSegment(segment);
                    }
                }
            }
            else
            {
                retVal = surface;
            }

            return(retVal);
        }
        /// <summary>
        /// Provides the surface of this function if it has been statically defined
        /// </summary>
        /// <param name="context">the context used to create the graph</param>
        /// <param name="Xparameter">The parameter used for the X axis</param>
        /// <param name="Yparameter">The parameter used for the Y axis</param>
        /// <returns></returns>
        public virtual Surface createSurfaceForParameters(Interpreter.InterpretationContext context, Parameter Xparameter, Parameter Yparameter)
        {
            Surface retVal = Surface;

            if (retVal == null)
            {
                if (Xparameter != null)
                {
                    if (Yparameter != null)
                    {
                        if (Cases.Count > 0)
                        {
                            retVal = new Surface(Xparameter, Yparameter);

                            foreach (Case cas in Cases)
                            {
                                if (PreconditionSatisfied(context, cas, Xparameter, Yparameter))
                                {
                                    Surface surface = cas.Expression.createSurface(context, Xparameter, Yparameter);
                                    if (surface != null)
                                    {
                                        Parameter parameter = null;
                                        surface = ReduceSurface(context, cas, surface, out parameter);

                                        if (parameter == null || parameter == surface.XParameter)
                                        {
                                            retVal.MergeX(surface);
                                        }
                                        else
                                        {
                                            retVal = Surface.MergeY(retVal, surface);
                                        }
                                    }
                                    else
                                    {
                                        AddError("Cannot create surface for expression " + cas.ExpressionText);
                                        retVal = null;
                                        break;
                                    }
                                }
                            }
                        }
                        else if (Graph != null)
                        {
                            // The function is defined by a graph
                            // Extend it to a surface
                            // TODO: Check the right parameter
                            retVal            = Graph.ToSurfaceX();
                            retVal.XParameter = Xparameter;
                            retVal.YParameter = Yparameter;
                        }
                        else
                        {
                            AddError("cannot create surface for function " + Name + " with given parameters");
                        }
                    }
                    else
                    {
                        // Function with 1 parameter that ranges over the Xaxis
                        retVal = new Surface(Xparameter, Yparameter);
                        Functions.Graph graph = createGraphForParameter(context, Xparameter);
                        foreach (Graph.Segment segment in graph.Segments)
                        {
                            Graph           newGraph   = Graph.createGraph(segment.Expression.v0);
                            Surface.Segment newSegment = new Surface.Segment(segment.Start, segment.End, newGraph);
                            retVal.AddSegment(newSegment);
                        }
                    }
                }
                else if (Yparameter != null)
                {
                    // TODO : Remove check code
                    if ((Yparameter.Enclosing != this))
                    {
                        System.Diagnostics.Debugger.Break();
                    }

                    // Function with 1 parameter that ranges over the Yaxis
                    retVal = new Surface(Xparameter, Yparameter);
                    Graph           graph   = createGraphForParameter(context, Yparameter);
                    Surface.Segment segment = new Functions.Surface.Segment(0, double.MaxValue, graph);
                    retVal.AddSegment(segment);
                }
                else
                {
                    AddError("Invalid parameters for surface creation");
                }
            }

            retVal.XParameter = Xparameter;
            retVal.YParameter = Yparameter;

            return(retVal);
        }
Beispiel #8
0
        /// <summary>
        ///     Performs an operation based on two surfaces.
        /// </summary>
        /// <param name="first">the first surface</param>
        /// <param name="second">the second surface</param>
        /// <param name="operation">the operation to perform on these graphs</param>
        /// <returns>the new graph</returns>
        private static Surface CombineTwoSurfaces(Surface first, Surface second, Segment.Op operation)
        {
            Surface retVal = new Surface(first.XParameter, first.YParameter);

            if (retVal.XParameter == null)
            {
                retVal.XParameter = second.XParameter;
            }
            if (retVal.YParameter == null)
            {
                retVal.YParameter = second.YParameter;
            }

            int i = 0;
            int j = 0;

            double start = 0;

            while (i < first.Segments.Count && j < second.Segments.Count)
            {
                ISurfaceSegment segment_i = first.Segments[i];
                ISurfaceSegment segment_j = second.Segments[j];

                if (segment_i.Start != segment_j.Start && start <= segment_i.Start && start <= segment_j.Start)
                {
                    if (segment_i.Start < segment_j.Start)
                    {
                        // First consider segment_i where no segment_j is available
                        if (segment_i.End <= segment_j.Start)
                        {
                            // No overlap
                            IGraph val = operation(segment_i.Graph, null);
                            retVal.AddSegment(new Segment(start, segment_i.End, val));
                            start = segment_i.End;
                            i     = i + 1;
                        }
                        else
                        {
                            // Overlap between segment_i and segment_j, segment_i is before segment_j
                            IGraph val = operation(segment_i.Graph, null);
                            retVal.AddSegment(new Segment(start, segment_j.Start, val));
                            start = segment_j.Start;
                        }
                    }
                    else
                    {
                        // First consider segment_j where no segment_i is available
                        if (segment_j.End <= segment_i.Start)
                        {
                            // No overlap
                            IGraph val = operation(segment_j.Graph, null);
                            retVal.AddSegment(new Segment(start, segment_j.End, val));
                            start = segment_j.End;
                            j     = j + 1;
                        }
                        else
                        {
                            // Overlap between segment_i and segment_j, segment_j is before segment_i
                            IGraph val = operation(segment_j.Graph, null);
                            retVal.AddSegment(new Segment(start, segment_i.Start, val));
                            start = segment_i.Start;
                        }
                    }
                }
                else
                {
                    double end;
                    if (segment_i.End < segment_j.End)
                    {
                        end = segment_i.End;
                        i   = i + 1;
                    }
                    else
                    {
                        if (segment_i.End == segment_j.End)
                        {
                            i = i + 1;
                        }
                        end = segment_j.End;
                        j   = j + 1;
                    }
                    IGraph val = operation(segment_i.Graph, segment_j.Graph);
                    retVal.AddSegment(new Segment(start, end, val));
                    start = end;
                }
            }

            while (i < first.Segments.Count)
            {
                ISurfaceSegment segment_i = first.Segments[i];

                IGraph val = operation(segment_i.Graph, null);
                retVal.AddSegment(new Segment(start, segment_i.End, val));

                start = segment_i.End;
                i     = i + 1;
            }

            while (j < second.Segments.Count)
            {
                ISurfaceSegment segment_j = second.Segments[j];

                IGraph val = operation(null, segment_j.Graph);
                retVal.AddSegment(new Segment(start, segment_j.End, val));

                start = segment_j.End;
                j     = j + 1;
            }

            retVal.MergeDuplicates();

            return(retVal);
        }