<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def polymorph_response(response, poly, bqm, penalty_strength=None, keep_penalty_variables=True, discard_unsatisfied=False):
 """ Transforms the sampleset for the higher order problem. Given a response of a penalized HUBO, this function creates a new sampleset object, taking into account penalty information and calculates the energies of samples for the higherorder problem. Args: response (:obj:`.SampleSet`):
 response for a penalized hubo. poly (:obj:`.BinaryPolynomial`):
 A binary polynomial. bqm (:obj:`dimod.BinaryQuadraticModel`):
 Binary quadratic model of the reduced problem. penalty_strength (float, optional):
 default is None, if provided, will be added to the info field of the returned sampleSet object. keep_penalty_variables (bool, optional):
 default is True. if False will remove the variables used for penalty from the samples discard_unsatisfied (bool, optional):
 default is False. If True will discard samples that do not satisfy the penalty conditions. Returns: (:obj:`.SampleSet'):
 A sampleSet object that has additional penalty information. The energies of samples are calculated for the HUBO ignoring the penalty variables. """

    record = response.record
    penalty_vector = penalty_satisfaction(response, bqm)
    original_variables = bqm.variables

    if discard_unsatisfied:
        samples_to_keep = list(map(bool, list(penalty_vector)))
        penalty_vector = np.array([True] * np.sum(samples_to_keep))
    else:
        samples_to_keep = list(map(bool, [1] * len(record.sample)))

    samples = record.sample[samples_to_keep]
    energy_vector = poly.energies((samples, response.variables))

    if not keep_penalty_variables:
        original_variables = poly.variables
        idxs = [response.variables.index[v] for v in original_variables]
        samples = np.asarray(samples[:, idxs])

    num_samples, num_variables = np.shape(samples)

    datatypes = [('sample', np.dtype(np.int8), (num_variables,)),
                 ('energy', energy_vector.dtype),
                 ('penalty_satisfaction',
                  penalty_vector.dtype)]
    datatypes.extend((name, record[name].dtype, record[name].shape[1:])
                     for name in record.dtype.names if
                     name not in {'sample',
                                  'energy'})

    data = np.rec.array(np.empty(num_samples, dtype=datatypes))
    data.sample = samples
    data.energy = energy_vector
    for name in record.dtype.names:
        if name not in {'sample', 'energy'}:
            data[name] = record[name][samples_to_keep]

    data['penalty_satisfaction'] = penalty_vector
    response.info['reduction'] = bqm.info['reduction']
    if penalty_strength is not None:
        response.info['penalty_strength'] = penalty_strength
    return SampleSet(data, original_variables, response.info,
                     response.vartype)