Example #1
0
def test_mcmc_algorithm_1_2x2_elber():
    """
    Test a simple 2x2 Elber system to ensure that the correct matrices
    are generated and sampled. Optionally generate a plot showing this.
    """
    max_x = 3.0 * 12.0 / 500.0
    max_y = 3.0 * 30.0 / 150.0
    N = np.array([[0, 12], [30, 0]])
    t = np.array([[500],[150]])
    R = np.array([[500], [150]])
    model = base.Model()
    model.num_milestones = 2
    data_sample = common_analyze.Data_sample(model)
    data_sample.N_ij = N
    data_sample.R_i = t
    data_sample.compute_rate_matrix()
    Q = data_sample.Q
    assert Q[0,0] == -12.0 / 500.0
    assert Q[0,1] == 12.0 / 500.0
    assert Q[1,0] == 30.0 / 150.0
    assert Q[1,1] == -30.0 / 150.0
    algorithm = markov_chain_monte_carlo\
            .irreversible_stochastic_matrix_algorithm_sample
    mcmc_algorithm_any_2x2_common(algorithm, Q, N, R, max_x, max_y, 
                                       make_plot=False)
    
    return
def make_simple_model():
    n_anchors = 3
    n_milestones = 3
    
    # generate data to feed directly into MMVT_data_sample()
    model = base.Model()
    model.calculation_type = "elber"
    model.num_milestones = n_milestones
    model.num_anchors = n_anchors
    anchor0 = elber_base.Elber_toy_anchor()
    anchor0.index = 0
    anchor0.endstate = True
    milestone_0_0 = base.Milestone()
    milestone_0_0.index = 0
    milestone_0_0.neighbor_anchor_index = 0
    milestone_0_0.alias_index = 2
    milestone_0_1 = base.Milestone()
    milestone_0_1.index = 1
    milestone_0_1.neighbor_anchor_index = 1
    milestone_0_1.alias_index = 3
    anchor0.milestones = [milestone_0_0, milestone_0_1]
    
    anchor1 = elber_base.Elber_toy_anchor()
    anchor1.index = 1
    milestone_1_0 = base.Milestone()
    milestone_1_0.index = 0
    milestone_1_0.neighbor_anchor_index = 0
    milestone_1_0.alias_index = 1
    milestone_1_1 = base.Milestone()
    milestone_1_1.index = 1
    milestone_1_1.neighbor_anchor_index = 1
    milestone_1_1.alias_index = 2
    milestone_1_2 = base.Milestone()
    milestone_1_2.index = 2
    milestone_1_2.neighbor_anchor_index = 2
    milestone_1_2.alias_index = 3
    anchor1.milestones = [milestone_1_0, milestone_1_1, milestone_1_2]
    
    anchor2 = elber_base.Elber_toy_anchor()
    anchor2.index = 2
    milestone_2_0 = base.Milestone()
    milestone_2_0.index = 1
    milestone_2_0.neighbor_anchor_index = 1
    milestone_2_0.alias_index = 1
    milestone_2_1 = base.Milestone()
    milestone_2_1.index = 2
    milestone_2_1.neighbor_anchor_index = 2
    milestone_2_1.alias_index = 2
    
    anchor2.milestones = [milestone_2_0, milestone_2_1]
    anchor2.bulkstate = True
    model.anchors = [anchor0, anchor1, anchor2]
    return model
