human
Complete this python program:
def _populate_grad_dict(var_to_app_to_idx, grad_dict, wrt, cost_name=None):
assistant
#Here is the Python program you requested.

    """Helper function for grad function.
    Parameters
    var_to_app_to_idx : dict
    a dictionary mapping a variable to a second dictionary.
    the second dictionary maps apply nodes acting on
    this variable to the variable\s index in the apply
    node\s input list
    grad_dict : dict
    A dictionary mapping variables to their gradients.
    Should be populated by grad function, which should:
    - Set the gradient with respect to the cost to 1
    - Load all gradients from known_grads, possibly
    overriding the cost
    - Set the gradient for disconnected
    inputs to a variable with type DisconnectedType()
    wrt : list of Variables
    the minimal set of variables that must be included in `grad_dict`
    cost_name: string
    The name of the cost being differentiated, optional.
    Used to name the grad with respect to x as (d<cost_name>/dx)
    Returns
    list of Variables
    A list of gradients corresponding to `wrt`
    """
    term_dict = OrderedDict()
    def access_term_cache(node):
        '    Populates    term_dict[node]    and    returns    it    '
        if (node not in term_dict):
            inputs = node.inputs
            output_grads = [access_grad_cache(var) for var in node.outputs]
            outputs_connected = [(not isinstance(g.type, DisconnectedType)) for g in output_grads]
            connection_pattern = _node_to_pattern(node)
            inputs_connected = [(True in [(input_to_output and output_to_cost) for (input_to_output, output_to_cost) in zip(input_to_outputs, outputs_connected)]) for input_to_outputs in connection_pattern]
            output_is_int = [(hasattr(output.type, 'dtype') and (output.type.dtype in theano.tensor.discrete_dtypes)) for output in node.outputs]
            ograd_is_nan = [isinstance(output.type, NullType) for output in output_grads]
            only_connected_to_nan = [(True not in [(in_to_out and out_to_cost and (not out_nan)) for (in_to_out, out_to_cost, out_nan) in zip(in_to_outs, outputs_connected, ograd_is_nan)]) for in_to_outs in connection_pattern]
            if (True not in inputs_connected):
                input_grads = [disconnected_type() for ipt in inputs]
            elif (False not in only_connected_to_nan):
                input_grads = []
                for connected in inputs_connected:
                    if connected:
                        input_grads.append(null_type())
                    else:
                        input_grads.append(disconnected_type())
            else:
                try:
                    dinputs = [node.inputs[x[0]] for x in itervalues(node.op.destroy_map)]
                except AttributeError:
                    dinputs = []
                def try_to_copy_if_needed(var):
                    if ((var in dinputs) and hasattr(var, 'copy')):
                        return var.copy()
                    return var
                inputs = [try_to_copy_if_needed(ipt) for ipt in inputs]
                new_output_grads = []
   ...