예제 #1
0
    def get_minmax_data(self, start=None, end=None):
        """
        return the min and max of x and y for the graph of `self`
        and the parameter between `start` and `end`

        INPUT:

        - ``start,end`` - interval on which we are considering the function.

        OUTPUT:

        A dictionary
        """
        x_list = [
            numerical_approx(P.x, prec=30)
            for P in self.representative_points()
        ]
        y_list = [
            numerical_approx(P.y, prec=30)
            for P in self.representative_points()
        ]
        d = {}
        d['xmin'] = min(x_list)
        d['xmax'] = max(x_list)
        d['ymin'] = min(y_list)
        d['ymax'] = max(y_list)
        return d
예제 #2
0
def are_almost_equal(a, b, epsilon=0.0001):
    # \brief Says if `a` and `b` are equal up to epsilon
    aN = numerical_approx(a)
    bN = numerical_approx(b)
    if abs(aN - bN) < 0.0001:  # epsilon
        return True
    return False
예제 #3
0
def check_too_large(obj,pspict=None):
    try:
        bb=obj.bounding_box(pspict)
        mx=bb.xmin
        my=bb.ymin
        Mx=bb.xmax
        My=bb.ymax

    except AttributeError:
        print "Object {0} has no method bounding_box.".format(obj)
        mx=obj.mx
        my=obj.my
        Mx=obj.Mx
        My=obj.My
    if pspict:
        from Exceptions import TooLargeBBException
        # In some circumstances, the comparison
        # mx<pspict.mx_acceptable_BB
        # provokes a MemoryError.
        n_Mx=numerical_approx(Mx)
        n_mx=numerical_approx(mx)
        n_My=numerical_approx(My)
        n_my=numerical_approx(my)
        if n_mx<pspict.mx_acceptable_BB :
            raise TooLargeBBException(obj=obj,faulty="xmin",acceptable=pspict.mx_acceptable_BB,got=n_mx)
        if n_my<pspict.my_acceptable_BB :
            raise TooLargeBBException(obj=obj,faulty="ymin",acceptable=pspict.my_acceptable_BB,got=n_my)
        if n_Mx>pspict.Mx_acceptable_BB :
            raise TooLargeBBException(obj=obj,faulty="xmax",acceptable=pspict.Mx_acceptable_BB,got=n_Mx)
        if n_My>pspict.My_acceptable_BB :
            raise TooLargeBBException(obj=obj,faulty="ymax",acceptable=pspict.My_acceptable_BB,got=n_My)
예제 #4
0
    def equation(self):
        """
        return the equation of the line under the form
        x + by + c = 0

        Coefficients 'b' and 'c' are numerical approximations. 
        See Utilities.Intersection

        EXAMPLES::

            sage: from yanntricks import *
            sage: Segment(Point(0,0),Point(1,1)).equation
            x - y == 0
            sage: Segment(Point(1,0),Point(0,1)).equation
            x + y - 1 == 0
        """
        if self.is_vertical:
            self.coefs = [1, 0, -self.I.x]
        if self.is_horizontal:
            self.coefs = [0, 1, -self.I.y]
        if not (self.is_vertical or self.is_horizontal):
            self.coefs = [1, -1/self.slope, self.independent/self.slope]
        x, y = var('x,y')
        Ix = numerical_approx(self.I.x)
        Iy = numerical_approx(self.I.y)
        Fx = numerical_approx(self.F.x)
        Fy = numerical_approx(self.F.y)
        coefs = [numerical_approx(s) for s in self.coefs]
        return coefs[0]*x+coefs[1]*y+coefs[2] == 0
예제 #5
0
def assert_almost_equal(e1, e2, epsilon=0.0001, failure_message=""):
    """
    Raise a FailedAssertException if the two expressions 'e1' and 'e2' 
    are not equal up to 'epsilon'

    First try to use
    ```
    e1.is_almost_equal(e2,epsilon)
    ```
    because some objects in 'yanntricks' have that method.

    If `e1` has not that method :
    - assume that `e1` and `e2` are numerical
    - compute a numerical approximation
    - fail if the absolute value of the difference
        is larger than `epsilon`
    """
    if hasattr(e1, 'is_almost_equal'):
        if not e1.is_almost_equal(e2, epsilon):
            from yanntricks.testing.unit_tests.Exceptions import FailedAssertException
            raise FailedAssertException(
                str(e1) + " is not equal to " + str(e2) + " up to " +
                str(epsilon))
        return True

    v1 = numerical_approx(e1)
    v2 = numerical_approx(e2)
    d = abs(v1 - v2)
    if not d < epsilon:
        from yanntricks.testing.unit_tests.Exceptions import FailedAssertException
        raise FailedAssertException(
            str(e1) + " is not equal to " + str(e2) + " up to " + str(epsilon))
