Пример #1
0
def shifted_coordinates_within_range(coordinates, minimum, maximum, precision = 4):
    # Handle input errors
    allow_none_matrix(coordinates, 'first')
    compare_scalars(minimum, maximum, 'second', 'third')
    positive_integer(precision)

    # Create list to return
    result = []

    # Handle general case
    if coordinates[0] is not None:
        # Generate inputs
        input_points = shifted_points_within_range(coordinates, minimum, maximum, precision)
        
        # Generate outputs
        output_points = []
        for point in input_points:
            output_points.append(coordinates[0][1])
        
        # Unite inputs and outputs into single list
        result = unite_vectors(input_points, output_points)
    
    # Handle no points
    else:
        result = coordinates
    
    # Return result
    return result
Пример #2
0
def logistic_roots_initial_value(first_constant,
                                 second_constant,
                                 third_constant,
                                 initial_value,
                                 precision=4):
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant,
                 initial_value)
    positive_integer(precision)

    # Create list to return
    result = []

    # Create pivot variable
    log_argument = first_constant / initial_value - 1

    # Circumvent logarithm of zero
    if log_argument == 0:
        log_argument = 10**(-precision)

    # Create intermediary variables
    numerator = log(abs(log_argument))
    denominator = second_constant
    ratio = numerator / denominator

    # Determine root given an initial value
    root = third_constant - ratio

    # Round root
    rounded_root = rounded_value(root, precision)

    # Return result
    result.append(rounded_root)
    return result
