Esempio n. 1
0
        /// <summary>
        ///     Creates the surface associated to the value provided
        /// </summary>
        /// <param name="context"></param>
        /// <param name="value"></param>
        /// <param name="explain"></param>
        /// <returns></returns>
        protected Surface createSurfaceForValue(InterpretationContext context, IValue value, ExplanationPart explain)
        {
            Surface retVal = null;

            Function function = value as Function;

            if (function != null)
            {
                retVal = function.CreateSurface(context, explain);
            }
            else
            {
                DoubleValue val   = value as DoubleValue;
                Graph       graph = new Graph();
                graph.AddSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, val.Val, 0)));
                retVal = new Surface(null, null);
                retVal.AddSegment(new Surface.Segment(0, double.MaxValue, graph));
            }

            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>
        /// <param name="explain"></param>
        /// <returns></returns>
        public virtual Surface CreateSurfaceForParameters(InterpretationContext context, Parameter xParameter,
            Parameter yParameter, ExplanationPart explain)
        {
            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, explain))
                                {
                                    Surface surface = cas.Expression.CreateSurface(context, xParameter, yParameter,
                                        explain);
                                    if (surface != null)
                                    {
                                        Parameter parameter = null;
                                        surface = ReduceSurface(context, cas, surface, out parameter, explain);

                                        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);
                        Graph graph = CreateGraphForParameter(context, xParameter, explain);
                        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)
                {
                    // Function with 1 parameter that ranges over the Yaxis
                    retVal = new Surface(xParameter, yParameter);
                    Graph graph = CreateGraphForParameter(context, yParameter, explain);
                    Surface.Segment segment = new Surface.Segment(0, double.MaxValue, graph);
                    retVal.AddSegment(segment);
                }
                else
                {
                    AddError("Invalid parameters for surface creation");
                }
            }

            if (retVal != null)
            {
                retVal.XParameter = xParameter;
                retVal.YParameter = yParameter;
            }

            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>
        /// <param name="explain"></param>
        /// <returns>The reduced surface</returns>
        private Surface ReduceSurface(InterpretationContext context, Case cas, Surface surface, out Parameter parameter,
            ExplanationPart explain)
        {
            Surface retVal;

            // Evaluate the axis
            parameter = null;
            foreach (PreCondition preCondition in cas.PreConditions)
            {
                List<ISegment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter, explain);
                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, explain);
                    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 (ISurfaceSegment segment in surface.Segments)
                {
                    retVal.AddSegment(new Surface.Segment(segment));
                }

                // Reduces the segments according to this preconditions
                foreach (PreCondition preCondition in cas.PreConditions)
                {
                    List<ISegment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter,
                        explain);
                    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 (PreCondition preCondition in cas.PreConditions)
                    {
                        List<ISegment> boundaries = EvaluateBoundaries(context, preCondition, surface.YParameter,
                            explain);
                        segment.Graph.Reduce(boundaries);
                    }
                    if (!segment.Empty())
                    {
                        retVal.AddSegment(segment);
                    }
                }
            }
            else
            {
                retVal = surface;
            }

            return retVal;
        }
        /// <summary>
        ///     Creates the surface associated to the value provided
        /// </summary>
        /// <param name="context"></param>
        /// <param name="value"></param>
        /// <param name="explain"></param>
        /// <returns></returns>
        protected Surface createSurfaceForValue(InterpretationContext context, IValue value, ExplanationPart explain)
        {
            Surface retVal = null;

            Function function = value as Function;
            if (function != null)
            {
                retVal = function.createSurface(context, explain);
            }
            else
            {
                DoubleValue val = value as DoubleValue;
                Graph graph = new Graph();
                graph.AddSegment(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve(0, val.Val, 0)));
                retVal = new Surface(null, null);
                retVal.AddSegment(new Surface.Segment(0, double.MaxValue, graph));
            }

            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;
        }