<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def network_lopf(network, snapshots=None, solver_name="glpk", solver_io=None, skip_pre=False, extra_functionality=None, solver_logfile=None, solver_options={}, keep_files=False, formulation="angles", ptdf_tolerance=0., free_memory={},extra_postprocessing=None):
 """ Linear optimal power flow for a group of snapshots. Parameters snapshots : list or index slice A list of snapshots to optimise, must be a subset of network.snapshots, defaults to network.snapshots solver_name : string Must be a solver name that pyomo recognises and that is installed, e.g. "glpk", "gurobi" solver_io : string, default None Solver Input-Output option, e.g. "python" to use "gurobipy" for solver_name="gurobi" skip_pre: bool, default False Skip the preliminary steps of computing topology, calculating dependent values and finding bus controls. extra_functionality : callable function This function must take two arguments `extra_functionality(network,snapshots)` and is called after the model building is complete, but before it is sent to the solver. It allows the user to add/change constraints and add/change the objective function. solver_logfile : None|string If not None, sets the logfile option of the solver. solver_options : dictionary A dictionary with additional options that get passed to the solver. (e.g. {'threads':2} tells gurobi to use only 2 cpus) keep_files : bool, default False Keep the files that pyomo constructs from OPF problem construction, e.g. .lp file - useful for debugging formulation : string Formulation of the linear power flow equations to use; must be one of ["angles","cycles","kirchhoff","ptdf"] ptdf_tolerance : float Value below which PTDF entries are ignored free_memory : set, default {'pyomo'} Any subset of {'pypsa', 'pyomo'}. Allows to stash `pypsa` time-series data away while the solver runs (as a pickle to disk) and/or free `pyomo` data after the solution has been extracted. extra_postprocessing : callable function This function must take three arguments `extra_postprocessing(network,snapshots,duals)` and is called after the model has solved and the results are extracted. It allows the user to extract further information about the solution, such as additional shadow prices. Returns ------- None """


    snapshots = _as_snapshots(network, snapshots)

    network_lopf_build_model(network, snapshots, skip_pre=skip_pre,
                             formulation=formulation, ptdf_tolerance=ptdf_tolerance)

    if extra_functionality is not None:
        extra_functionality(network,snapshots)

    network_lopf_prepare_solver(network, solver_name=solver_name,
                                solver_io=solver_io)

    return network_lopf_solve(network, snapshots, formulation=formulation,
                              solver_logfile=solver_logfile, solver_options=solver_options,
                              keep_files=keep_files, free_memory=free_memory,
                              extra_postprocessing=extra_postprocessing)