def ERPMooZibfNOiU():
    pspict, fig = SinglePicture("ERPMooZibfNOiU")
    pspict.dilatation(1)

    t0 = 40
    a = 2.3
    b = 1.3
    O = Point(0, 0)
    lp = Segment(O, Circle(O, 5).getPoint(t0))
    P = lp.midpoint()

    fun = lambda t: Point(a * cos(t), b * sin(t)).rotation(t0) + P
    decal = fun(pi / 2) - P
    Gamma = NonAnalyticPointParametricCurve(lambda x: fun(x) + decal, 0,
                                            2 * pi)
    Gamma.parameters.plotpoints = 20

    pt = Gamma(3 * pi / 2 - 0.15)
    xx = pt.x
    v = AffineVector(P, pt).normalize(2)
    v.parameters.color = "blue"
    pspict.DrawGraphs(v)
    F = v.F
    Fx = F.x

    a = 7.73542889062775 * cos(11 / 9 * pi +
                               1.30951587282752) - 7.55775391156456 * cos(
                                   5 / 18 * pi) + 2.5 * cos(2 / 9 * pi)
    print(numerical_approx(a))
    print(numerical_approx(a, digits=5))

    fig.no_figure()
    fig.conclude()
    fig.write_the_file()
예제 #7
0
def distance_sq(P,Q,numerical=False):
    if not numerical :
        return (P.x-Q.x)**2+(P.y-Q.y)**2
    Px=numerical_approx(P.x)
    Qx=numerical_approx(Q.x)
    Qy=numerical_approx(Q.y)
    Py=numerical_approx(P.y)
    return (Px-Qx)**2+(Py-Qy)**2
예제 #8
0
 def points_list(self):
     l = []
     import numpy
     ai = numerical_approx(self.angleI)
     af = numerical_approx(self.angleF)
     angles = numpy.linspace(ai, af, self.linear_plotpoints)
     for a in angles:
         l.append(self.get_point(a))
     return l
예제 #9
0
def PointToPolaire(P=None,x=None,y=None,origin=None,numerical=True):
    """
    Return the polar coordinates of a point.

    INPUT:
    - ``P`` - (default=None) a point
    - ``x,y`` - (defautl=None) the coordinates of the points

    EXAMPLES:

    You can provide a point::

        sage: from phystricks import Point
        sage: from phystricks.SmallComputations import *
        sage: print PointToPolaire(Point(1,1))
        PolarCoordinates, r=sqrt(2),degree=45,radian=1/4*pi

    or directly the coordinates ::

        sage: print PointToPolaire(x=1,y=1)
        PolarCoordinates, r=sqrt(2),degree=45,radian=1/4*pi
    """
    from Numerical import numerical_is_negative
    if origin:
        Ox=origin.x
        Oy=origin.y
    if not origin:
        Ox=0
        Oy=0
    if P:
        Px=P.x
        Py=P.y
    else :
        Px=x
        Py=y
    Qx=Px-Ox
    Qy=Py-Oy
    if numerical:
        Qx=numerical_approx(Qx)
        Qy=numerical_approx(Qy)
    r=sqrt(  Qx**2+Qy**2 )
    if abs(Qx)<0.001:   # epsilon
        if Qy>0:
            radian=pi/2
        else :
            radian=3*pi/2
    else :
        radian=arctan(Qy/Qx)
    if Qx<0:
        if Qy>0:
            radian=radian+pi
        if Qy<=0:
            radian=pi+radian
    # Only positive values (February 11, 2015)
    if numerical_is_negative(radian):
        radian=radian+2*pi
    return PolarCoordinates(r,value_radian=radian)
예제 #10
0
def numerical_max(x, y, epsilon=None):
    # Same as `numerical_min` with ad-hoc changes
    nx = numerical_approx(x)
    ny = numerical_approx(y)

    if epsilon is not None:
        if abs(nx, ny) > epsilon:
            raise ValueError

    return max(nx, ny)
예제 #11
0
    def is_almost_orthogonal(self, other, epsilon=0.001):
        if self.is_vertical:
            return other.is_horizontal
        if self.is_horizontal:
            return other.is_vertical

        s_slope = numerical_approx(self.slope)
        o_slope = numerical_approx(other.slope)

        if abs(s_slope + 1 / o_slope) < epsilon:
            return True
        return False