Example #3
0
def make_simple_model():
    n_anchors = 4
    n_milestones = 3
    
    # generate data to feed directly into MMVT_data_sample()
    model = base.Model()
    model.num_milestones = n_milestones
    model.num_anchors = n_anchors
    anchor0 = mmvt_base.MMVT_toy_anchor()
    anchor0.index = 0
    milestone_0_0 = base.Milestone()
    milestone_0_0.index = 0
    milestone_0_0.neighbor_anchor_index = 1
    milestone_0_0.alias_index = 1
    anchor0.milestones = [milestone_0_0]
    
    anchor1 = mmvt_base.MMVT_toy_anchor()
    anchor1.index = 1
    milestone_1_0 = base.Milestone()
    milestone_1_0.index = 0
    milestone_1_0.neighbor_anchor_index = 0
    milestone_1_0.alias_index = 1
    milestone_1_1 = base.Milestone()
    milestone_1_1.index = 1
    milestone_1_1.neighbor_anchor_index = 2
    milestone_1_1.alias_index = 2
    anchor1.milestones = [milestone_1_0, milestone_1_1]
    
    anchor2 = mmvt_base.MMVT_toy_anchor()
    anchor2.index = 2
    milestone_2_0 = base.Milestone()
    milestone_2_0.index = 1
    milestone_2_0.neighbor_anchor_index = 1
    milestone_2_0.alias_index = 1
    milestone_2_1 = base.Milestone()
    milestone_2_1.index = 2
    milestone_2_1.neighbor_anchor_index = 3
    milestone_2_1.alias_index = 2
    anchor2.milestones = [milestone_2_0, milestone_2_1]
    
    anchor3 = mmvt_base.MMVT_toy_anchor()
    anchor3.index = 3
    milestone_3_0 = base.Milestone()
    milestone_3_0.index = 2
    milestone_3_0.neighbor_anchor_index = 2
    milestone_3_0.alias_index = 1
    anchor3.milestones = [milestone_3_0]
    
    model.anchors = [anchor0, anchor1, anchor2, anchor3]
    return model
Example #4
0
def generate_seekr2_model_and_filetree(model_input, force_overwrite):
    """
    Using the Model_input from the user, prepare the Model
    object and the filetree. Then prepare all building files
    for each anchor and serialize the Model to XML.
    """
    model = common_prepare.model_factory(model_input)
    common_prepare.prepare_model_cvs_and_anchors(model, model_input)
    root_directory = os.path.expanduser(model_input.root_directory)
    xml_path = os.path.join(root_directory, "model.xml")
    if os.path.exists(xml_path):
        # then a model file already exists at this location: update
        # the anchor directories.
        old_model = base.Model()
        old_model.deserialize(xml_path)
        common_prepare.modify_model(old_model, model, root_directory,
                                    force_overwrite)

    filetree.generate_filetree(model, root_directory)
    filetree.copy_building_files(model, model_input, root_directory)
    common_prepare.generate_bd_files(model, root_directory)
    model.serialize(xml_path)
    return model, xml_path
Example #5
0
    cuda_device_index = args["cuda_device_index"]
    min_total_simulation_length = args["min_total_simulation_length"]
    max_total_simulation_length = args["max_total_simulation_length"]
    convergence_cutoff = args["convergence_cutoff"]
    minimum_anchor_transitions = args["minimum_anchor_transitions"]
    directory = args["directory"]
    force_overwrite = args["force_overwrite"]
    save_state_file = args["save_state_file"]
    namd_command = args["namd_command"]
    namd_arguments = args["namd_arguments"]
    minimum_b_surface_trajectories = args["minimum_b_surface_trajectories"]
    minimum_bd_milestone_trajectories = args[
        "minimum_bd_milestone_trajectories"]
    max_b_surface_trajs_to_extract = args["max_b_surface_trajs_to_extract"]
    min_b_surface_encounters = args["min_b_surface_encounters"]
    min_bd_milestone_encounters = args["min_bd_milestone_encounters"]
    num_rev_launches = args["num_rev_launches"]
    umbrella_restart_mode = args["umbrella_restart_mode"]

    assert os.path.exists(input_file), "A nonexistent input file was provided."
    model = base.Model()
    model.deserialize(input_file)

    run(model, instruction, min_total_simulation_length,
        max_total_simulation_length, convergence_cutoff, directory,
        minimum_anchor_transitions, cuda_device_index, force_overwrite,
        save_state_file, namd_command, namd_arguments,
        minimum_b_surface_trajectories, minimum_bd_milestone_trajectories,
        max_b_surface_trajs_to_extract, min_b_surface_encounters,
        min_bd_milestone_encounters, num_rev_launches, umbrella_restart_mode)
