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
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
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
def test_generate_negative_periodic(self): generate_negative_periodic = generate_elements(5, -3) self.assertEqual(generate_negative_periodic, [5.0, 8.0, 11.0, 14.0, 17.0, '5.0 + 3.0k'])
def test_generate_floats(self): generate_floats = generate_elements(7.81259217, 3.12748261) self.assertEqual( generate_floats, [7.8126, 10.9401, 14.0676, 17.195, 20.3225, '7.8126 + 3.1275k'])
def test_generate_ints(self): generate_ints = generate_elements(2, 3) self.assertEqual(generate_ints, [2.0, 5.0, 8.0, 11.0, 14.0, '2.0 + 3.0k'])
def sinusoidal_roots(first_constant, second_constant, third_constant, fourth_constant, precision = 4): """ Calculates the roots 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 ------- roots : list of float or str List of the x-coordinates of the initial x-intercepts within two periods of the original function in float format, along with the general forms in string format that can be used to determine all other x-intercepts by plugging in any integer value for 'k' and evaluating; if the function never crosses the x-axis, then it will return a list of `None` See Also -------- :func:`~regressions.analyses.equations.sinusoidal.sinusoidal_equation`, :func:`~regressions.analyses.derivatives.sinusoidal.sinusoidal_derivatives`, :func:`~regressions.analyses.integrals.sinusoidal.sinusoidal_integral`, :func:`~regressions.models.sinusoidal.sinusoidal_model` Notes ----- - Standard form of a sinusoidal function: :math:`f(x) = a\\cdot{\\sin(b\\cdot(x - c))} + d` - Sinusoidal formula: :math:`x_0 = c + \\frac{1}{b}\\cdot{\\sin^{-1}(-\\frac{d}{a})} + \\frac{2\\pi}{b}\\cdot{k}` - :math:`\\text{if} -1 < -\\frac{d}{a} < 0 \\text{ or } 0 < -\\frac{d}{a} < 1, x_1 = c + \\frac{\\pi}{b} - \\frac{1}{b}\\cdot{\\sin^{-1}(-\\frac{d}{a})} + \\frac{2\\pi}{b}\\cdot{k}` - :math:`\\text{if} -\\frac{d}{a} = 0, x_1 = c - \\frac{\\pi}{b} + \\frac{2\\pi}{b}\\cdot{k}` - :math:`k \\in \\mathbb{Z}` Examples -------- Import `sinusoidal_roots` function from `regressions` library >>> from regressions.analyses.roots.sinusoidal import sinusoidal_roots Calculate the roots of a sinusoidal function with coefficients 2, 3, 5, and 7 >>> roots_first = sinusoidal_roots(2, 3, 5, 7) >>> print(roots_first) [None] Calculate the roots of a sinusoidal function with coefficients 7, -5, -3, and 2 >>> roots_second = sinusoidal_roots(7, -5, -3, 2) >>> print(roots_second) [-8.7128, -7.9686, -7.4562, -6.712, -6.1995, -5.4553, -4.9429, -4.1987, -3.6863, -2.942, '-3.6863 + 1.2566k', '-2.942 + 1.2566k'] Calculate the roots of a sinusoidal function with all inputs set to 0 >>> roots_zeroes = sinusoidal_roots(0, 0, 0, 0) >>> print(roots_zeroes) [-15707.9632, 47123.8899, 109955.743, 172787.596, 235619.4491, '-15707.9632 + 62831.8531k'] """ # 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 list for roots roots = [] # Identify key ratio ratio = -1 * coefficients[3] / coefficients[0] # Handle no roots if ratio > 1 or ratio < -1: roots = [None] # Handle multiple roots else: # Create intermediary variables radians = asin(ratio) periodic_radians = radians / coefficients[1] # Determine pertinent values periodic_unit = 2 * pi / coefficients[1] initial_value = coefficients[2] + periodic_radians roots = generate_elements(initial_value, 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: # Determine supplementary values alternative_initial_value = coefficients[2] + pi / coefficients[1] - periodic_radians generated_elements = generate_elements(alternative_initial_value, periodic_unit, precision) # Add additional results to roots list 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 = rounded_roots + sorted_other_roots return result