예제 #12
0
def test_imaginary_part(z,epsilon=0.0001):
    """
    Return a tuple '(isreal,w)' where 'isreal' is a boolean saying if 'z' is real (in the sense that it is real and does not contain 'I' in its string representation) and 'w' is 'z' when the imaginary part is larger than epsilon and an 'numerical_approx' of 'z' when its imaginary part is smaller than 'epsilon'

    With the collateral effect that it returns a numerical approximation.
    """
    if is_real(z) and "I" not in str(z):
        return True,z
    k=numerical_approx(z)
    if is_real(k):
        return True,k
    if abs( k.imag_part() )<epsilon:
        return True,numerical_approx( z.real_part() )
    print("It seems that an imaginary part is not so small.")
    return False,z
예제 #13
0
def psi(x, k, prec):
    if len(x) == 0 or (x[0]**k) > 10**prec:
        return sg.Rational(0.0)

    x_power = x.apply_map(lambda y: y**k)
    return sg.sum(
        x_power.apply_map(lambda y: sg.numerical_approx(1 / y, digits=prec)))
예제 #14
0
def distance_sq(P, Q, numerical=False):
    """
    Return the squared distance between P and Q.

    @param {bool} `numerical`
        If True, use numerical approximations and return a
        numerical approximation.
    """

    if not numerical:
        return (P.x - Q.x)**2 + (P.y - Q.y)**2
    Px = numerical_approx(P.x)
    Qx = numerical_approx(Q.x)
    Qy = numerical_approx(Q.y)
    Py = numerical_approx(P.y)
    return (Px - Qx)**2 + (Py - Qy)**2
예제 #15
0
    def __init__(self, f, mx, Mx):
        ObjectGraph.__init__(self, self)
        self.f = f
        self.mx = mx
        self.Mx = Mx
        self.I = self.get_point(mx)
        self.F = self.get_point(Mx)

        self.parameters.plotpoints = 100

        from numpy import linspace
        if self.mx is not None and self.Mx is not None:
            self.drawpoints = linspace(numerical_approx(self.mx), numerical_approx(
                self.Mx), self.parameters.plotpoints, endpoint=True)
        self._curve = None
        self.mode = None
예제 #16
0
    def LaTeX_lines(self):
        """
        Return the lines to be included in your LaTeX file.
        """
        a = []
        a.append(self.comments())
        if self.figure_environment:
            a.append(
                "The result is on figure \\ref{"+self.name+"}. % From file "+self.script_filename)
            # The pseudo_caption is changed to the function name later.
            a.append("\\newcommand{"+self.caption+"}{"+pseudo_caption+"}")
            a.append("\\input{%s}" % (self.filename.from_main()))
        else:
            text = r"""\\begin{center}
   INCLUSION
\end{center}""".replace("INCLUSION", "\\input{%s}" % (self.filename.from_main()))
            if len(self.record_pspicture) == 1:
                pspict = self.record_pspicture[0]
                # By the way, this is a reason why we cannot do this before to have
                visual_xsize = pspict.visual_xsize()
                # concluded the picture.
                text = text.replace("WIDTH", str(
                    numerical_approx(visual_xsize, digits=3))+"cm")
            a.append(text)
        text = "\n".join(a)
        return text
예제 #17
0
def number_to_string(x,digits):
    from Numerical import is_almost_zero
    nx=numerical_approx(x)

    # Avoid something like "0.125547e-6" (LaTeX will not accept).
    if is_almost_zero(nx,0.001):
        if digits==1:
            return "0"
        return "0."+"0"*(digits-1)

    sx=str(nx)

    # in a definitive release, this test can be removed.
    # this is only for my culture; I guess that it never happens
    if "." not in sx:
        print(x)
        print(sx)
        raise

    sx=sx+"0"*(digits+1) # be sure not to lack digits
    if nx<0:
        sx=sx[0:digits+2]    # +1 for the decimal dot, +1 for the minus
    else :
        sx=sx[0:digits+1]    
    if sx.endswith("."):
        sx=sx[:-1]

    return sx
    def __call__(self, xe, numerical=False):
        """
        return the value of the function at given point

        INPUT:
        - ``xe`` - a number. The point at which we want to evaluate the function
        - ``numerical`` (boolean, default=False) If True, return a numerical_approximation

        EXAMPLES::

            sage: from yanntricks import *
            sage: x=var('x')
            sage: f=phyFunction(cos(x))
            sage: f(1)
            cos(1)
            sage: f(1,numerical=True)
            0.540302305868140
        """
        if numerical:
            return numerical_approx(self.sageFast(xe))
        else:
            try:
                return self.sage(x=xe)
            except TypeError:  # Happens when one has a distribution function
                try:
                    return self.sage(xe)
                except TypeError:
                    print("ooMHAQooMbDokI")
                    print(self, type(self))
                    print(xe, type(xe))
                    raise
