code: def graphical_distance(model, points, **kwds):
      """find the ``radius(x')`` that minimizes the graph between reality (data),
      ``y = G(x)``, and an approximating function, ``y' = F(x')``.
  
      Args:
          model (func): a model ``y' = F(x')`` that approximates reality ``y = G(x)``
          points (mystic.math.legacydata.dataset): a dataset, defines ``y = G(x)``
          ytol (float, default=0.0): maximum acceptable difference ``|y - F(x')|``.
          xtol (float, default=0.0): maximum acceptable difference ``|x - x'|``.
          cutoff (float, default=ytol): zero out distances less than cutoff.
          hausdorff (bool, default=False): hausdorff ``norm``, where if given,
              then ``ytol = |y - F(x')| + |x - x'|/norm``.
  
      Returns:
          the radius (the minimum distance ``x,G(x)`` to ``x',F(x')`` for each ``x``)
  
      Notes:
          *points* can be a ``mystic.math.legacydata.dataset`` or a list of
          ``mystic.math.legacydata.datapoint`` objects.
  
          *xtol* defines the n-dimensional base of a pilar of height *ytol*,
          centered at each point. The region inside the pilar defines the space
          where a "valid" model must intersect. If *xtol* is not specified, then
          the base of the pilar will be a dirac at ``x' = x``. This function
          performs an optimization for each ``x`` to find an appropriate ``x'``.
  
          *ytol* is a single value, while *xtol* is a single value or an iterable.
          *cutoff* takes a float or a boolean, where ``cutoff=True`` will set the
          value of *cutoff* to the default. Typically, the value of *cutoff* is
          *ytol*, 0.0, or None. *hausdorff* can be False (e.g. ``norm = 1.0``),
          True (e.g. ``norm = spread(x)``), or a list of points of ``len(x)``.
  
          While *cutoff* and *ytol* are very tightly related, they play a distinct
          role; *ytol* is used to set the optimization termination for an acceptable
          ``|y - F(x')|``, while *cutoff* is applied post-optimization.
  
          If we are using the hausdorff norm, then *ytol* will set the optimization
          termination for an acceptable ``|y - F(x')| + |x - x'|/norm``, where the
          ``x`` values are normalized by ``norm = hausdorff``."""  # FIXME: update docs to show normalization in y
      # NotImplemented:
      # L = list of lipschitz constants, for use when lipschitz metric is desired
      # constraints = constraints function for finding minimum distance
      from mystic.math.legacydata import dataset
      from numpy import asarray, sum, isfinite, zeros, seterr
      from mystic.solvers import diffev2, fmin_powell
      from mystic.monitors import Monitor, VerboseMonitor
  
      # ensure target xe and ye is a dataset
      target = dataset()
      target.load(*_get_xy(points))
      nyi = target.npts  # y's are target.values
      nxi = len(target.coords[-1])  # nxi = len(x) / len(y)
  
      # NOTE: the constraints function is a function over a single xe,ye
      #       because each underlying optimization is over a single xe,ye.
      #       thus, we 'pass' on using constraints at this time...
      constraints = None  # default is no constraints
      if "constraints" in kwds:
          constraints = kwds.pop("constraints")
      if not constraints:  # if None (default), there are no constraints
          constraints = lambda x: x
  
      # get tolerance in y and wiggle room in x
      ytol = kwds.pop("ytol", 0.0)
      xtol = kwds.pop(
          "xtol", 0.0
      )  # default is to not allow 'wiggle room' in x
  
      cutoff = (
          ytol  # default is to zero out distances less than tolerance
      )
      if "cutoff" in kwds:
          cutoff = kwds.pop("cutoff")
      if cutoff is True:
          cutoff = ytol
      elif cutoff is False:
          cutoff = None
      ipop = kwds.pop("ipop", min(20, 3 * nxi))  # XXX: tune ipop?
      imax = kwds.pop("imax", 1000)  # XXX: tune imax?
  
      # get range for the dataset (normalization for hausdorff distance)
      hausdorff = kwds.pop("hausdorff", False)
      if not hausdorff:  # False, (), None, ...
          ptp = [0.0] * nxi
          yptp = 1.0
      elif hausdorff is True:
          from mystic.math.measures import spread
  
          ptp = [spread(xi) for xi in zip(*target.coords)]
          yptp = spread(
              target.values
          )  # XXX: this can lead to bad bad things...
      else:
          try:  # iterables
              if len(hausdorff) < nxi + 1:
                  hausdorff = (
                      list(hausdorff)
                      + [0.0] * (nxi - len(hausdorff))
                      + [1.0]
                  )
              ptp = hausdorff[:-1]  # all the x
              yptp = hausdorff[-1]  # just the y
          except TypeError:  # non-iterables
              ptp = [hausdorff] * nxi
              yptp = hausdorff
  
      #########################################################################
      def radius(
          model, point, ytol=0.0, xtol=0.0, ipop=None, imax=None
      ):
          """graphical distance between a single point x,y and a model F(x')"""
          # given a single point x,y: find the radius = |y - F(x')| + delta
          # radius is just a minimization over x' of |y - F(x')| + delta
          # where we apply a constraints function (of box constraints) of
          # |x - x'| <= xtol  (for each i in x)
          #
          # if hausdorff = some iterable, delta = |x - x'|/hausdorff
          # if hausdorff = True, delta = |x - x'|/spread(x); using the dataset range
          # if hausdorff = False, delta = 0.0
          #
          # if ipop, then DE else Powell; ytol is used in VTR(ytol)
          # and will terminate when cost <= ytol
          x, y = _get_xy(point)
          y = asarray(y)
          # catch cases where yptp or y will cause issues in normalization
          # if not isfinite(yptp): return 0.0 #FIXME: correct?  shouldn't happen
          # if yptp == 0: from numpy import inf; return inf #FIXME: this is bad
  
          # build the cost function
          if hausdorff:  # distance in all directions
  
              def cost(rv):
                  """cost = |y - F(x')| + |x - x'| for each x,y (point in dataset)"""
                  _y = model(rv)
                  if not isfinite(_y):
                      return abs(_y)
                  errs = seterr(
                      invalid="ignore", divide="ignore"
                  )  # turn off warning
                  z = abs((asarray(x) - rv) / ptp)  # normalize by range
                  m = abs(y - _y) / yptp  # normalize by range
                  seterr(
                      invalid=errs["invalid"], divide=errs["divide"]
                  )  # turn on warning
                  return m + sum(z[isfinite(z)])
  
          else:  # vertical distance only
  
              def cost(rv):
                  """cost = |y - F(x')| for each x,y (point in dataset)"""
                  return abs(y - model(rv))
  
          if debug:
              print("rv: %s" % str(x))
              print("cost: %s" % cost(x))
  
          # if xtol=0, radius is difference in x,y and x,F(x); skip the optimization
          try:
              if not imax or not max(xtol):  # iterables
                  return cost(x)
          except TypeError:
              if not xtol:  # non-iterables
                  return cost(x)
  
          # set the range constraints
          xtol = asarray(xtol)
          bounds = list(zip(x - xtol, x + xtol))
  
          if debug:
              print("lower: %s" % str(zip(*bounds)[0]))
              print("upper: %s" % str(zip(*bounds)[1]))
  
          # optimize where initially x' = x
          stepmon = Monitor()
          if debug:
              stepmon = VerboseMonitor(1)
          # XXX: edit settings?
          MINMAX = 1  # XXX: confirm MINMAX=1 is minimization
          ftol = ytol
          gtol = None  # use VTRCOG
          if ipop:
              results = diffev2(
                  cost,
                  bounds,
                  ipop,
                  ftol=ftol,
                  gtol=gtol,
                  itermon=stepmon,
                  maxiter=imax,
                  bounds=bounds,
                  full_output=1,
                  disp=0,
                  handler=False,
              )
          else:
              results = fmin_powell(
                  cost,
                  x,
                  ftol=ftol,
                  gtol=gtol,
                  itermon=stepmon,
                  maxiter=imax,
                  bounds=bounds,
                  full_output=1,
                  disp=0,
                  handler=False,
              )
          # solved = results[0]            # x'
          func_opt = MINMAX * results[1]  # cost(x')
          if debug:
              print("solved: %s" % results[0])
              print("cost: %s" % func_opt)
  
          # get the minimum distance |y - F(x')|
          return func_opt
  
      # return results[0], func_opt
      #########################################################################
  
      # XXX: better to do a single optimization rather than for each point ???
      d = [
          radius(model, point, ytol, xtol, ipop, imax)
          for point in target
      ]
      return infeasibility(d, cutoff)
  
file_path: mystic/mystic/math/distance.py
label_desc: Use image node_id 14 for calling a global function with example usage: graphical_distance(model, points) and returns: infeasibility, func_opt, unknown, abs, cost, abs, cost