Example #6
0
def make_test_model(tmp_dir,
                    num_anchors=3,
                    milestone_type="spherical",
                    make_dir=True,
                    mode="amber",
                    engine="openmm",
                    no_BD=False):

    if milestone_type == "spherical":
        #group1 = [2478, 2489, 2499, 2535, 2718, 2745, 2769, 2787, 2794, 2867,
        #          2926]
        group1 = list(range(147))
        #group2 = [3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229]
        group2 = list(range(147, 162))
        groups = [group1, group2]
        cv1 = mmvt_base.MMVT_spherical_CV(index=0, groups=groups)
        cvs = [cv1]

    else:
        raise Exception("milestone type not implemented")

    mymodel = base.Model()
    mymodel.temperature = 277.8
    mymodel.calculation_type = "MMVT"
    mymodel.calculation_settings = mmvt_base.MMVT_settings()
    mymodel.calculation_settings.num_production_steps = 100
    mymodel.anchor_rootdir = tmp_dir
    mymodel.num_anchors = num_anchors
    mymodel.num_milestones = num_anchors - 1

    if engine == "openmm":
        mymodel.openmm_settings = base.Openmm_settings()
        mymodel.openmm_settings.energy_reporter_frequency = 50
        mymodel.openmm_settings.trajectory_reporter_frequency = 50
        mymodel.openmm_settings.restart_checkpoint_frequency = 50
        mymodel.openmm_settings.total_simulation_length = 50
        mymodel.openmm_settings.cuda_platform_settings = None
        mymodel.openmm_settings.reference_platform = True

    if engine == "namd":
        mymodel.namd_settings = base.Namd_settings()
        mymodel.namd_settings.energy_reporter_frequency = 50
        mymodel.namd_settings.trajectory_reporter_frequency = 50
        mymodel.namd_settings.restart_checkpoint_frequency = 50
        mymodel.namd_settings.total_simulation_length = 50

    if not no_BD:
        my_k_on_info = base.K_on_info()
        my_k_on_info.source_milestones = [2]
        mymodel.k_on_info = my_k_on_info

    mymodel.collective_variables = cvs
    '''
    for index in range(num_anchors):
        milestone_list = []
        if index < num_anchors-1:
            milestone1 = base.Milestone()
            milestone1.index = index
            milestone1.neighbor_index = index+1
            milestone1.alias_id = 2
            milestone1.cv_index = 0
            milestone1.variables = {"radius": 1.3}
            milestone_list.append(milestone1)
            bulkstate = False
        else:
            bulkstate = True
        
        if index > 0:
            milestone2 = base.Milestone()
            milestone2.index = index-1
            milestone2.neighbor_index = index-1
            milestone2.alias_id = 1
            milestone2.cv_index = 0
            milestone2.variables = {"radius": 1.1}
            milestone_list.append(milestone2)
            endstate = False
        else:
            endstate = True
            
        if bulkstate:
            endstate = True
    '''
    for i in range(num_anchors):
        index = i
        milestone_list = []
        num_milestones = 0

        if i > 0:
            milestone1 = base.Milestone()
            milestone1.index = i - 1
            milestone1.neighbor_anchor_index = i - 1
            milestone1.alias_index = num_milestones + 1
            milestone1.cv_index = 0
            milestone1.variables = {"k": -1.0, "radius": 0.1 * i}
            milestone_list.append(milestone1)
            num_milestones += 1
            endstate = False
        else:
            endstate = True

        if i < num_anchors - 1:
            milestone2 = base.Milestone()
            milestone2.index = i
            milestone2.neighbor_anchor_index = i + 1
            milestone2.alias_index = num_milestones + 1
            milestone2.cv_index = 0
            milestone2.variables = {"k": 1.0, "radius": 0.1 * (i + 1)}
            milestone_list.append(milestone2)
            bulkstate = False
        else:
            bulkstate = True

        name = "anchor_%d" % index
        directory = name
        if make_dir:
            full_anchor_dir = os.path.join(tmp_dir, directory)
            os.mkdir(full_anchor_dir)
            prod_dir = os.path.join(full_anchor_dir, "prod")
            os.mkdir(prod_dir)
            building_dir = os.path.join(full_anchor_dir, "building")
            os.mkdir(building_dir)
        md_glob = "mmvt*.out"
        md = True
        bd = False

        #anchor = base.Anchor(name, index, directory, md_glob, md, bd,
        #         endstate, bulkstate, len(milestone_list), milestone_list)
        anchor = mmvt_base.MMVT_anchor()
        anchor.name = name
        anchor.index = index
        anchor.directory = directory
        anchor.md_mmvt_output_glob = md_glob
        anchor.md = md
        anchor.bd = bd
        anchor.endstate = endstate
        anchor.bulkstate = bulkstate
        #anchor.num_milestones = len(milestone_list)
        anchor.milestones = milestone_list

        if mode == 'amber':
            make_amber_params(anchor, building_dir, engine=engine)
        elif mode == 'forcefield':
            make_forcefield_params(anchor, building_dir)
        else:
            raise Exception("mode not implemented:" + mode)

        mymodel.anchors.append(anchor)

    if not no_BD:
        mymodel.browndye_settings = base.Browndye_settings()
        mymodel.browndye_settings.apbs_grid_spacing = 0.5
        mymodel.browndye_settings.n_threads = 1
        mymodel.browndye_settings.recompute_ligand_electrostatics = 1
        mymodel.browndye_settings.debye_length = 7.5612
        mymodel.browndye_settings.ghost_indices_rec = [147]
        mymodel.browndye_settings.ghost_indices_lig = [15]
        mymodel.k_on_info.b_surface_directory = "b_surface"
        mymodel.k_on_info.b_surface_num_steps = 100
        ion1 = base.Ion()
        ion1.radius = 1.2
        ion1.charge = -1.0
        ion1.conc = 0.15
        ion2 = base.Ion()
        ion2.radius = 0.9
        ion2.charge = 1.0
        ion2.conc = 0.15
        mymodel.k_on_info.ions = [ion1, ion2]
        if make_dir:
            b_surface_abs_path = os.path.join(tmp_dir, "b_surface")
            os.mkdir(b_surface_abs_path)

        make_browndye_params_b_surface(mymodel, b_surface_abs_path)

        mymodel.k_on_info.bd_milestones = []
        bd_milestone = base.BD_milestone()
        bd_milestone.index = 0
        bd_milestone.name = "bd_milestone_0"
        bd_milestone.directory = bd_milestone.name
        bd_milestone.outer_milestone = milestone2
        #bd_milestone.outer_milestone = mymodel.anchors[-1].milestones[-1]
        assert "radius" in bd_milestone.outer_milestone.variables, \
            "A BD outer milestone must be spherical."

        bd_milestone.inner_milestone = milestone1

        bd_milestone.num_steps = 1
        bd_milestone.receptor_indices = list(range(147))
        bd_milestone.ligand_indices = list(range(15))

        mymodel.k_on_info.bd_milestones.append(bd_milestone)

        for bd_milestone in mymodel.k_on_info.bd_milestones:
            bd_milestone_dict = {}
            bd_milestone_dict[bd_milestone.extracted_directory] = {}
            bd_milestone_dict[bd_milestone.fhpd_directory] = {}

            bd_milestone_filetree = filetree.Filetree(
                {bd_milestone.directory: bd_milestone_dict})
            bd_milestone_filetree.make_tree(tmp_dir)

    return mymodel
