<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def compute_sub_structure(self, sub_structure, tol=1e-3):
 """ Gives total ewald energy for an sub structure in the same lattice. The sub_structure must be a subset of the original structure, with possible different charges. Args: substructure (Structure):
 Substructure to compute Ewald sum for. tol (float):
 Tolerance for site matching in fractional coordinates. Returns: Ewald sum of substructure. """

        total_energy_matrix = self.total_energy_matrix.copy()

        def find_match(site):
            for test_site in sub_structure:
                frac_diff = abs(np.array(site.frac_coords)
                                - np.array(test_site.frac_coords)) % 1
                frac_diff = [abs(a) < tol or abs(a) > 1 - tol
                             for a in frac_diff]
                if all(frac_diff):
                    return test_site
            return None

        matches = []
        for i, site in enumerate(self._s):
            matching_site = find_match(site)
            if matching_site:
                new_charge = compute_average_oxidation_state(matching_site)
                old_charge = self._oxi_states[i]
                scaling_factor = new_charge / old_charge
                matches.append(matching_site)
            else:
                scaling_factor = 0
            total_energy_matrix[i, :] *= scaling_factor
            total_energy_matrix[:, i] *= scaling_factor

        if len(matches) != len(sub_structure):
            output = ["Missing sites."]
            for site in sub_structure:
                if site not in matches:
                    output.append("unmatched = {}".format(site))
            raise ValueError("\n".join(output))

        return sum(sum(total_energy_matrix))