code: def _classify_variables(constraints, variables="x", nvars=None):
      """Takes a string of constraint equations and determines which variables
      are dependent, independent, and unconstrained. Assumes there are no duplicate
      equations. Returns a dictionary with keys: 'dependent', 'independent', and
      'unconstrained', and with values that enumerate the variables that match
      each variable type.
  
      Args:
          constraints (str): a string of symbolic constraints, with one constraint
              equation per line. Constraints must be equality constraints only.
              Standard python syntax should be followed (the ``math`` and ``numpy``
              modules are already imported).
          variables (str, default='x'): desired variable name. A list of variable
              name strings is also accepted for when desired variable names
              don't have the same base, and can include variables that are not
              found in the constraints equation string.
          nvars (int, default=None): number of variables. Includes variables not
              explicitly stated in the constraints (e.g. ``x1`` in the example below).
  
      Examples:
          >>> constraints = '''
          ...     x0 = x4**2
          ...     x2 = x3 + x4'''
          >>> _classify_variables(constraints, nvars=5)
          {'dependent':['x0','x2'], 'independent':['x3','x4'], 'unconstrained':['x1']}
  
          >>> constraints = '''
          ...     x0 = x4**2
          ...     x4 - x3 = 0.
          ...     x4 - x0 = x2'''
          >>> _classify_variables(constraints, nvars=5)
          {'dependent': ['x0','x2','x4'], 'independent': ['x3'], 'unconstrained': ['x1']}
      """
      if ">" in constraints or "<" in constraints:
          raise NotImplementedError("cannot classify inequalities")
  
      from mystic.symbolic import replace_variables, get_variables
  
      # XXX: use solve? or first if not in form xi = ... ?
      if list_or_tuple_or_ndarray(variables):
          if nvars is not None:
              variables = variables[:nvars]
          constraints = replace_variables(constraints, variables)
          varname = "$"
          ndim = len(variables)
      else:
          varname = variables  # varname used below instead of variables
          myvar = get_variables(constraints, variables)
          if myvar:
              ndim = max([int(v.strip(varname)) for v in myvar]) + 1
          else:
              ndim = 0
      if nvars is not None:
          ndim = nvars
  
      eqns = constraints.splitlines()
      indices = list(range(ndim))
      dep = []
      indep = []
      for eqn in eqns:  # find which variables are used
          if eqn:
              for var in range(ndim):
                  if indices.count(var) != 0:
                      if eqn.find(varname + str(var)) != -1:
                          indep.append(var)
                          indices.remove(var)
      indep.sort()
      _dep = []
      for eqn in eqns:  # find which variables are on the LHS
          if eqn:
              split = eqn.split("=")
              for var in indep:
                  if split[0].find(varname + str(var)) != -1:
                      _dep.append(var)
                      indep.remove(var)
                      break
      _dep.sort()
      indep = _dep + indep  # prefer variables found on LHS
      for eqn in eqns:  # find one dependent variable per equation
          _dep = []
          _indep = indep[:]
          if eqn:
              for var in _indep:
                  if eqn.find(varname + str(var)) != -1:
                      _dep.append(var)
                      _indep.remove(var)
          if _dep:
              dep.append(_dep[0])
              indep.remove(_dep[0])
      # FIXME: 'equivalent' equations not ignored (e.g. x2=x2; or x2=1, 2*x2=2)
      """These are good:
      >>> constraints = '''
      ...     x0 = x4**2
      ...     x2 - x4 - x3 = 0.'''
      >>> _classify_variables(constraints, nvars=5)
      {'dependent': ['x0','x2'], 'independent': ['x3','x4'], 'unconstrained': ['x1']}
      >>> constraints = '''
      ...     x0 + x2 = 0.
      ...     x0 + 2*x2 = 0.'''
      >>> _classify_variables(constraints, nvars=5)
      {'dependent': ['x0','x2'], 'independent': [], 'unconstrained': ['x1','x3','x4']}
  
      This is a bug:
      >>> constraints = '''
      ...     x0 + x2 = 0.
      ...     2*x0 + 2*x2 = 0.'''
      >>> _classify_variables(constraints, nvars=5)
      {'dependent': ['x0','x2'], 'independent': [], 'unconstrained': ['x1','x3','x4']}
      """  # XXX: should simplify first?
      dep.sort()
      indep.sort()
      # return the actual variable names (not the indices)
      if varname == variables:  # then was single variable
          variables = [varname + str(i) for i in range(ndim)]
      dep = [variables[i] for i in dep]
      indep = [variables[i] for i in indep]
      indices = [variables[i] for i in indices]
      d = {
          "dependent": dep,
          "independent": indep,
          "unconstrained": indices,
      }
      return d
  
file_path: mystic/mystic/_symbolic.py
imports: from mystic.tools import permutations
  from mystic.tools import list_or_tuple_or_ndarray
label_desc: Use image node_id 1 for calling a global function with example usage: _classify_variables(constraints, variables, nvars) and returns: d