Example #7
0
def make_smol_model(tmp_path, num_anchors, intervals):
    basename = "testmmvt.dat"
    mymodel = base.Model()
    mymodel.temperature = 300.0
    mymodel.calculation_type = "mmvt"
    mymodel.anchor_rootdir = tmp_path
    mymodel.num_anchors = num_anchors+1
    mymodel.num_milestones = mymodel.num_anchors - 1
    
    # TEMPORARY: toy system will eventually have its own settings
    mymodel.openmm_settings = base.Openmm_settings()
    
    intervals.append(1.0)
    
    for index in range(mymodel.num_anchors):
        boundary1 = float(index)
        boundary2 = float(index)+intervals[index]
        x0 = boundary1 + 0.5
        milestones = []
        anchor = mmvt_base.MMVT_anchor()
        if index == 0:
            milestone_count = 1
            milestone1 = base.Milestone()
            milestone1.index = 0
            milestone1.neighbor_anchor_index = 1
            milestone1.alias_index = 1
            milestone1.cv_index = 0
            milestones.append(milestone1)
            anchor.bulkstate = False
            end_state = True
        elif index > 0 and index < mymodel.num_anchors-1:
            milestone_count = 2
            milestone1 = base.Milestone()
            milestone1.index = index-1
            milestone1.neighbor_anchor_index = index-1
            milestone1.alias_index = 1
            milestone1.cv_index = 0
            milestone2 = base.Milestone()
            milestone2.index = index
            milestone2.neighbor_anchor_index = index+1
            milestone2.alias_index = 2
            milestone2.cv_index = 0
            milestones.append(milestone1)
            milestones.append(milestone2)
            anchor.bulkstate = False
            end_state = False
        elif index == mymodel.num_anchors-1:
            milestone_count = 1
            milestone1 = base.Milestone()
            milestone1.index = index-1
            milestone1.neighbor_anchor_index = index-1
            milestone1.alias_index = 1
            milestone1.cv_index = 0
            milestones.append(milestone1)
            anchor.bulkstate = True
            end_state = False
        
        anchor.name = "anchor_%d" % index
        anchor.index = index
        anchor.directory = anchor.name
        anchor.md_mmvt_output_glob = basename
        anchor.md = True
        anchor.endstate = end_state
        anchor.milestones = milestones
        mymodel.anchors.append(anchor)
    return mymodel