Пример #3
0
def exponential_roots_initial_value(first_constant, second_constant, initial_value, precision = 4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Create list to return
    result = []

    # Create intermediary variables
    numerator = log(abs(initial_value / first_constant))
    denominator = log(abs(second_constant))

    # Circumvent division by zero
    if denominator == 0:
        denominator = 10**(-precision)

    # Determine root given an initial value
    ratio = numerator / denominator

    # Round root
    rounded_ratio = rounded_value(ratio, precision)

    # Return result
    result.append(rounded_ratio)
    return result
Пример #4
0
def sinusoidal_roots_derivative_initial_value(first_constant, second_constant, third_constant, fourth_constant, initial_value, precision = 4):
    # Handle input errors
    five_scalars(first_constant, second_constant, third_constant, fourth_constant, initial_value)
    positive_integer(precision)

    # Create intermediary list and list to return
    roots = []
    result = []

    # Identify key ratio
    ratio = initial_value / (first_constant * second_constant)

    # Handle no roots
    if ratio > 1 or ratio < -1:
        result.append(None)
    
    # Handle multiple roots
    else:
        # Handle case in which initial value is zero
        if ratio == 0:
            roots = sinusoidal_roots_first_derivative(first_constant, second_constant, third_constant, fourth_constant, precision)
        
        # Handle general case
        else:
            radians = acos(ratio)
            periodic_radians = radians / second_constant
            periodic_unit = 2 * pi / second_constant
            initial = third_constant + periodic_radians
            roots = generate_elements(initial, periodic_unit, precision)

            # Handle roots that bounce on the x-axis
            if ratio == 1 or ratio == -1:
                pass

            # Handle roots that cross the x-axis
            else:
                alternative_initial = third_constant + periodic_unit - periodic_radians
                generated_elements = generate_elements(alternative_initial, periodic_unit, precision)
                roots.extend(generated_elements)
        
        # Separate numerical roots, string roots, and None results
        separated_roots = separate_elements(roots)
        numerical_roots = separated_roots['numerical']
        other_roots = separated_roots['other']
        
        # Sort numerical roots
        sorted_roots = sorted_list(numerical_roots)

        # Round numerical roots
        rounded_roots = rounded_list(sorted_roots, precision)
        
        # Sort other_roots
        sorted_other_roots = sorted_strings(other_roots)

        # Combine numerical and non-numerical roots
        result.extend(rounded_roots + sorted_other_roots)
    
    # Return result
    return result
Пример #5
0
def sinusoidal_roots_initial_value(first_constant, second_constant, third_constant, fourth_constant, initial_value, precision = 4):
    # Handle input errors
    five_scalars(first_constant, second_constant, third_constant, fourth_constant, initial_value)
    positive_integer(precision)

    # Determine roots given an initial value
    result = sinusoidal_roots(first_constant, second_constant, third_constant, fourth_constant - initial_value, precision)
    return result
Пример #6
0
def shifted_points_within_range(points, minimum, maximum, precision = 4):
    # Handle input errors
    allow_vector_matrix(points, 'first')
    compare_scalars(minimum, maximum, 'second', 'third')
    positive_integer(precision)

    # Grab general points
    general_points = []
    for point in points:
        # Handle coordinate pairs
        if isinstance(point, list):
            if isinstance(point[0], str):
                general_points.append(point[0])
        
        # Handle single coordinates
        else:
            if isinstance(point, str):
                general_points.append(point)
    
    # Generate options for inputs
    optional_points = []
    for point in general_points:
        # Grab initial value and periodic unit
        initial_value_index = point.find(' + ')
        initial_value = float(point[:initial_value_index])
        periodic_unit_index = initial_value_index + 3
        periodic_unit = float(point[periodic_unit_index:-1])
        
        # Increase or decrease initial value to fit into range
        alternative_initial_value = shift_into_range(initial_value, periodic_unit, minimum, maximum)
        
        # Generate additional values within range
        generated_elements = generate_elements(alternative_initial_value, periodic_unit, precision)
        optional_points += generated_elements
    
    # Separate numerical inputs from string inputs
    separated_points = separate_elements(optional_points)
    numerical_points = separated_points['numerical']
    other_points = separated_points['other']

    # Sort numerical inputs
    sorted_points = sorted_list(numerical_points)

    # Reduce numerical inputs to within a given range
    selected_points = [x for x in sorted_points if x >= minimum and x <= maximum]
    
    # Round numerical inputs
    rounded_points = rounded_list(selected_points, precision)
    
    # Sort string inputs
    sorted_other_points = sorted_strings(other_points)
    
    # Combine numerical and string inputs
    result = rounded_points + sorted_other_points
    return result
Пример #7
0
def logarithmic_roots_derivative_initial_value(first_constant,
                                               second_constant,
                                               initial_value,
                                               precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Determine roots of derivative given an initial value
    result = hyperbolic_roots(first_constant, -1 * initial_value, precision)
    return result
Пример #8
0
def linear_roots_initial_value(first_constant,
                               second_constant,
                               initial_value,
                               precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Determine roots given an initial value
    result = linear_roots(first_constant, second_constant - initial_value,
                          precision)
    return result
Пример #9
0
def exponential_roots_derivative_initial_value(first_constant, second_constant, initial_value, precision = 4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Circumvent division by zero
    denominator = log(abs(second_constant))
    if denominator == 0:
        denominator = 10**(-precision)

    # Determine root of derivative given an initial value
    result = exponential_roots_initial_value(first_constant * denominator, second_constant, initial_value, precision)
    return result
Пример #10
0
def quadratic_roots_derivative_initial_value(first_constant,
                                             second_constant,
                                             third_constant,
                                             initial_value,
                                             precision=4):
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant,
                 initial_value)
    positive_integer(precision)

    # Determine roots of derivative given an initial value
    result = linear_roots(2 * first_constant, second_constant - initial_value,
                          precision)
    return result
Пример #11
0
def exponential_roots_second_derivative(first_constant, second_constant, precision = 4):
    # Handle input errors
    two_scalars(first_constant, second_constant)
    positive_integer(precision)

    # Create list to return
    result = []
    
    # Determine root of second derivative
    root = None

    # Return result
    result.append(root)
    return result
Пример #12
0
def quadratic_roots_first_derivative(first_constant,
                                     second_constant,
                                     third_constant,
                                     precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, third_constant)
    positive_integer(precision)

    # Generate coefficients of first derivative
    constants = quadratic_derivatives(first_constant, second_constant,
                                      third_constant)['first']['constants']

    # Determine roots of first derivative
    result = linear_roots(*constants, precision)
    return result
Пример #13
0
def rounded_list(numbers, precision=4):
    # Handle input errors
    allow_none_vector(numbers, 'first')
    positive_integer(precision)

    # Create list to return
    results = []

    # Iterate over input
    for number in numbers:
        # Store rounded values of input in list to return
        results.append(rounded_value(number, precision))

    # Return results
    return results
Пример #14
0
def hyperbolic_roots_first_derivative(first_constant,
                                      second_constant,
                                      precision=4):
    # Handle input errors
    two_scalars(first_constant, second_constant)
    positive_integer(precision)

    # Create list to return
    result = []

    # Determine root of first derivative
    root = 0.0

    # Return result
    result.append(root)
    return result
Пример #15
0
def quadratic_roots_second_derivative(first_constant,
                                      second_constant,
                                      third_constant,
                                      precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, third_constant)
    positive_integer(precision)

    # Create list to return
    result = []

    # Determine root
    root = None

    # Return result
    result.append(root)
    return result
Пример #16
0
def logistic_roots_second_derivative(first_constant,
                                     second_constant,
                                     third_constant,
                                     precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, third_constant)
    positive_integer(precision)

    # Create list to return
    result = []

    # Determine root of second derivative
    root = rounded_value(third_constant)

    # Return root
    result.append(root)
    return result
Пример #17
0
def cubic_roots_second_derivative(first_constant,
                                  second_constant,
                                  third_constant,
                                  fourth_constant,
                                  precision=4):
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant,
                 fourth_constant)
    positive_integer(precision)

    # Generate coefficients of second derivative
    constants = cubic_derivatives(first_constant, second_constant,
                                  third_constant,
                                  fourth_constant)['second']['constants']

    # Determine roots of second derivative
    result = linear_roots(*constants, precision)
    return result
Пример #18
0
def sinusoidal_roots_second_derivative(first_constant, second_constant, third_constant, fourth_constant, precision = 4):
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant, fourth_constant)
    positive_integer(precision)

    # Generate coefficients of second derivative
    constants = sinusoidal_derivatives(first_constant, second_constant, third_constant, fourth_constant)['second']['constants']

    # Create intermediary variables
    periodic_unit = pi / constants[1]
    initial_value = constants[2]

    # Generate roots based on criteria
    generated_roots = generate_elements(initial_value, periodic_unit, precision)

    # Return result
    result = generated_roots
    return result
Пример #19
0
def linear_roots_derivative_initial_value(first_constant,
                                          second_constant,
                                          initial_value,
                                          precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Create list to return
    result = []

    # Handle general case
    if initial_value == first_constant:
        result.append('All')

    # Handle exception
    else:
        result.append(None)

    # Return result
    return result
Пример #20
0
def logistic_roots_derivative_initial_value(first_constant,
                                            second_constant,
                                            third_constant,
                                            initial_value,
                                            precision=4):
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant,
                 initial_value)
    positive_integer(precision)

    # Create intermediary list and list to return
    roots = []
    result = []

    # Determine quadratic roots of derivative given an initial value
    intermediary_roots = quadratic_roots(
        initial_value, 2 * initial_value - first_constant * second_constant,
        initial_value, precision)

    # Handle no roots
    if intermediary_roots[0] == None:
        roots.append(None)

    # Convert quadratic roots using logarithms
    else:
        for intermediary in intermediary_roots:
            if intermediary == 0:
                intermediary = 10**(-precision)
            root = third_constant - log(abs(intermediary)) / second_constant
            rounded_root = rounded_value(root, precision)
            roots.append(rounded_root)

    # Sort roots
    sorted_roots = sorted_list(roots)

    # Return result
    result.extend(sorted_roots)
    return result
Пример #21
0
def hyperbolic_roots_derivative_initial_value(first_constant,
                                              second_constant,
                                              initial_value,
                                              precision=4):
    # Handle input errors
    three_scalars(first_constant, second_constant, initial_value)
    positive_integer(precision)

    # Create list to return
    result = []

    # Create intermediary variable
    ratio = -1 * first_constant / initial_value

    # Handle no roots
    if ratio < 0:
        result.append(None)

    # Determine roots of derivative given an initial value
    else:
        radical = ratio**(1 / 2)
        rounded_radical = rounded_value(radical, precision)
        result.append(rounded_radical)
    return result
Пример #22
0
def extrema_points(equation_type, coefficients, precision=4):
    """
    Calculates the extrema of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which extrema must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    ValueError
        First argument must be either 'linear', 'quadratic', 'cubic', 'hyperbolic', 'exponential', 'logarithmic', 'logistic', or 'sinusoidal'
    TypeError
        Second argument must be a 1-dimensional list containing elements that are integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    points['maxima'] : list of float or str
        Values of the x-coordinates at which the original function has a relative maximum; if the function is sinusoidal, then only two or three results within a two-period interval will be listed, but a general form will also be included; if the function has no maxima, then it will return a list of `None`
    points['minima'] : list of float or str
        Values of the x-coordinates at which the original function has a relative minimum; if the function is sinusoidal, then only two or three results within a two-period interval will be listed, but a general form will also be included; if the function has no minima, then it will return a list of `None`

    See Also
    --------
    - Roots for key functions: :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.analyses.roots.quadratic.quadratic_roots`, :func:`~regressions.analyses.roots.cubic.cubic_roots`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.analyses.roots.exponential.exponential_roots`, :func:`~regressions.analyses.roots.logarithmic.logarithmic_roots`, :func:`~regressions.analyses.roots.logistic.logistic_roots`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`
    - Graphical analysis: :func:`~regressions.analyses.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.maxima.maxima_points`, :func:`~regressions.analyses.minima.minima_points`, :func:`~regressions.analyses.points.key_coordinates`

    Notes
    -----
    - Critical points for the derivative of a function: :math:`c_i = \\{ c_1, c_2, c_3,  \\cdots, c_{n-1}, c_n \\}`
    - X-coordinates of the extrema of the function: :math:`x_{ext} = \\{ x \\mid x \\in c_i, \\left( f'(\\frac{c_{j-1} + c_j}{2}) < 0 \\cap f'(\\frac{c_j + c_{j+1}}{2}) > 0 \\right) \\\\ \\cup \\left( f'(\\frac{c_{j-1} + c_j}{2}) > 0 \\cap f'(\\frac{c_j + c_{j+1}}{2}) < 0 \\right) \\}`
    - |extrema_values|

    Examples
    --------
    Import `extrema_points` function from `regressions` library
        >>> from regressions.analyses.extrema import extrema_points
    Calulate the extrema of a cubic function with coefficients 1, -15, 63, and -7
        >>> points_cubic = extrema_points('cubic', [1, -15, 63, -7])
        >>> print(points_cubic['maxima'])
        [3.0]
        >>> print(points_cubic['minima'])
        [7.0]
    Calulate the extrema of a sinusoidal function with coefficients 2, 3, 5, and 7
        >>> points_sinusoidal = extrema_points('sinusoidal', [2, 3, 5, 7])
        >>> print(points_sinusoidal['maxima'])
        [5.5236, 7.618, 9.7124, '5.5236 + 2.0944k']
        >>> print(points_sinusoidal['minima'])
        [6.5708, 8.6652, '6.5708 + 2.0944k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)

    # Determine maxima and minima
    max_points = maxima_points(equation_type, coefficients, precision)
    min_points = minima_points(equation_type, coefficients, precision)

    # Create dictionary to return
    result = {}

    # Handle sinusoidal case
    if equation_type == 'sinusoidal':
        # Recreate sign chart
        intervals_set = sign_chart('sinusoidal', coefficients, 1, precision)

        # Grab general form
        general_form = intervals_set[-1]

        # Extract periodic unit
        periodic_unit_index = general_form.find(' + ') + 3
        periodic_unit = 2 * float(general_form[periodic_unit_index:-1])
        rounded_periodic_unit = rounded_value(periodic_unit, precision)

        # Create general forms for max and min
        max_general_form = str(
            max_points[0]) + ' + ' + str(rounded_periodic_unit) + 'k'
        min_general_form = str(
            min_points[0]) + ' + ' + str(rounded_periodic_unit) + 'k'

        # Append general form as final element of each list
        max_extended = max_points + [max_general_form]
        min_extended = min_points + [min_general_form]
        result = {'maxima': max_extended, 'minima': min_extended}

    # Handle all other cases
    else:
        result = {'maxima': max_points, 'minima': min_points}
    return result
Пример #23
0
def logistic_model(data, precision=4):
    """
    Generates a logistic regression model from a given data set

    Parameters
    ----------
    data : list of lists of int or float
        List of lists of numbers representing a collection of coordinate pairs; it must include at least 10 pairs
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within first argument must be integers or floats
    ValueError
        First argument must contain at least 10 elements
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    model['constants'] : list of float
        Coefficients of the resultant logistic model; the first element is the carrying capacity, the second element is the growth rate, and the third element is the sigmoid's midpoint
    model['evaluations']['equation'] : func
        Function that evaluates the equation of the logistic model at a given numeric input (e.g., model['evaluations']['equation'](10) would evaluate the equation of the logistic model when the independent variable is 10)
    model['evaluations']['derivative'] : func
        Function that evaluates the first derivative of the logistic model at a given numeric input (e.g., model['evaluations']['derivative'](10) would evaluate the first derivative of the logistic model when the independent variable is 10)
    model['evaluations']['integral'] : func
        Function that evaluates the integral of the logistic model at a given numeric input (e.g., model['evaluations']['integral'](10) would evaluate the integral of the logistic model when the independent variable is 10)
    model['points']['roots'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the x-intercepts of the logistic model (will always be `None`)
    model['points']['maxima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the maxima of the logistic model (will always be `None`)
    model['points']['minima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the minima of the logistic model (will always be `None`)
    model['points']['inflections'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the inflection points of the logistic model (will contain exactly one point)
    model['accumulations']['range'] : float
        Total area under the curve represented by the logistic model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided (i.e., over the range)
    model['accumulations']['iqr'] : float
        Total area under the curve represented by the logistic model between the first and third quartiles of all the independent coordinates originally provided (i.e., over the interquartile range)
    model['averages']['range']['average_value_derivative'] : float
        Average rate of change of the curve represented by the logistic model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_derivative'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['range']['average_value_integral'] : float
        Average value of the curve represented by the logistic model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_integral'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their value equals the function's average value over that interval
    model['averages']['iqr']['average_value_derivative'] : float
        Average rate of change of the curve represented by the logistic model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_derivative'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['iqr']['average_value_integral'] : float
        Average value of the curve represented by the logistic model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_integral'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their value equals the function's average value over that interval
    model['correlation'] : float
        Correlation coefficient indicating how well the model fits the original data set (values range between 0.0, implying no fit, and 1.0, implying a perfect fit)

    See Also
    --------
    :func:`~regressions.analyses.equations.logistic.logistic_equation`, :func:`~regressions.analyses.derivatives.logistic.logistic_derivatives`, :func:`~regressions.analyses.integrals.logistic.logistic_integral`, :func:`~regressions.analyses.roots.logistic.logistic_roots`, :func:`~regressions.statistics.correlation.correlation_coefficient`, :func:`~regressions.execute.run_all`

    Notes
    -----
    - Provided ordered pairs for the data set: :math:`p_i = \\{ (p_{1,x}, p_{1,y}), (p_{2,x}, p_{2,y}), \\cdots, (p_{n,x}, p_{n,y}) \\}`
    - Provided values for the independent variable: :math:`X_i = \\{ p_{1,x}, p_{2,x}, \\cdots, p_{n,x} \\}`
    - Provided values for the dependent variable: :math:`Y_i = \\{ p_{1,y}, p_{2,y}, \\cdots, p_{n,y} \\}`
    - Minimum value of the provided values for the independent variable: :math:`X_{min} \\leq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - Maximum value of the provided values for the independent variable: :math:`X_{max} \\geq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - First quartile of the provided values for the independent variable: :math:`X_{Q1}`
    - Third quartile of the provided values for the independent variable: :math:`X_{Q3}`
    - Mean of all provided values for the dependent variable: :math:`\\bar{y} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n Y_i}`
    - Resultant values for the coefficients of the logistic model: :math:`C_i = \\{ a, b, c \\}`
    - Standard form for the equation of the logistic model: :math:`f(x) = \\frac{a}{1 + \\text{e}^{-b\\cdot(x - c)}}`
    - First derivative of the logistic model: :math:`f'(x) = \\frac{ab\\cdot{\\text{e}^{-b\\cdot(x - c)}}}{(1 + \\text{e}^{-b\\cdot(x - c)})^2}`
    - Second derivative of the logistic model: :math:`f''(x) = \\frac{2ab^2\\cdot{\\text{e}^{-2b\\cdot(x - c)}}}{(1 + \\text{e}^{-b\\cdot(x - c)})^3} - \\frac{ab^2\\cdot{\\text{e}^{-b\\cdot(x - c)}}}{(1 + \\text{e}^{-b\\cdot(x - c)})^2}`
    - Integral of the logistic model: :math:`F(x) = \\frac{a}{b}\\cdot{\\ln|\\text{e}^{b\\cdot(x - c)} + 1|}`
    - Potential x-values of the roots of the logistic model: :math:`x_{intercepts} = \\{ \\varnothing \\}`
    - Potential x-values of the maxima of the logistic model: :math:`x_{maxima} = \\{ \\varnothing \\}`
    - Potential x-values of the minima of the logistic model: :math:`x_{minima} = \\{ \\varnothing \\}`
    - Potential x-values of the inflection points of the logistic model: :math:`x_{inflections} = \\{ c \\}`
    - Accumulatation of the logistic model over its range: :math:`A_{range} = \\int_{X_{min}}^{X_{max}} f(x) \\,dx`
    - Accumulatation of the logistic model over its interquartile range: :math:`A_{iqr} = \\int_{X_{Q1}}^{X_{Q3}} f(x) \\,dx`
    - Average rate of change of the logistic model over its range: :math:`m_{range} = \\frac{f(X_{max}) - f(X_{min})}{X_{max} - X_{min}}`
    - Potential x-values at which the logistic model's instantaneous rate of change equals its average rate of change over its range: :math:`x_{m,range} = \\{ c + \\frac{1}{b}\\cdot{\\ln(2m_{range})} - \\frac{1}{b}\\cdot{\\ln\\left(ab - 2m_{range} - \\sqrt{(2m_{range} - ab)^2 - 4m_{range}^2}\\right)}, \\\\ c + \\frac{1}{b}\\cdot{\\ln(2m_{range})} - \\frac{1}{b}\\cdot{\\ln\\left(ab - 2m_{range} + \\sqrt{(2m_{range} - ab)^2 - 4m_{range}^2}\\right)} \\}`
    - Average value of the logistic model over its range: :math:`v_{range} = \\frac{1}{X_{max} - X_{min}}\\cdot{A_{range}}`
    - Potential x-values at which the logistic model's value equals its average value over its range: :math:`x_{v,range} = \\{ c - \\frac{1}{b}\\cdot{\\ln(\\frac{a}{v_{range}} - 1)} \\}`
    - Average rate of change of the logistic model over its interquartile range: :math:`m_{iqr} = \\frac{f(X_{Q3}) - f(X_{Q1})}{X_{Q3} - X_{Q1}}`
    - Potential x-values at which the logistic model's instantaneous rate of change equals its average rate of change over its interquartile range: :math:`x_{m,iqr} = \\{ c + \\frac{1}{b}\\cdot{\\ln(2m_{iqr})} - \\frac{1}{b}\\cdot{\\ln\\left(ab - 2m_{iqr} - \\sqrt{(2m_{iqr} - ab)^2 - 4m_{iqr}^2}\\right)}, \\\\ c + \\frac{1}{b}\\cdot{\\ln(2m_{iqr})} - \\frac{1}{b}\\cdot{\\ln\\left(ab - 2m_{iqr} + \\sqrt{(2m_{iqr} - ab)^2 - 4m_{iqr}^2}\\right)} \\}`
    - Average value of the logistic model over its interquartile range: :math:`v_{iqr} = \\frac{1}{X_{Q3} - X_{Q1}}\\cdot{A_{iqr}}`
    - Potential x-values at which the logistic model's value equals its average value over its interquartile range: :math:`x_{v,iqr} = \\{ c - \\frac{1}{b}\\cdot{\\ln(\\frac{a}{v_{iqr}} - 1)} \\}`
    - Predicted values based on the logistic model: :math:`\\hat{y}_i = \\{ \\hat{y}_1, \\hat{y}_2, \\cdots, \\hat{y}_n \\}`
    - Residuals of the dependent variable: :math:`e_i = \\{ p_{1,y} - \\hat{y}_1, p_{2,y} - \\hat{y}_2, \\cdots, p_{n,y} - \\hat{y}_n \\}`
    - Deviations of the dependent variable: :math:`d_i = \\{ p_{1,y} - \\bar{y}, p_{2,y} - \\bar{y}, \\cdots, p_{n,y} - \\bar{y} \\}`
    - Sum of squares of residuals: :math:`SS_{res} = \\sum\\limits_{i=1}^n e_i^2`
    - Sum of squares of deviations: :math:`SS_{dev} = \\sum\\limits_{i=1}^n d_i^2`
    - Correlation coefficient for the logistic model: :math:`r = \\sqrt{1 - \\frac{SS_{res}}{SS_{dev}}}`
    - |regression_analysis|

    Examples
    --------
    Import `logistic_model` function from `regressions` library
        >>> from regressions.models.logistic import logistic_model
    Generate a logistic regression model for the data set [[1, 0.0000122], [2, 0.000247], [3, 0.004945], [4, 0.094852], [5, 1.0], [6, 1.905148], [7, 1.995055], [8, 1.999753], [9, 1.999988], [10, 1.999999]], then print its coefficients, roots, total accumulation over its interquartile range, and correlation
        >>> model_perfect = logistic_model([[1, 0.0000122], [2, 0.000247], [3, 0.004945], [4, 0.094852], [5, 1.0], [6, 1.905148], [7, 1.995055], [8, 1.999753], [9, 1.999988], [10, 1.999999]])
        >>> print(model_perfect['constants'])
        [2.0, 3.0, 5.0]
        >>> print(model_perfect['points']['roots'])
        [None]
        >>> print(model_perfect['accumulations']['iqr'])
        5.9987
        >>> print(model_perfect['correlation'])
        1.0
    Generate a logistic regression model for the data set [[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]], then print its coefficients, inflections, total accumulation over its range, and correlation
        >>> model_agnostic = logistic_model([[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]])
        >>> print(model_agnostic['constants'])
        [43.9838, 0.3076, 0.9747]
        >>> print(model_agnostic['points']['inflections'])
        [[0.9747, 21.9919]]
        >>> print(model_agnostic['accumulations']['range'])
        305.9347
        >>> print(model_agnostic['correlation'])
        0.5875
    """
    # Handle input errors
    matrix_of_scalars(data, 'first')
    long_vector(data)
    positive_integer(precision)

    # Store independent and dependent variable values separately
    independent_variable = single_dimension(data, 1)
    dependent_variable = single_dimension(data, 2)

    # Determine key values for bounds
    halved_data = half_dimension(data, 1)
    dependent_lower = single_dimension(halved_data['lower'], 2)
    dependent_upper = single_dimension(halved_data['upper'], 2)
    mean_lower = mean_value(dependent_lower)
    mean_upper = mean_value(dependent_upper)
    dependent_max = max(dependent_variable)
    dependent_min = min(dependent_variable)
    dependent_range = dependent_max - dependent_min
    independent_max = max(independent_variable)
    independent_min = min(independent_variable)
    independent_range = independent_max - independent_min
    independent_avg = (independent_max + independent_min) / 2

    # Circumvent error with bounds
    if dependent_range == 0:
        dependent_range = 1
    if independent_range == 0:
        independent_range = 1

    # Create function to guide model generation
    def logistic_fit(variable, first_constant, second_constant,
                     third_constant):
        evaluation = first_constant / (1 + exp(-1 * second_constant *
                                               (variable - third_constant)))
        return evaluation

    # Create list to store coefficients of generated equation
    solution = []

    # Handle normal case where values appear to increase in the set
    if mean_upper >= mean_lower:
        # Generate model
        parameters, covariance = curve_fit(
            logistic_fit,
            independent_variable,
            dependent_variable,
            bounds=[(dependent_max - dependent_range, 0,
                     independent_avg - independent_range),
                    (dependent_max + dependent_range, inf,
                     independent_avg + independent_range)])
        solution = list(parameters)

    # Handle case where values do not appear to increase in the set
    else:
        # Generate model with inverted negative infinity and zero values
        parameters, covariance = curve_fit(
            logistic_fit,
            independent_variable,
            dependent_variable,
            bounds=[(dependent_max - dependent_range, -inf,
                     independent_avg - independent_range),
                    (dependent_max + dependent_range, 0,
                     independent_avg + independent_range)])
        solution = list(parameters)

    # Eliminate zeroes from solution
    coefficients = no_zeroes(solution, precision)

    # Generate evaluations for function, derivative, and integral
    equation = logistic_equation(*coefficients, precision)
    derivative = logistic_derivatives(*coefficients,
                                      precision)['first']['evaluation']
    integral = logistic_integral(*coefficients, precision)['evaluation']

    # Determine key points of graph
    points = key_coordinates('logistic', coefficients, precision)

    # Generate values for lower and upper bounds
    five_numbers = five_number_summary(independent_variable, precision)
    min_value = five_numbers['minimum']
    max_value = five_numbers['maximum']
    q1 = five_numbers['q1']
    q3 = five_numbers['q3']

    # Calculate accumulations
    accumulated_range = accumulated_area('logistic', coefficients, min_value,
                                         max_value, precision)
    accumulated_iqr = accumulated_area('logistic', coefficients, q1, q3,
                                       precision)

    # Determine average values and their points
    averages_range = average_values('logistic', coefficients, min_value,
                                    max_value, precision)
    averages_iqr = average_values('logistic', coefficients, q1, q3, precision)

    # Create list of predicted outputs
    predicted = []
    for element in independent_variable:
        predicted.append(equation(element))

    # Calculate correlation coefficient for model
    accuracy = correlation_coefficient(dependent_variable, predicted,
                                       precision)

    # Package preceding results in multiple dictionaries
    evaluations = {
        'equation': equation,
        'derivative': derivative,
        'integral': integral
    }
    points = {
        'roots': points['roots'],
        'maxima': points['maxima'],
        'minima': points['minima'],
        'inflections': points['inflections']
    }
    accumulations = {'range': accumulated_range, 'iqr': accumulated_iqr}
    averages = {'range': averages_range, 'iqr': averages_iqr}

    # Package all dictionaries in single dictionary to return
    result = {
        'constants': coefficients,
        'evaluations': evaluations,
        'points': points,
        'accumulations': accumulations,
        'averages': averages,
        'correlation': accuracy
    }
    return result
Пример #24
0
def linear_model(data, precision = 4):
    """
    Generates a linear regression model from a given data set

    Parameters
    ----------
    data : list of lists of int or float
        List of lists of numbers representing a collection of coordinate pairs; it must include at least 10 pairs
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within first argument must be integers or floats
    ValueError
        First argument must contain at least 10 elements
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    model['constants'] : list of float
        Coefficients of the resultant linear model; the first element is the coefficient of the linear term, and the second element is the coefficient of the constant term
    model['evaluations']['equation'] : func
        Function that evaluates the equation of the linear model at a given numeric input (e.g., model['evaluations']['equation'](10) would evaluate the equation of the linear model when the independent variable is 10)
    model['evaluations']['derivative'] : func
        Function that evaluates the first derivative of the linear model at a given numeric input (e.g., model['evaluations']['derivative'](10) would evaluate the first derivative of the linear model when the independent variable is 10)
    model['evaluations']['integral'] : func
        Function that evaluates the integral of the linear model at a given numeric input (e.g., model['evaluations']['integral'](10) would evaluate the integral of the linear model when the independent variable is 10)
    model['points']['roots'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the x-intercepts of the linear model (will contain exactly one point)
    model['points']['maxima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the maxima of the linear model (will always be `None`)
    model['points']['minima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the minima of the linear model (will always be `None`)
    model['points']['inflections'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the inflection points of the linear model (will always be `None`)
    model['accumulations']['range'] : float
        Total area under the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided (i.e., over the range)
    model['accumulations']['iqr'] : float
        Total area under the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided (i.e., over the interquartile range)
    model['averages']['range']['average_value_derivative'] : float
        Average rate of change of the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_derivative'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['range']['average_value_integral'] : float
        Average value of the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_integral'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their value equals the function's average value over that interval
    model['averages']['iqr']['average_value_derivative'] : float
        Average rate of change of the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_derivative'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['iqr']['average_value_integral'] : float
        Average value of the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_integral'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their value equals the function's average value over that interval
    model['correlation'] : float
        Correlation coefficient indicating how well the model fits the original data set (values range between 0.0, implying no fit, and 1.0, implying a perfect fit)

    See Also
    --------
    :func:`~regressions.analyses.equations.linear.linear_equation`, :func:`~regressions.analyses.derivatives.linear.linear_derivatives`, :func:`~regressions.analyses.integrals.linear.linear_integral`, :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.statistics.correlation.correlation_coefficient`, :func:`~regressions.execute.run_all`

    Notes
    -----
    - Provided ordered pairs for the data set: :math:`p_i = \\{ (p_{1,x}, p_{1,y}), (p_{2,x}, p_{2,y}), \\cdots, (p_{n,x}, p_{n,y}) \\}`
    - Provided values for the independent variable: :math:`X_i = \\{ p_{1,x}, p_{2,x}, \\cdots, p_{n,x} \\}`
    - Provided values for the dependent variable: :math:`Y_i = \\{ p_{1,y}, p_{2,y}, \\cdots, p_{n,y} \\}`
    - Minimum value of the provided values for the independent variable: :math:`X_{min} \\leq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - Maximum value of the provided values for the independent variable: :math:`X_{max} \\geq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - First quartile of the provided values for the independent variable: :math:`X_{Q1}`
    - Third quartile of the provided values for the independent variable: :math:`X_{Q3}`
    - Mean of all provided values for the dependent variable: :math:`\\bar{y} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n Y_i}`
    - Resultant values for the coefficients of the linear model: :math:`C_i = \\{ a, b \\}`
    - Standard form for the equation of the linear model: :math:`f(x) = a\\cdot{x} + b`
    - First derivative of the linear model: :math:`f'(x) = a`
    - Second derivative of the linear model: :math:`f''(x) = 0`
    - Integral of the linear model: :math:`F(x) = \\frac{a}{2}\\cdot{x^2} + b\\cdot{x}`
    - Potential x-values of the roots of the linear model: :math:`x_{intercepts} = \\{ -\\frac{b}{a} \\}`
    - Potential x-values of the maxima of the linear model: :math:`x_{maxima} = \\{ \\varnothing \\}`
    - Potential x-values of the minima of the linear model: :math:`x_{minima} = \\{ \\varnothing \\}`
    - Potential x-values of the inflection points of the linear model: :math:`x_{inflections} = \\{ \\varnothing \\}`
    - Accumulatation of the linear model over its range: :math:`A_{range} = \\int_{X_{min}}^{X_{max}} f(x) \\,dx`
    - Accumulatation of the linear model over its interquartile range: :math:`A_{iqr} = \\int_{X_{Q1}}^{X_{Q3}} f(x) \\,dx`
    - Average rate of change of the linear model over its range: :math:`m_{range} = \\frac{f(X_{max}) - f(X_{min})}{X_{max} - X_{min}}`
    - Potential x-values at which the linear model's instantaneous rate of change equals its average rate of change over its range: :math:`x_{m,range} = \\{ [X_{min}, X_{max}] \\}`
    - Average value of the linear model over its range: :math:`v_{range} = \\frac{1}{X_{max} - X_{min}}\\cdot{A_{range}}`
    - Potential x-values at which the linear model's value equals its average value over its range: :math:`x_{v,range} = \\{ -\\frac{b - v_{range}}{a} \\}`
    - Average rate of change of the linear model over its interquartile range: :math:`m_{iqr} = \\frac{f(X_{Q3}) - f(X_{Q1})}{X_{Q3} - X_{Q1}}`
    - Potential x-values at which the linear model's instantaneous rate of change equals its average rate of change over its interquartile range: :math:`x_{m,iqr} = \\{ [X_{Q1}, X_{Q3}] \\}`
    - Average value of the linear model over its interquartile range: :math:`v_{iqr} = \\frac{1}{X_{Q3} - X_{Q1}}\\cdot{A_{iqr}}`
    - Potential x-values at which the linear model's value equals its average value over its interquartile range: :math:`x_{v,iqr} = \\{ -\\frac{b - v_{iqr}}{a} \\}`
    - Predicted values based on the linear model: :math:`\\hat{y}_i = \\{ \\hat{y}_1, \\hat{y}_2, \\cdots, \\hat{y}_n \\}`
    - Residuals of the dependent variable: :math:`e_i = \\{ p_{1,y} - \\hat{y}_1, p_{2,y} - \\hat{y}_2, \\cdots, p_{n,y} - \\hat{y}_n \\}`
    - Deviations of the dependent variable: :math:`d_i = \\{ p_{1,y} - \\bar{y}, p_{2,y} - \\bar{y}, \\cdots, p_{n,y} - \\bar{y} \\}`
    - Sum of squares of residuals: :math:`SS_{res} = \\sum\\limits_{i=1}^n e_i^2`
    - Sum of squares of deviations: :math:`SS_{dev} = \\sum\\limits_{i=1}^n d_i^2`
    - Correlation coefficient for the linear model: :math:`r = \\sqrt{1 - \\frac{SS_{res}}{SS_{dev}}}`
    - |regression_analysis|

    Examples
    --------
    Import `linear_model` function from `regressions` library
        >>> from regressions.models.linear import linear_model
    Generate a linear regression model for the data set [[1, 30], [2, 27], [3, 24], [4, 21], [5, 18], [6, 15], [7, 12], [8, 9], [9, 6], [10, 3]], then print its coefficients, roots, total accumulation over its interquartile range, and correlation
        >>> model_perfect = linear_model([[1, 30], [2, 27], [3, 24], [4, 21], [5, 18], [6, 15], [7, 12], [8, 9], [9, 6], [10, 3]])
        >>> print(model_perfect['constants'])
        [-3.0, 33.0]
        >>> print(model_perfect['points']['roots'])
        [[11.0, 0.0]]
        >>> print(model_perfect['accumulations']['iqr'])
        82.5
        >>> print(model_perfect['correlation'])
        1.0
    Generate a linear regression model for the data set [[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]], then print its coefficients, inflections, total accumulation over its range, and correlation
        >>> model_agnostic = linear_model([[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]])
        >>> print(model_agnostic['constants'])
        [1.9636, 23.0]
        >>> print(model_agnostic['points']['inflections'])
        [None]
        >>> print(model_agnostic['accumulations']['range'])
        304.1982
        >>> print(model_agnostic['correlation'])
        0.5516
    """
    # Handle input errors
    matrix_of_scalars(data, 'first')
    long_vector(data)
    positive_integer(precision)

    # Store independent and dependent variable values separately
    independent_variable = single_dimension(data, 1)
    dependent_variable = single_dimension(data, 2)

    # Create matrices for independent and dependent variables
    independent_matrix = []
    dependent_matrix = column_conversion(dependent_variable)

    # Iterate over inputted data
    for element in independent_variable:
        # Store linear and constant evaluations of original independent elements together as lists within independent matrix
        independent_matrix.append([element, 1])

    # Solve system of equations
    solution = system_solution(independent_matrix, dependent_matrix, precision)

    # Eliminate zeroes from solution
    coefficients = no_zeroes(solution, precision)

    # Generate evaluations for function, derivatives, and integral
    equation = linear_equation(*coefficients, precision)
    derivative = linear_derivatives(*coefficients, precision)['first']['evaluation']
    integral = linear_integral(*coefficients, precision)['evaluation']

    # Determine key points of graph
    points = key_coordinates('linear', coefficients, precision)

    # Generate values for lower and upper bounds
    five_numbers = five_number_summary(independent_variable, precision)
    min_value = five_numbers['minimum']
    max_value = five_numbers['maximum']
    q1 = five_numbers['q1']
    q3 = five_numbers['q3']

    # Calculate accumulations
    accumulated_range = accumulated_area('linear', coefficients, min_value, max_value, precision)
    accumulated_iqr = accumulated_area('linear', coefficients, q1, q3, precision)

    # Determine average values and their points
    averages_range = average_values('linear', coefficients, min_value, max_value, precision)
    averages_iqr = average_values('linear', coefficients, q1, q3, precision)

    # Create list of predicted outputs
    predicted = []
    for element in independent_variable:
        predicted.append(equation(element))
    
    # Calculate correlation coefficient for model
    accuracy = correlation_coefficient(dependent_variable, predicted, precision)

    # Package preceding results in multiple dictionaries
    evaluations = {
        'equation': equation,
        'derivative': derivative,
        'integral': integral
    }
    points = {
        'roots': points['roots'],
        'maxima': points['maxima'],
        'minima': points['minima'],
        'inflections': points['inflections']
    }
    accumulations = {
        'range': accumulated_range,
        'iqr': accumulated_iqr
    }
    averages = {
        'range': averages_range,
        'iqr': averages_iqr
    }

    # Package all dictionaries in single dictionary to return
    result = {
        'constants': coefficients,
        'evaluations': evaluations,
        'points': points,
        'accumulations': accumulations,
        'averages': averages,
        'correlation': accuracy
    }
    return result
Пример #25
0
def sinusoidal_equation(first_constant, second_constant, third_constant, fourth_constant, precision = 4):
    """
    Generates a sinusoidal function to provide evaluations at variable inputs

    Parameters
    ----------
    first_constant : int or float
        Vertical stretch factor of the resultant sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    second_constant : int or float
        Horizontal stretch factor of the resultant sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    third_constant : int or float
        Horizontal shift of the resultant sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    fourth_constant : int or float
        Vertical shift of the resultant sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the resultant roots

    Raises
    ------
    TypeError
        First four arguments must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    evaluation : func
        Function for evaluating a sinusoidal equation when passed any integer or float argument

    See Also
    --------
    :func:`~regressions.analyses.derivatives.sinusoidal.sinusoidal_derivatives`, :func:`~regressions.analyses.integrals.sinusoidal.sinusoidal_integral`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`, :func:`~regressions.models.sinusoidal.sinusoidal_model`

    Notes
    -----
    - Standard form of a sinusoidal function: :math:`f(x) = a\\cdot{\\sin(b\\cdot(x - c))} + d`

        - Period of function: :math:`\\frac{2\\pi}{|b|}`
        - Amplitude of function: :math:`|a|`

    - |sine_functions|

    Examples
    --------
    Import `sinusoidal_equation` function from `regressions` library
        >>> from regressions.analyses.equations.sinusoidal import sinusoidal_equation
    Create a sinusoidal function with coefficients 2, 3, 5, and 7, then evaluate it at 10
        >>> evaluation_first = sinusoidal_equation(2, 3, 5, 7)
        >>> print(evaluation_first(10))
        8.3006
    Create a sinusoidal function with coefficients 7, -5, -3, and 2, then evaluate it at 10
        >>> evaluation_second = sinusoidal_equation(7, -5, -3, 2)
        >>> print(evaluation_second(10))
        -3.7878
    Create a sinusoidal function with all inputs set to 0, then evaluate it at 10
        >>> evaluation_zero = sinusoidal_equation(0, 0, 0, 0)
        >>> print(evaluation_zero(10))
        0.0001
    """
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant, fourth_constant)
    positive_integer(precision)
    coefficients = no_zeroes([first_constant, second_constant, third_constant, fourth_constant], precision)

    # Create evaluation
    def sinusoidal_evaluation(variable):
        evaluation = coefficients[0] * sin(coefficients[1] * (variable - coefficients[2])) + coefficients[3]
        result = rounded_value(evaluation, precision)
        return result
    return sinusoidal_evaluation
Пример #26
0
def hyperbolic_integral(first_constant, second_constant, precision=4):
    """
    Generates the integral of a hyperbolic function

    Parameters
    ----------
    first_constant : int or float
        Coefficient of the reciprocal variable of the original hyperbolic function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    second_constant : int or float
        Coefficient of the constant term of the original hyperbolic function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the resultant roots

    Raises
    ------
    TypeError
        First two arguments must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    integral['constants'] : list of float
        Coefficients of the resultant integral
    integral['evaluation'] : func
        Function for evaluating the resultant integral at any float or integer argument; if zero inputted as argument, it will be converted to a small, non-zero decimal value (e.g., 0.0001)

    See Also
    --------
    :func:`~regressions.analyses.equations.hyperbolic.hyperbolic_equation`, :func:`~regressions.analyses.derivatives.hyperbolic.hyperbolic_derivatives`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.models.hyperbolic.hyperbolic_model`

    Notes
    -----
    - Standard form of a hyperbolic function: :math:`f(x) = a\\cdot{\\frac{1}{x}} + b`
    - Integral of a hyperbolic function: :math:`F(x) = a\\cdot{\\ln|x|} + b\\cdot{x}`
    - |indefinite_integral|
    - |integration_formulas|

    Examples
    --------
    Import `sinusoidal_hyperbolic` function from `regressions` library
        >>> from regressions.analyses.hyperbolics.sinusoidal import sinusoidal_hyperbolic
    Generate the integral of a hyperbolic function with coefficients 2 and 3, then display its coefficients
        >>> integral_constants = hyperbolic_integral(2, 3)
        >>> print(integral_constants['constants'])
        [2.0, 3.0]
    Generate the integral of a hyperbolic function with coefficients -2 and 3, then evaluate its integral at 10
        >>> integral_evaluation = hyperbolic_integral(-2, 3)
        >>> print(integral_evaluation['evaluation'](10))
        25.3948
    Generate the integral of a hyperbolic function with all inputs set to 0, then display its coefficients
        >>> integral_zeroes = hyperbolic_integral(0, 0)
        >>> print(integral_zeroes['constants'])
        [0.0001, 0.0001]
    """
    # Handle input errors
    two_scalars(first_constant, second_constant)
    positive_integer(precision)
    coefficients = no_zeroes([first_constant, second_constant], precision)

    # Create constants
    constants = [coefficients[0], coefficients[1]]

    # Create evaluation
    def hyperbolic_evaluation(variable):
        # Circumvent logarithm of zero
        if variable == 0:
            variable = 10**(-precision)
        evaluation = constants[0] * log(
            abs(variable)) + constants[1] * variable
        rounded_evaluation = rounded_value(evaluation, precision)
        return rounded_evaluation

    # Package constants and evaluation in single dictionary
    results = {'constants': constants, 'evaluation': hyperbolic_evaluation}
    return results
Пример #27
0
def coordinate_pairs(equation_type, coefficients, inputs, point_type = 'point', precision = 4):
    """
    Creates a list of coordinate pairs from a set of inputs

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which coordinate pairs must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    inputs : list of int or float or str
        X-coordinates to use to generate the y-coordinates for each coordinate pair
    point_type : str, default='point'
        Name of the type of point that describes all points which must be generated (e.g., 'intercepts', 'maxima')
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    ValueError
        First argument must be either 'linear', 'quadratic', 'cubic', 'hyperbolic', 'exponential', 'logarithmic', 'logistic', or 'sinusoidal'
    TypeError
        Second argument must be a 1-dimensional list containing elements that are integers or floats
    TypeError
        Third argument must be a 1-dimensional list containing elements that are integers, floats, strings, or None
    ValueError
        Fourth argument must be either 'point', 'intercepts', 'maxima', 'minima', or 'inflections'
    ValueError
        Last argument must be a positive integer
        
    Returns
    -------
    points : list of float or str
        List containing lists of coordinate pairs, in which the second element of the inner lists are floats and the first elements of the inner lists are either floats or strings (the latter for general forms); may return a list of None if inputs list contained None

    See Also
    --------
    :func:`~regressions.vectors.generate.generate_elements`, :func:`~regressions.vectors.unify.unite_vectors`

    Notes
    -----
    - Set of x-coordinates of points: :math:`x_i = \\{ x_1, x_2, \\cdots, x_n \\}`
    - Set of y-coordinates of points: :math:`y_i = \\{ y_1, y_2, \\cdots, y_n \\}`
    - Set of coordinate pairs of points: :math:`p_i = \\{ (x_1, y_1), (x_2, y_2), \\cdots, (x_n, y_n) \\}`

    Examples
    --------
    Import `coordinate_pairs` function from `regressions` library
        >>> from regressions.analyses.points import coordinate_pairs
    Generate a list of coordinate pairs for a cubic function with coefficients 2, 3, 5, and 7 based off x-coordinates of 1, 2, 3, and 4
        >>> points_cubic = coordinate_pairs('cubic', [2, 3, 5, 7], [1, 2, 3, 4])
        >>> print(points_cubic)
        [[1.0, 17.0], [2.0, 45.0], [3.0, 103.0], [4.0, 203.0]]
    Generate a list of coordinate pairs for a sinusoidal function with coefficients 2, 3, 5, and 7 based off x-coordinates of 1, 2, 3, and 4
        >>> points_sinusoidal = coordinate_pairs('sinusoidal', [2, 3, 5, 7], [1, 2, 3, 4])
        >>> print(points_sinusoidal)
        [[1.0, 8.0731], [2.0, 6.1758], [3.0, 7.5588], [4.0, 6.7178]]
    Generate a list of coordinate pairs for a quadratic function with coefficients 1, -5, and 6 based off x-coordinates of 2 and 3 (given that the resultant coordinates will be x-intercepts)
        >>> points_quadratic = coordinate_pairs('quadratic', [1, -5, 6], [2, 3], 'intercepts')
        >>> print(points_quadratic)
        [[2.0, 0.0], [3.0, 0.0]]
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    allow_none_vector(inputs, 'third')
    select_points(point_type, 'fourth')
    positive_integer(precision)

    # Create equations for evaluating inputs (based on equation type)
    equation = lambda x : x
    if equation_type == 'linear':
        equation = linear_equation(*coefficients, precision)
    elif equation_type == 'quadratic':
        equation = quadratic_equation(*coefficients, precision)
    elif equation_type == 'cubic':
        equation = cubic_equation(*coefficients, precision)
    elif equation_type == 'hyperbolic':
        equation = hyperbolic_equation(*coefficients, precision)
    elif equation_type == 'exponential':
        equation = exponential_equation(*coefficients, precision)
    elif equation_type == 'logarithmic':
        equation = logarithmic_equation(*coefficients, precision)
    elif equation_type == 'logistic':
        equation = logistic_equation(*coefficients, precision)
    elif equation_type == 'sinusoidal':
        equation = sinusoidal_equation(*coefficients, precision)

    # Round inputs
    rounded_inputs = []
    for point in inputs:
        if isinstance(point, (int, float)):
            rounded_inputs.append(rounded_value(point, precision))
        else:
            rounded_inputs.append(point)

    # Create empty lists
    outputs = []
    coordinates = []
    
    # Handle no points
    if rounded_inputs[0] == None:
        coordinates.append(None)
    
    # Fill outputs list with output value at each input
    else:
        for value in rounded_inputs:
            # Circumvent inaccurate rounding
            if point_type == 'intercepts':
                outputs.append(0.0)
            
            # Evaluate function at inputs
            else:
                # Evaluate numerical inputs
                if isinstance(value, (int, float)):
                    output = equation(value)
                    rounded_output = rounded_value(output, precision)
                    outputs.append(rounded_output)
                
                # Handle non-numerical inputs
                else:
                    outputs.append(outputs[0])

        # Unite inputs and outputs for maxima into single list
        coordinates.extend(unite_vectors(rounded_inputs, outputs))
    
    # Return final coordinate pairs
    return coordinates
Пример #28
0
def key_coordinates(equation_type, coefficients, precision = 4):
    """
    Calculates the key points of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which key points must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    ValueError
        First argument must be either 'linear', 'quadratic', 'cubic', 'hyperbolic', 'exponential', 'logarithmic', 'logistic', or 'sinusoidal'
    TypeError
        Second argument must be a 1-dimensional list containing elements that are integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    points['roots'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a root; second elements of those lists will be 0; if the function is sinusoidal, then only the initial results within a four-period interval will be listed, but general forms will also be included; if the function has no roots, then it will return a list of `None`
    points['maxima'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a relative maximum; second elements of those lists will be the y-coordinate of that maximum; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no maxima, then it will return a list of `None`
    points['minima'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a relative minimum; second elements of those lists will be the y-coordinate of that minimum; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no minima, then it will return a list of `None`
    points['inflections'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has an inflection; second elements of those lists will be the y-coordinate of that inflection; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no inflection points, then it will return a list of `None`

    See Also
    --------
    - Roots for key functions: :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.analyses.roots.quadratic.quadratic_roots`, :func:`~regressions.analyses.roots.cubic.cubic_roots`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.analyses.roots.exponential.exponential_roots`, :func:`~regressions.analyses.roots.logarithmic.logarithmic_roots`, :func:`~regressions.analyses.roots.logistic.logistic_roots`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`
    - Graphical analysis: :func:`~regressions.analyses.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.maxima.maxima_points`, :func:`~regressions.analyses.minima.minima_points`, :func:`~regressions.analyses.extrema.extrema_points`, :func:`~regressions.analyses.inflections.inflection_points`

    Notes
    -----
    - Key points include x-intercepts, maxima, minima, and points of inflection
    - |intercepts|
    - |extrema|
    - |inflections|

    Examples
    --------
    Import `key_coordinates` function from `regressions` library
        >>> from regressions.analyses.points import key_coordinates
    Calculate the key points of a cubic function with coefficients 1, -15, 63, and -7
        >>> points_cubic = key_coordinates('cubic', [1, -15, 63, -7])
        >>> print(points_cubic['roots'])
        [[0.1142, 0.0]]
        >>> print(points_cubic['maxima'])
        [[3.0, 74.0]]
        >>> print(points_cubic['minima'])
        [[7.0, 42.0]]
        >>> print(points_cubic['inflections'])
        [[5.0, 58.0]]
    Calculate the key points of a sinusoidal function with coefficients 2, 3, 5, and 1
        >>> points_sinusoidal = key_coordinates('sinusoidal', [2, 3, 5, 1])
        >>> print(points_sinusoidal['roots'])
        [[4.8255, 0.0], [6.2217, 0.0], [6.9199, 0.0], [8.3161, 0.0], [9.0143, 0.0], [10.4105, 0.0], [11.1087, 0.0], [12.5049, 0.0], [13.203, 0.0], [14.5993, 0.0], ['4.8255 + 2.0944k', 0.0], ['6.2217 + 2.0944k', 0.0]]
        >>> print(points_sinusoidal['maxima'])
        [[5.5236, 3.0], [7.618, 3.0], [9.7124, 3.0], ['5.5236 + 2.0944k', 3.0]]
        >>> print(points_sinusoidal['minima'])
        [[6.5708, -1.0], [8.6652, -1.0], ['6.5708 + 2.0944k', -1.0]]
        >>> print(points_sinusoidal['inflections'])
        [[5.0, 1.0], [6.0472, 1.0], [7.0944, 1.0], [8.1416, 1.0], [9.1888, 1.0001], ['5.0 + 1.0472k', 1.0]]
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)
    
    # Create lists of inputs
    intercepts_inputs = intercept_points(equation_type, coefficients, precision)
    extrema_inputs = extrema_points(equation_type, coefficients, precision)
    maxima_inputs = extrema_inputs['maxima']
    minima_inputs = extrema_inputs['minima']
    inflections_inputs = inflection_points(equation_type, coefficients, precision)

    # Generate coordinate pairs for all x-intercepts
    intercepts_coordinates = coordinate_pairs(equation_type, coefficients, intercepts_inputs, 'intercepts', precision)
    
    # Generate coordinate pairs for all maxima
    maxima_coordinates = coordinate_pairs(equation_type, coefficients, maxima_inputs, 'maxima', precision)
    
    # Generate coordinate pairs for all minima
    minima_coordinates = coordinate_pairs(equation_type, coefficients, minima_inputs, 'minima', precision)
    
    # Generate coordinate pairs for all points of inflection
    inflections_coordinates = coordinate_pairs(equation_type, coefficients, inflections_inputs, 'inflections', precision)
    
    # Create dictionary to return
    result = {
        'roots': intercepts_coordinates,
        'maxima': maxima_coordinates,
        'minima': minima_coordinates,
        'inflections': inflections_coordinates
    }
    return result
Пример #29
0
def sinusoidal_derivatives(first_constant,
                           second_constant,
                           third_constant,
                           fourth_constant,
                           precision=4):
    """
    Calculates the first and second derivatives of a sinusoidal function

    Parameters
    ----------
    first_constant : int or float
        Vertical stretch factor of the original sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    second_constant : int or float
        Horizontal stretch factor of the original sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    third_constant : int or float
        Horizontal shift of the original sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    fourth_constant : int or float
        Vertical shift of the original sine function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the resultant roots

    Raises
    ------
    TypeError
        First four arguments must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    derivatives['first']['constants'] : list of float
        Coefficients of the resultant first derivative
    derivatives['first']['evaluation'] : func
        Function for evaluating the resultant first derivative at any float or integer argument
    derivatives['second']['constants'] : list of float
        Coefficients of the resultant second derivative
    derivatives['second']['evaluation'] : func
        Function for evaluating the resultant second derivative at any float or integer argument

    See Also
    --------
    :func:`~regressions.analyses.equations.sinusoidal.sinusoidal_equation`, :func:`~regressions.analyses.integrals.sinusoidal.sinusoidal_integral`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`, :func:`~regressions.models.sinusoidal.sinusoidal_model`

    Notes
    -----
    - Standard form of a sinusoidal function: :math:`f(x) = a\\cdot{\\sin(b\\cdot(x - c))} + d`
    - First derivative of a sinusoidal function: :math:`f'(x) = ab\\cdot{\\cos(b\\cdot(x - c))}`
    - Second derivative of a sinusoidal function: :math:`f''(x) = -ab^2\\cdot{\\sin(b\\cdot(x - c))}`
    - |differentiation_formulas|
    - |chain_rule|
    - |trigonometric|

    Examples
    --------
    Import `sinusoidal_derivatives` function from `regressions` library
        >>> from regressions.analyses.derivatives.sinusoidal import sinusoidal_derivatives
    Generate the derivatives of a sinusoidal function with coefficients 2, 3, 5, and 7, then display the coefficients of its first and second derivatives
        >>> derivatives_constants = sinusoidal_derivatives(2, 3, 5, 7)
        >>> print(derivatives_constants['first']['constants'])
        [6.0, 3.0, 5.0]
        >>> print(derivatives_constants['second']['constants'])
        [-18.0, 3.0, 5.0]
    Generate the derivatives of a sinusoidal function with coefficients 7, -5, -3, and 2, then evaluate its first and second derivatives at 10
        >>> derivatives_evaluation = sinusoidal_derivatives(7, -5, -3, 2)
        >>> print(derivatives_evaluation['first']['evaluation'](10))
        19.6859
        >>> print(derivatives_evaluation['second']['evaluation'](10))
        144.695
    Generate the derivatives of a sinusoidal function with all inputs set to 0, then display the coefficients of its first and second derivatives
        >>> derivatives_zeroes = sinusoidal_derivatives(0, 0, 0, 0)
        >>> print(derivatives_zeroes['first']['constants'])
        [0.0001, 0.0001, 0.0001]
        >>> print(derivatives_zeroes['second']['constants'])
        [-0.0001, 0.0001, 0.0001]
    """
    # Handle input errors
    four_scalars(first_constant, second_constant, third_constant,
                 fourth_constant)
    positive_integer(precision)
    coefficients = no_zeroes(
        [first_constant, second_constant, third_constant, fourth_constant],
        precision)

    # Create first derivative
    first_coefficients = [
        coefficients[0] * coefficients[1], coefficients[1], coefficients[2]
    ]
    first_constants = rounded_list(first_coefficients, precision)

    def first_derivative(variable):
        evaluation = first_constants[0] * cos(first_constants[1] *
                                              (variable - first_constants[2]))
        rounded_evaluation = rounded_value(evaluation, precision)
        return rounded_evaluation

    first_dictionary = {
        'constants': first_constants,
        'evaluation': first_derivative
    }

    # Create second derivative
    second_coefficients = [
        -1 * first_constants[0] * first_constants[1], first_constants[1],
        first_constants[2]
    ]
    second_constants = rounded_list(second_coefficients, precision)

    def second_derivative(variable):
        evaluation = second_constants[0] * sin(
            second_constants[1] * (variable - second_constants[2]))
        rounded_evaluation = rounded_value(evaluation, precision)
        return rounded_evaluation

    second_dictionary = {
        'constants': second_constants,
        'evaluation': second_derivative
    }

    # Package both derivatives in single dictionary
    results = {'first': first_dictionary, 'second': second_dictionary}
    return results
Пример #30
0
def hyperbolic_derivatives(first_constant, second_constant, precision=4):
    """
    Calculates the first and second derivatives of a hyperbolic function

    Parameters
    ----------
    first_constant : int or float
        Coefficient of the reciprocal variable of the original hyperbolic function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    second_constant : int or float
        Coefficient of the constant term of the original hyperbolic function; if zero, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the resultant roots

    Raises
    ------
    TypeError
        First two arguments must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    derivatives['first']['constants'] : list of float
        Coefficients of the resultant first derivative
    derivatives['first']['evaluation'] : func
        Function for evaluating the resultant first derivative at any float or integer argument; if zero inputted as argument, it will be converted to a small, non-zero decimal value (e.g., 0.0001)
    derivatives['second']['constants'] : list of float
        Coefficients of the resultant second derivative
    derivatives['second']['evaluation'] : func
        Function for evaluating the resultant second derivative at any float or integer argument; if zero inputted as argument, it will be converted to a small, non-zero decimal value (e.g., 0.0001)

    See Also
    --------
    :func:`~regressions.analyses.equations.hyperbolic.hyperbolic_equation`, :func:`~regressions.analyses.integrals.hyperbolic.hyperbolic_integral`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.models.hyperbolic.hyperbolic_model`

    Notes
    -----
    - Standard form of a hyperbolic function: :math:`f(x) = a\\cdot{\\frac{1}{x}} + b`
    - First derivative of a hyperbolic function: :math:`f'(x) = -a\\cdot{\\frac{1}{x^2}}`
    - Second derivative of a hyperbolic function: :math:`f''(x) = 2a\\cdot{\\frac{1}{x^3}}`
    - |differentiation_formulas|

    Examples
    --------
    Import `hyperbolic_derivatives` function from `regressions` library
        >>> from regressions.analyses.derivatives.hyperbolic import hyperbolic_derivatives
    Generate the derivatives of a hyperbolic function with coefficients 2 and 3, then display the coefficients of its first and second derivatives
        >>> derivatives_constants = hyperbolic_derivatives(2, 3)
        >>> print(derivatives_constants['first']['constants'])
        [-2.0]
        >>> print(derivatives_constants['second']['constants'])
        [4.0]
    Generate the derivatives of a hyperbolic function with coefficients -2 and 3, then evaluate its first and second derivatives at 10
        >>> derivatives_evaluation = hyperbolic_derivatives(-2, 3)
        >>> print(derivatives_evaluation['first']['evaluation'](10))
        0.02
        >>> print(derivatives_evaluation['second']['evaluation'](10))
        -0.004
    Generate the derivatives of a hyperbolic function with all inputs set to 0, then display the coefficients of its first and second derivatives
        >>> derivatives_zeroes = hyperbolic_derivatives(0, 0)
        >>> print(derivatives_zeroes['first']['constants'])
        [-0.0001]
        >>> print(derivatives_zeroes['second']['constants'])
        [0.0002]
    """
    # Handle input errors
    two_scalars(first_constant, second_constant)
    positive_integer(precision)
    coefficients = no_zeroes([first_constant, second_constant], precision)

    # Create first derivative
    first_constants = [-1 * coefficients[0]]

    def first_derivative(variable):
        # Circumvent division by zero
        if variable == 0:
            variable = 10**(-precision)
        evaluation = first_constants[0] / variable**2
        rounded_evaluation = rounded_value(evaluation, precision)
        return rounded_evaluation

    first_dictionary = {
        'constants': first_constants,
        'evaluation': first_derivative
    }

    # Create second derivative
    second_constants = [-2 * first_constants[0]]

    def second_derivative(variable):
        # Circumvent division by zero
        if variable == 0:
            variable = 10**(-precision)
        evaluation = second_constants[0] / variable**3
        rounded_evaluation = rounded_value(evaluation, precision)
        return rounded_evaluation

    second_dictionary = {
        'constants': second_constants,
        'evaluation': second_derivative
    }

    # Package both derivatives in single dictionary
    results = {'first': first_dictionary, 'second': second_dictionary}
    return results