예제 #19
0
def inner_product(v, w, numerical=False):
    """
    Return the inner product of vectors `v` and `w`
    @param v a vector
    @param w a vector
    @param numerical a boolean

    If `numerical` is true, the computations are done on
    numerical approximations of the coordinates.
    """
    if numerical:
        if not v.I.is_almost_equal(w.I):
            raise OperationNotPermitedException(
                "I only compute inner products "
                "of vectors based on the same point.")
    if not numerical:
        if v.I != w.I:
            raise OperationNotPermitedException(
                "I only compute inner products "
                "of vectors based on the same point.")

    s = v.Dx * w.Dx + v.Dy * w.Dy
    if numerical:
        return numerical_approx(s)
    return s
예제 #20
0
    def __init__(self, a, b):
        self.x = SR(a)
        self.y = SR(b)
        ObjectGraph.__init__(self, self)
        self.point = self.obj
        self.add_option("PointSymbol=*")
        self._advised_mark_angle = None

        try:
            ax = abs(numerical_approx(self.x))
            if ax < 0.00001 and ax > 0:
                self.x = 0
            ay = abs(numerical_approx(self.y))
            if ay < 0.00001 and ay > 0:
                self.y = 0
        except TypeError:
            pass
예제 #21
0
def roundingMinMax(d):
    """
    From a dictionary of "xmin,..." return the dictionary of three-digit rounded values
    """
    new = {}
    for p in ["xmax", "xmin", "ymax", "ymin"]:
        s = numerical_approx(d[p], digits=3)
        new[p] = s
    return new
예제 #22
0
def extrapolate(matrix, Psi, prec=None):
    v = Psi[1][-1, :]
    B = create_B(matrix)
    a = sum(sum(Psi[1]))
    b = sum(sum(B*v))
    if prec:
        return sg.numerical_approx(a + b, digits=prec)
    else:
        return a + b
예제 #23
0
    def equation(self, numerical=False):
        """
        Return the equation of `self`.

        OUTPUT:

        an equation.

        EXAMPLES::

            sage: from yanntricks import *
            sage: circle=Circle(Point(0,0),1)
            sage: circle.equation()
            x^2 + y^2 - 1 == 0

        ::

            sage: circle=CircleOA(Point(-1,-1),Point(0,0))
            sage: circle.equation()
            (x + 1)^2 + (y + 1)^2 - 2 == 0

        If 'numerical' is True, return numerical approximations of the coefficients.
        """
        if numerical == True and self._numerical_equation is not None:
            return self._numerical_equation
        if numerical == False and self._equation is not None:
            return self._equation

        x, y = var('x,y')
        if not self.visual:
            cx = self.center.x
            cy = self.center.y
            cr = self.radius
            self._equation = (x - cx)**2 + (y - cy)**2 - cr**2 == 0
            if not numerical:
                return self._equation
            if numerical:
                cx = numerical_approx(cx)
                cy = numerical_approx(cy)
                cr = numerical_approx(cr)
                self._numerical_equation = (x - cx)**2 + (y -
                                                          cy)**2 - cr**2 == 0
                return self._numerical_equation

        Rx = self.radius / self.pspict.xunit
        Ry = self.radius / self.pspict.yunit

        if numerical == False:
            self._equation = (x-self.center.x)**2/Rx**2 + \
                (y-self.center.y)**2/Ry**2-1 == 0
            return self._equation
        if numerical == True:
            Rx = numerical_approx(Rx)
            Ry = numerical_approx(Ry)
            cx = numerical_approx(self.center.x)
            cy = numerical_approx(self.center.y)
            self._numerical_equation = (x - cx)**2 / Rx**2 + (
                y - cy)**2 / Ry**2 - 1 == 0
            return self._numerical_equation