Example #8
0
def model_factory(model_input, use_absolute_directory=False):
    """
    Given the Model_input object, which contains the settings, 
    create the Model object which contains more detailed 
    information.
    """

    model = base.Model()
    calc_settings = model_input.calculation_settings
    if model_input.calculation_type.lower() == "mmvt":
        model.calculation_settings = mmvt_base.MMVT_settings()
        model.calculation_settings.num_production_steps = \
            calc_settings.md_steps_per_anchor
        model.calculation_settings.energy_reporter_interval = \
            calc_settings.md_output_interval
        model.calculation_settings.restart_checkpoint_interval = \
            calc_settings.md_output_interval
        model.calculation_settings.trajectory_reporter_interval = \
            calc_settings.md_output_interval
    elif model_input.calculation_type.lower() == "elber":
        model.calculation_settings = elber_base.Elber_settings()
        model.calculation_settings.temperature_equil_progression = \
            calc_settings.temperature_equil_progression
        model.calculation_settings.num_temperature_equil_steps = \
            calc_settings.num_temperature_equil_steps
        model.calculation_settings.num_umbrella_stage_steps = \
            calc_settings.num_umbrella_stage_steps
        model.calculation_settings.umbrella_force_constant = \
            calc_settings.umbrella_force_constant
        model.calculation_settings.fwd_rev_interval = \
            calc_settings.fwd_rev_interval
        model.calculation_settings.umbrella_energy_reporter_interval = \
            calc_settings.fwd_rev_interval
        model.calculation_settings.umbrella_trajectory_reporter_interval = \
            calc_settings.fwd_rev_interval
        model.calculation_settings.rev_energy_reporter_interval = \
            calc_settings.rev_output_interval
        model.calculation_settings.rev_trajectory_reporter_interval = \
            calc_settings.rev_output_interval
        model.calculation_settings.fwd_energy_reporter_interval = \
            calc_settings.fwd_output_interval
        model.calculation_settings.fwd_trajectory_reporter_interval = \
            calc_settings.fwd_output_interval

    else:
        raise Exception("Invalid calculation_type entered:",
                        model_input.calculation_type)
    model.calculation_type = model_input.calculation_type.lower()
    temperature = model_input.temperature
    model.temperature = temperature
    if use_absolute_directory:
        model.anchor_rootdir = model_input.root_directory
    else:
        model.anchor_rootdir = "."
    if model_input.ensemble.lower() == "nvt":
        pressure = None
    elif model_input.ensemble.lower() == "npt":
        pressure = model_input.pressure
    elif model_input.ensemble.lower() == "nve":
        raise Exception("NVE ensemble not yet implemented. Options must be"\
                        "NVT or NPT.")
    else:
        raise Exception("Invalid ensemble entered:", model_input.ensemble)

    if model_input.md_program.lower() == "openmm":
        mm_settings = base.Openmm_settings()
        mm_settings.langevin_integrator.target_temperature = temperature
        if pressure is not None:
            mm_settings.barostat = base.Barostat_settings_openmm()
            mm_settings.barostat.target_temperature = temperature
            mm_settings.barostat.target_pressure = pressure
        mm_settings.initial_temperature = temperature
        mm_settings.nonbonded_cutoff = model_input.nonbonded_cutoff
        mm_settings.run_minimization = model_input.run_minimization
        mm_settings.hydrogenMass = model_input.hydrogenMass
        mm_settings.constraints = model_input.constraints
        mm_settings.langevin_integrator.timestep = model_input.timestep
        mm_settings.rigidWater = model_input.rigidWater

        model.openmm_settings = mm_settings
    elif model_input.md_program.lower() == "namd":
        namd_settings = base.Namd_settings()
        namd_settings.langevin_integrator.target_temperature = temperature
        if pressure is not None:
            namd_settings.barostat = base.Barostat_settings_namd()
            namd_settings.barostat.target_temperature = temperature
            namd_settings.barostat.target_pressure = pressure
        namd_settings.initial_temperature = temperature
        namd_settings.nonbonded_cutoff = model_input.nonbonded_cutoff
        namd_settings.run_minimization = model_input.run_minimization
        assert model_input.hydrogenMass is None, "hydrogen mass "\
            "repartitioning not yet implemented in NAMD SEEKR."
        #namd_settings.hydrogenMass = model_input.hydrogenMass
        namd_settings.constraints = model_input.constraints
        namd_settings.langevin_integrator.timestep = model_input.timestep
        namd_settings.rigidWater = model_input.rigidWater
        model.namd_settings = namd_settings

    else:
        raise Exception("Invalid MD program entered:", model_input.md_program)

    if model_input.browndye_settings_input is None:
        # Running no BD
        pass

    else:
        k_on_info = base.K_on_info()
        k_on_info.ions = model_input.browndye_settings_input.ions
        k_on_info.b_surface_num_trajectories = \
            model_input.browndye_settings_input.num_b_surface_trajectories

        model.browndye_settings = base.Browndye_settings()
        model.browndye_settings.browndye_bin_dir = \
            model_input.browndye_settings_input.binary_directory
        model.browndye_settings.receptor_pqr_filename = \
            os.path.basename(
                model_input.browndye_settings_input.receptor_pqr_filename)
        model.browndye_settings.ligand_pqr_filename = \
            os.path.basename(
                model_input.browndye_settings_input.ligand_pqr_filename)
        model.browndye_settings.apbs_grid_spacing = \
            model_input.browndye_settings_input.apbs_grid_spacing
        model.browndye_settings.n_threads = \
            model_input.browndye_settings_input.n_threads

        model.k_on_info = k_on_info

    return model
