0

Let f1 and f2 be two functions in the range of [a, b], and maxerr the required approximation. They both differentiable and continuous in this range. I should return an iterable of approximate intersection Xs, such that: ∀x∈Xs, |f_1(x) - f_2(x)| < maxerr.

The signature of the function for example should be:

def intersection(self, f1: callable, f2: callable, a: float, b: float, maxerr=0.001) -> callable:

What is the most profficient way to do that without using a library method that finds the intersection directly?

Notes:

  • Python 3.7
  • Forbidden build-in functions: finding roots and intersections of functions, interpolation, integration, matrix decomposition, eigenvectors and solving linear systems.

Right now my code is as the following:

def intersection_recursive(f1, f2, a, b, maxerr, X, start_time, timeout, side_flag):
  f = f1 - f2
    startX = a
    endX = b
    while not f(startX) * f(endX) < 0 and time.time() < start_time + timeout:
        startX = random.uniform(a, b)
        endX = random.uniform(startX, b)
    mid = (startX + endX) / 2
    while not abs(f(mid)) < maxerr and time.time() < start_time + timeout:
        if f(startX) * f(mid) < -1:
            endX = mid
        else:
            startX = mid
        mid = (startX + endX) / 2
    if abs(f(mid)) < maxerr:
        X.append(mid)
    else:
        return X
    if side_flag:
        return intersection_recursive(f1, f2, a, mid, maxerr, X, start_time, timeout, not side_flag)
    else:
        return intersection_recursive(f1, f2, mid, b, maxerr, X, start_time, timeout, not side_flag)

def intersection(self, f1: callable, f2: callable, a: float, b: float, maxerr=0.001) -> callable:
   timeout = 10
   X = []
   start_time = time.time()
   intersection_recursive(f1, f2, a, b, maxerr, X, start_time, timeout, True)
   return X

1 Answers1

0

The below answer is to the original question, where no assumptions about the functions are made...


Without any additional information about the functions the no free lunch theorem applies and any search strategy is as valid as any other.

That said, a simple quasirandom sequence covers all of [a, b] uniformly at every detail level, given enough time.

I don't think your function signature is correct by the way, it should return an iterable.

from typing import Callable, Iterable

def intersection(f1: Callable[[float], float],
                 f2: Callable[[float], float],
                 a: float, b: float,
                 maxerr: float=0.001) -> Iterable[float]:
   a, b = sorted([a, b])
   invphi = 2 / (1 + 5**0.5)
   t = 0.5
   while True:
       x = a + (b-a)*t
       if abs(f1(x) - f2(x)) < maxerr:
           yield x
       t = (t + invphi) % 1.0
orlp
  • 112,504
  • 36
  • 218
  • 315