예제 #24
0
def point_to_box_intersection(P,box,pspict=None):
    from phystricks.src.Utilities import distance_sq
    A=Point(box.xmin,box.ymin)
    B=Point(box.xmax,box.ymin)
    C=Point(box.xmax,box.ymax)
    D=Point(box.xmin,box.ymax)
    # n'écrivez pas ça au tableau quand un inspecteur est dans la salle :
    center=(A+B+C+D)/4
    line=Segment(P,center)

    edges=[Segment(A,B),Segment(B,C),Segment(C,D),Segment(D,A)]
    inter=[]
    for ed in edges:
        c=Intersection(line,ed)
        if len(c)>0:
            S=c[0]

            # We deal with the case in which the line travers the corner.
            # In this case, the line passes trough the other one.
            if S==A:
                inter=[A,C]
            if S==B:
                inter=[B,D]
            if S==C:
                inter=[A,C]
            if S==D:
                inter=[B,D]
            # The last two tests are to know if S lies between ed.I and ed.F
            # We use numerical approximations in order to avoid some 
            # OverflowError: Python int too large to convert to C long
            elif numerical_approx( (S.x-ed.I.x)*(S.x-ed.F.x) )<0:
                inter.append(S)
            elif numerical_approx( (S.y-ed.I.y)*(S.y-ed.F.y) )<0:
                inter.append(S)

    if len(inter)==2:
        inter.sort(key=lambda Q:distance_sq(Q,P,numerical=True))

    if pspict:
        for i,S in enumerate(inter):
            S.put_mark(0.2,angle=None,added_angle=0,text=str(i),pspict=pspict)
        pspict.DrawGraphs(inter,line,center,box)

    return inter
예제 #25
0
    def visual_angleIF(self, pspict):
        from yanntricks.src.point import Point
        from yanntricks.src.AngleMeasure import AngleMeasure
        aI1 = visual_polar_coordinates(
            Point(cos(self.angleI.radian), sin(self.angleI.radian)),
            pspict).measure
        aF1 = visual_polar_coordinates(
            Point(cos(self.angleF.radian), sin(self.angleF.radian)),
            pspict).measure

        a = numerical_approx(aI1.degree)
        b = numerical_approx(aF1.degree)
        if a > b:
            a = a - 360
            aI2 = AngleMeasure(value_degree=a)
        else:
            aI2 = aI1
        aF2 = aF1
        return aI2, aF2
예제 #26
0
def numerical_min(x, y, epsilon=None):
    ##
    # \brief return the minimum of `x` and `y`
    #
    # Compute numerical approximations of `x` and `y` and return the min
    #
    # If `epsilon` is given, raise an exception if the difference is
    # smaller than `epsilon`.
    #
    #    The reason is that Sage cannot always determine the min or the max of
    #    expressions like ```1000``` of type `int` and ```cos(0.0823552493237255*pi)```  of type `sage.symbolic.expression.Expression`
    nx = numerical_approx(x)
    ny = numerical_approx(y)

    if epsilon is not None:
        if abs(nx, ny) > epsilon:
            raise ValueError

    return min(nx, ny)
    def solve_one_var(self, eqs, var):
        """
        Solve the equations with respect to the given variable

        Returns a list of numerical values.
        """
        liste = solve(eqs, var, explicit_solutions=True)
        a = []
        for soluce in liste:
            a.append(numerical_approx(soluce.rhs()))
        return a
예제 #28
0
    def is_almost_equal(self, other, epsilon=0.0001):
        ##
        #   return true if `self` and `other` have coordinates difference
        #   lower than `epsilon`
        #
        from yanntricks.src.NoMathUtilities import logging

        if not isinstance(other, Point):
            logging("We are comparing " + type(self) + " with " + type(other) +
                    ". We continue, but this is strange.")

        sx = numerical_approx(self.x)
        sy = numerical_approx(self.y)
        ox = numerical_approx(other.x)
        oy = numerical_approx(other.y)

        if abs(sx - ox) > epsilon:
            return False
        if abs(sy - oy) > epsilon:
            return False
        return True
예제 #29
0
    def length(self):
        """
        return (a numerical approximation of) the length of the segment

        EXAMPLES::

            sage: from phystricks import *
            sage: Segment(Point(1,1),Point(2,2)).length
            sqrt(2)

        """
        return numerical_approx(self.exact_length)
예제 #30
0
    def is_almost_orthogonal(self, other, epsilon=0.001):
        """
        Return true is `self` and `other` are orthogonal segments

        The answer is based on numerical approximations of the slopes.
        If \f$ k \f$ is the slope of `self`, check if the
        slope of the other is \f$ -1/k \f$ up to `epsilon`.

        See `is_orthogonal`
        """
        if self.is_vertical:
            return other.is_horizontal
        if self.is_horizontal:
            return other.is_vertical

        s_slope = numerical_approx(self.slope)
        o_slope = numerical_approx(other.slope)

        if abs(s_slope+1/o_slope) < epsilon:
            return True
        return False