Example #9
0
def test_mcmc_3x3_mmvt(tmpdir_factory):
    """
    Use the same statistics to generate both MMVT and Elber rate matrices.
    Then use the data to sample matrices and compare the distributions to
    ensure that the MMVT and Elber matrix sampling methods are consistent.
    """
    num = 10000 #100000
    stride = 4
    skip = 90
    n_anchors = 4
    n_milestones = 3
    
    # generate data to feed directly into MMVT_data_sample()
    model = base.Model()
    model.num_milestones = n_milestones
    model.num_anchors = n_anchors
    anchor0 = mmvt_base.MMVT_toy_anchor()
    anchor0.index = 0
    milestone_0_0 = base.Milestone()
    milestone_0_0.index = 0
    milestone_0_0.neighbor_anchor_index = 1
    milestone_0_0.alias_index = 1
    anchor0.milestones = [milestone_0_0]
    
    anchor1 = mmvt_base.MMVT_toy_anchor()
    anchor1.index = 1
    milestone_1_0 = base.Milestone()
    milestone_1_0.index = 0
    milestone_1_0.neighbor_anchor_index = 0
    milestone_1_0.alias_index = 1
    milestone_1_1 = base.Milestone()
    milestone_1_1.index = 1
    milestone_1_1.neighbor_anchor_index = 2
    milestone_1_1.alias_index = 2
    anchor1.milestones = [milestone_1_0, milestone_1_1]
    
    anchor2 = mmvt_base.MMVT_toy_anchor()
    anchor2.index = 2
    milestone_2_0 = base.Milestone()
    milestone_2_0.index = 1
    milestone_2_0.neighbor_anchor_index = 1
    milestone_2_0.alias_index = 1
    milestone_2_1 = base.Milestone()
    milestone_2_1.index = 2
    milestone_2_1.neighbor_anchor_index = 3
    milestone_2_1.alias_index = 2
    anchor2.milestones = [milestone_2_0, milestone_2_1]
    
    anchor3 = mmvt_base.MMVT_toy_anchor()
    anchor3.index = 3
    milestone_3_0 = base.Milestone()
    milestone_3_0.index = 2
    milestone_3_0.neighbor_anchor_index = 2
    milestone_3_0.alias_index = 1
    anchor3.milestones = [milestone_3_0]
    
    model.anchors = [anchor0, anchor1, anchor2, anchor3]
    
    # MMVT stats
    N_alpha_beta = {(0,1):12, (1,0):12,
                    (1,2):12, (2,1):12,
                    (2,3):6,  (3,2):6}
    k_alpha_beta = {(0,1):20.0, (1,0):10.0,
                    (1,2):10.0,  (2,1):(40.0/3.0),
                    (2,3):(20.0/3.0), (3,2):20.0}
    N_i_j_alpha = [{},
                   {(0,1):4, (1,0):4}, 
                   {(1,2):2, (2,1):2},
                   {}]
    R_i_alpha_total = [{0: 1.2},
                       {0: 1.2, 1:1.2},
                       {1: 1.2, 2:0.6},
                       {2: 0.6}]
    T_alpha_total = [1.2,
                     2.4,
                     1.8,
                     0.6]
    
    main_data_sample = mmvt_analyze.MMVT_data_sample(
            model, N_alpha_beta, k_alpha_beta, N_i_j_alpha, 
            R_i_alpha_total, T_alpha_total)
    main_data_sample.calculate_pi_alpha()
    main_data_sample.fill_out_data_quantities()
    main_data_sample.compute_rate_matrix()
    main_data_sample.calculate_thermodynamics()
    main_data_sample.calculate_kinetics()
    mmvt_Q = main_data_sample.Q
    
    # Elber stats
    N_i_j = {(0,1): 4, (1,0): 4, (1,2): 2, (2,1): 2}
    R_i = {0: 2.4, 1: 2.4, 2: 1.2}
    elber_N = np.array([[0, 4, 0],
                        [4, 0, 2],
                        [0, 2, 0]])
    elber_R = np.array([[2.4],
                        [2.4],
                        [1.2]])
    
    elber_Q = np.zeros((n_milestones, n_milestones))
    for i in range(n_milestones):
        for j in range(n_milestones):
            key = (i,j)
            if key in N_i_j:
                elber_Q[i,j] = N_i_j[key] / R_i[i]
    
    for i in range(n_milestones):
        elber_Q[i,i] = -np.sum(elber_Q[i,:])
    
    # Make sure the two models make identical matrices
    assert np.isclose(mmvt_Q, elber_Q).all()
    
    # Now compare the distributions of both of them
    
    # MMVT matrix sampler
    data_sample_list, p_i_error, free_energy_profile_err, MFPTs_error, \
        k_off_error, k_ons_error = mmvt_analyze.monte_carlo_milestoning_error(
        main_data_sample, num=num, stride=stride, skip=skip, verbose=True)
    
    mmvt_q1_distribution = []
    mmvt_q2_distribution = []
    for data_sample in data_sample_list:
        mmvt_q1_distribution.append(data_sample.Q[0,1])
        mmvt_q2_distribution.append(data_sample.Q[1,0])
    
    # Elber matrix sampler
    elber_q1_distribution = []
    elber_q2_distribution = []
    for counter in range(num * (stride) + skip):
        #if verbose: print("MCMC stepnum: ", counter)
        elber_Qnew = markov_chain_monte_carlo\
            .irreversible_stochastic_matrix_algorithm_sample(
                elber_Q, elber_N, elber_R)
        if counter > skip and counter % stride == 0:
            elber_q1_distribution.append(elber_Q[0,1])
            elber_q2_distribution.append(elber_Q[1,0])
        
        elber_Q = elber_Qnew
    
    assert np.isclose(np.mean(elber_q1_distribution), 
                      np.mean(mmvt_q1_distribution), rtol=0.5, atol=0.01)
    assert np.isclose(np.std(elber_q1_distribution), 
                      np.std(mmvt_q1_distribution), rtol=0.5, atol=0.01)
    assert np.isclose(np.mean(elber_q2_distribution), 
                      np.mean(mmvt_q2_distribution), rtol=0.5, atol=0.01)
    assert np.isclose(np.std(elber_q2_distribution), 
                      np.std(mmvt_q2_distribution), rtol=0.5, atol=0.01)
    
    return