Write a given model to file.

        Args:
            file: File-like object open for writing.
            model: Instance of :class:`NativeModel` to write.
            pretty: Whether to format the XML output for readability.

def write_model(self, file, model, pretty=False):
        """Write a given model to file.

        Args:
            file: File-like object open for writing.
            model: Instance of :class:`NativeModel` to write.
            pretty: Whether to format the XML output for readability.
        """
        ET.register_namespace('mathml', MATHML_NS)
        ET.register_namespace('xhtml', XHTML_NS)
        ET.register_namespace('fbc', FBC_V2)

        # Load compound information
        compound_name = {}
        compound_properties = {}
        for compound in model.compounds:
            compound_name[compound.id] = (
                compound.name if compound.name is not None else compound.id)
            compound_properties[compound.id] = compound.properties

        model_reactions = set(model.model)

        reaction_properties = {}
        biomass_id = None
        for r in model.reactions:
            if (model_reactions is not None and
                    r.id not in model_reactions):
                continue

            reaction_id = util.create_unique_id(
                self._make_safe_id(r.id), reaction_properties)
            if r.id == model.biomass_reaction:
                biomass_id = reaction_id

            reaction_properties[reaction_id] = r.properties

        # Add exchange reactions to reaction_properties,
        # also add flux limit info to flux_limits
        flux_limits = {}
        for compound, reaction_id, lower, upper in itervalues(model.exchange):
            # Create exchange reaction
            if reaction_id is None:
                reaction_id = create_exchange_id(reaction_properties, compound)
            reaction_id = util.create_unique_id(
                self._make_safe_id(reaction_id), reaction_properties)

            reaction_properties[reaction_id] = {
                'id': reaction_id,
                'equation': Reaction(Direction.Both, {compound: -1})
            }

            if lower is None:
                lower = -model.default_flux_limit
            if upper is None:
                upper = model.default_flux_limit
            flux_limits[reaction_id] = (lower, upper)

            # Create a dummy properties dict for undefined compounds
            if compound.name not in compound_properties:
                compound_properties[compound.name] = {
                    'id': compound.name
                }

        root = ET.Element(self._sbml_tag('sbml'))
        root.set(self._sbml_tag('level'), '3')
        root.set(self._sbml_tag('version'), '1')
        root.set(_tag('required', FBC_V2), 'false')
        if model.version_string is not None:
            notes_tag = ET.SubElement(root, self._sbml_tag('notes'))
            body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
            self._add_properties_notes(
                body_tag, {'model version': model.version_string})

        model_tag = ET.SubElement(root, self._sbml_tag('model'))
        model_tag.set(_tag('strict', FBC_V2), 'true')
        if model.name is not None:
            model_tag.set(self._sbml_tag('name'), model.name)

        # Build mapping from Compound to species ID
        model_compartments = {}
        model_species = {}
        species_ids = set()
        for _, properties in iteritems(reaction_properties):
            for compound, _ in properties['equation'].compounds:
                if compound in model_species:
                    continue

                # Create a dummy properties dict for undefined compounds
                if compound.name not in compound_properties:
                    compound_properties[compound.name] = {
                        'id': compound.name
                    }

                compound_id = util.create_unique_id(
                    self._make_safe_id(compound.name), species_ids)
                model_species[compound] = compound_id
                species_ids.add(compound_id)
                if compound.compartment not in model_compartments:
                    model_compartments[
                        compound.compartment] = 'C_' + util.create_unique_id(
                            self._make_safe_id(compound.compartment),
                            model_compartments)

        # Create list of compartments
        compartments = ET.SubElement(
            model_tag, self._sbml_tag('listOfCompartments'))
        for _, compartment_id in iteritems(model_compartments):
            compartment_tag = ET.SubElement(
                compartments, self._sbml_tag('compartment'))
            compartment_tag.set(self._sbml_tag('id'), compartment_id)
            compartment_tag.set(self._sbml_tag('constant'), 'true')

        # Create list of species
        species_list = ET.SubElement(
            model_tag, self._sbml_tag('listOfSpecies'))
        for species, species_id in sorted(
                iteritems(model_species), key=lambda x: x[1]):
            species_tag = ET.SubElement(species_list,
                                        self._sbml_tag('species'))
            species_tag.set(self._sbml_tag('id'), 'M_' + species_id)
            species_tag.set(
                self._sbml_tag('name'),
                compound_name.get(species.name, species.name))
            species_tag.set(
                self._sbml_tag('compartment'),
                model_compartments[species.compartment])
            species_tag.set(self._sbml_tag('constant'), 'false')
            species_tag.set(self._sbml_tag('boundaryCondition'), 'false')
            species_tag.set(self._sbml_tag('hasOnlySubstanceUnits'), 'true')
            if 'charge' in compound_properties[species.name]:
                species_tag.set(_tag('charge', FBC_V2), text_type(
                    compound_properties[species.name]['charge']))
            if 'formula' in compound_properties[species.name]:
                species_tag.set(_tag(
                    'chemicalFormula', FBC_V2), text_type(
                        compound_properties[species.name]['formula']))

            notes_tag = ET.SubElement(species_tag, self._sbml_tag('notes'))
            body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
            self._add_properties_notes(
                body_tag, compound_properties[species.name])

        params_list = ET.SubElement(
            model_tag, self._sbml_tag('listOfParameters'))

        # Create mapping for reactions containing flux limit definitions
        for rxn_id, lower_lim, upper_lim in itervalues(model.limits):
            flux_limits[rxn_id] = lower_lim, upper_lim

        params = {}
        gene_ids = {}

        if biomass_id is not None:
            self._add_fbc_objective(model_tag, biomass_id)

        # Create list of reactions
        reactions = ET.SubElement(model_tag, self._sbml_tag('listOfReactions'))
        for eq_id, properties in sorted(iteritems(reaction_properties)):
            reaction_tag = ET.SubElement(reactions, self._sbml_tag('reaction'))
            equation = properties['equation']

            reaction_tag.set(self._sbml_tag('id'), 'R_' + eq_id)
            if 'name' in properties:
                reaction_tag.set(self._sbml_tag('name'), properties['name'])
            reaction_tag.set(self._sbml_tag('reversible'), text_type(
                equation.direction == Direction.Both).lower())
            reaction_tag.set(self._sbml_tag('fast'), 'false')
            lower_str, upper_str = self._get_flux_bounds(
                eq_id, model, flux_limits, equation)

            params[upper_str] = 'P_'+self._make_safe_numerical_id(upper_str)
            params[lower_str] = 'P_'+self._make_safe_numerical_id(lower_str)
            reaction_tag.set(
                _tag('upperFluxBound', FBC_V2), params[upper_str])
            reaction_tag.set(
                _tag('lowerFluxBound', FBC_V2), params[lower_str])

            if 'genes' in properties:
                self._add_gene_associations(
                    eq_id, properties['genes'], gene_ids, reaction_tag)

            if any(value < 0 for _, value in equation.compounds):
                reactants = ET.SubElement(
                    reaction_tag, self._sbml_tag('listOfReactants'))

            if any(value > 0 for _, value in equation.compounds):
                products = ET.SubElement(
                    reaction_tag, self._sbml_tag('listOfProducts'))

            for compound, value in sorted(equation.compounds):
                dest_list = reactants if value < 0 else products
                spec_ref = ET.SubElement(
                    dest_list, self._sbml_tag('speciesReference'))
                spec_ref.set(
                    self._sbml_tag('species'), 'M_' + model_species[compound])
                spec_ref.set(
                    self._sbml_tag('constant'), 'true')
                spec_ref.set(
                    self._sbml_tag('stoichiometry'), text_type(abs(value)))

            notes_tag = ET.SubElement(reaction_tag, self._sbml_tag('notes'))
            body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
            self._add_properties_notes(body_tag, reaction_properties[eq_id])

            if self._cobra_flux_bounds is True:
                # Create COBRA-compliant parameter list
                kl_tag = ET.SubElement(
                    reaction_tag, self._sbml_tag('kineticLaw'))
                math_tag = ET.SubElement(kl_tag, self._sbml_tag('math'))
                ci_tag = ET.SubElement(math_tag, _tag('ci', MATHML_NS))
                ci_tag.text = 'FLUX_VALUE'
                param_list = ET.SubElement(
                    kl_tag, self._sbml_tag('listOfParameters'))

                ET.SubElement(param_list, self._sbml_tag('parameter'), {
                    self._sbml_tag('id'): 'LOWER_BOUND',
                    self._sbml_tag('name'): 'LOWER_BOUND',
                    self._sbml_tag('value'): lower_str,
                    self._sbml_tag('constant'): 'true'
                })
                ET.SubElement(param_list, self._sbml_tag('parameter'), {
                    self._sbml_tag('id'): 'UPPER_BOUND',
                    self._sbml_tag('name'): 'UPPER_BOUND',
                    self._sbml_tag('value'): upper_str,
                    self._sbml_tag('constant'): 'true'
                })

        for val, id in iteritems(params):
            param_tag = ET.SubElement(params_list, self._sbml_tag('parameter'))
            param_tag.set(self._sbml_tag('id'), id)
            param_tag.set(self._sbml_tag('value'), val)
            param_tag.set(self._sbml_tag('constant'), 'true')

        self._add_gene_list(model_tag, gene_ids)

        tree = ET.ElementTree(root)
        if pretty:
            self._indent(root)

        write_options = dict(
            encoding='utf-8',
            default_namespace=self._namespace)
        if PY3:
            write_options['encoding'] = 'unicode'
        tree.write(file, **write_options)