Ejemplo n.º 1
0
    def test_2(self):
        """Ensure that the evaluation of the criterion is equal across versions."""
        max_draws = np.random.randint(10, 100)

        # It seems to be important that max_draws and max_agents is the same
        # number because otherwise some functions that read draws from a file
        # to ensure compatibility of fortran and python versions won't work.
        bound_constr = {"max_draws": max_draws, "max_agents": max_draws}

        point_constr = {
            "interpolation": {"flag": False},
            "program": {"procs": 1, "threads": 1, "version": "python"},
            "estimation": {"maxfun": 0},
        }

        params_spec, options_spec = generate_random_model(
            point_constr=point_constr, bound_constr=bound_constr
        )
        respy_obj = RespyCls(params_spec, options_spec)

        num_agents_sim, optim_paras = dist_class_attributes(
            respy_obj, "num_agents_sim", "optim_paras"
        )

        type_shares = optim_paras["type_shares"]

        # Simulate a dataset
        simulate_observed(respy_obj)

        # Iterate over alternative implementations
        base_x, base_val = None, None

        num_periods = options_spec["num_periods"]

        write_draws(num_periods, max_draws)
        write_types(type_shares, num_agents_sim)

        for version in ["python", "fortran"]:

            respy_obj.unlock()

            respy_obj.set_attr("version", version)

            respy_obj.lock()

            x, val = respy_obj.fit()

            # Check for the returned parameters.
            if base_x is None:
                base_x = x
            np.testing.assert_allclose(base_x, x)

            # Check for the value of the criterion function.
            if base_val is None:
                base_val = val
            np.testing.assert_allclose(base_val, val)
Ejemplo n.º 2
0
    def test_3(self):
        """ Testing whether the a simulated dataset and the evaluation of the criterion function
        are the same for a tiny delta and a myopic agent.
        """
        constr = {"estimation": {"maxfun": 0}}
        params_spec, options_spec = generate_random_model(point_constr=constr,
                                                          myopic=True)
        respy_obj = RespyCls(params_spec, options_spec)

        optim_paras, num_agents_sim, edu_spec = dist_class_attributes(
            respy_obj, "optim_paras", "num_agents_sim", "edu_spec")

        write_types(optim_paras["type_shares"], num_agents_sim)
        write_edu_start(edu_spec, num_agents_sim)
        write_lagged_start(num_agents_sim)

        # Iterate over alternative discount rates.
        base_data, base_val = None, None

        for delta in [0.00, 0.000001]:

            respy_obj = RespyCls(params_spec, options_spec)

            respy_obj.unlock()

            respy_obj.attr["optim_paras"]["delta"] = np.array([delta])

            respy_obj.lock()

            simulate_observed(respy_obj)

            # This parts checks the equality of simulated dataset for the different
            # versions of the code.
            data_frame = pd.read_csv("data.respy.dat", delim_whitespace=True)

            if base_data is None:
                base_data = data_frame.copy()

            assert_frame_equal(base_data, data_frame)

            # This part checks the equality of an evaluation of the criterion function.
            _, crit_val = respy_obj.fit()

            if base_val is None:
                base_val = crit_val

            np.testing.assert_allclose(base_val,
                                       crit_val,
                                       rtol=1e-03,
                                       atol=1e-03)
Ejemplo n.º 3
0
    def test_5(self):
        """ This methods ensures that the core functions yield the same results across
        implementations.
        """
        params_spec, options_spec = generate_random_model()
        respy_obj = RespyCls(params_spec, options_spec)

        # Ensure that backward induction routines use the same grid for the
        # interpolation.
        max_states_period = write_interpolation_grid(respy_obj)

        # Extract class attributes
        (
            num_periods,
            edu_spec,
            optim_paras,
            num_draws_emax,
            is_debug,
            is_interpolated,
            num_points_interp,
            is_myopic,
            num_agents_sim,
            num_draws_prob,
            tau,
            seed_sim,
            num_agents_est,
            optimizer_options,
            file_sim,
            num_types,
            num_paras,
        ) = dist_class_attributes(
            respy_obj,
            "num_periods",
            "edu_spec",
            "optim_paras",
            "num_draws_emax",
            "is_debug",
            "is_interpolated",
            "num_points_interp",
            "is_myopic",
            "num_agents_sim",
            "num_draws_prob",
            "tau",
            "seed_sim",
            "num_agents_est",
            "optimizer_options",
            "file_sim",
            "num_types",
            "num_paras",
        )

        min_idx = edu_spec["max"] + 1
        shocks_cholesky = optim_paras["shocks_cholesky"]
        coeffs_common = optim_paras["coeffs_common"]
        coeffs_home = optim_paras["coeffs_home"]
        coeffs_edu = optim_paras["coeffs_edu"]
        coeffs_a = optim_paras["coeffs_a"]
        coeffs_b = optim_paras["coeffs_b"]
        delta = optim_paras["delta"]

        type_spec_shares = optim_paras["type_shares"]
        type_spec_shifts = optim_paras["type_shifts"]

        # Write out random components and interpolation grid to align the three
        # implementations.
        max_draws = max(num_agents_sim, num_draws_emax, num_draws_prob)
        write_types(type_spec_shares, num_agents_sim)
        write_edu_start(edu_spec, num_agents_sim)
        write_draws(num_periods, max_draws)
        write_lagged_start(num_agents_sim)

        # It is critical that the model is simulated after all files have been written
        # to the disk because they are picked up in the subroutines.
        respy_obj = simulate_observed(respy_obj)

        periods_draws_emax = read_draws(num_periods, num_draws_emax)
        periods_draws_prob = read_draws(num_periods, num_draws_prob)
        periods_draws_sims = read_draws(num_periods, num_agents_sim)

        fort, _ = resfort_interface(respy_obj, "simulate")

        state_space = pyth_solve(
            is_interpolated,
            num_points_interp,
            num_periods,
            is_debug,
            periods_draws_emax,
            edu_spec,
            optim_paras,
            file_sim,
            num_types,
        )

        (
            states_all,
            mapping_state_idx,
            periods_rewards_systematic,
            periods_emax,
        ) = state_space._get_fortran_counterparts()

        py = (
            periods_rewards_systematic,
            state_space.states_per_period,
            mapping_state_idx,
            periods_emax,
            states_all,
        )

        f2py = fort_debug.wrapper_solve(
            is_interpolated,
            num_points_interp,
            num_draws_emax,
            num_periods,
            is_myopic,
            is_debug,
            periods_draws_emax,
            min_idx,
            edu_spec["start"],
            edu_spec["max"],
            coeffs_common,
            coeffs_a,
            coeffs_b,
            coeffs_edu,
            coeffs_home,
            shocks_cholesky,
            delta,
            file_sim,
            max_states_period,
            num_types,
            type_spec_shares,
            type_spec_shifts,
        )

        assert_allclose(py[0], fort[0])
        assert_allclose(py[1], fort[1])
        assert_allclose(py[2], fort[2])
        assert_allclose(py[3], fort[3])
        assert_allclose(py[4], fort[4])

        assert_allclose(py[0], f2py[0])
        assert_allclose(py[1], f2py[1])
        assert_allclose(py[2], f2py[2])
        assert_allclose(py[3], f2py[3])
        assert_allclose(py[4], f2py[4])

        (
            states_all,
            mapping_state_idx,
            periods_rewards_systematic,
            periods_emax,
        ) = state_space._get_fortran_counterparts()

        simulated_data = pyth_simulate(
            state_space,
            num_agents_sim,
            periods_draws_sims,
            seed_sim,
            file_sim,
            edu_spec,
            optim_paras,
            is_debug,
        )
        py = simulated_data.copy().fillna(MISSING_FLOAT).values

        data_array = process_dataset(respy_obj).to_numpy()

        # Is is very important to cut the data array down to the size of the estimation
        # sample for the calculation of contributions.
        data_array = py[:num_agents_est * num_periods, :]

        f2py = fort_debug.wrapper_simulate(
            periods_rewards_systematic,
            mapping_state_idx,
            periods_emax,
            states_all,
            num_periods,
            num_agents_sim,
            periods_draws_sims,
            seed_sim,
            file_sim,
            edu_spec["start"],
            edu_spec["max"],
            edu_spec["share"],
            edu_spec["lagged"],
            optim_paras["coeffs_common"],
            optim_paras["coeffs_a"],
            optim_paras["coeffs_b"],
            shocks_cholesky,
            delta,
            num_types,
            type_spec_shares,
            type_spec_shifts,
            is_debug,
        )
        assert_allclose(py, f2py)

        # We have to cut the simulated data to `num_agents_est` as the Python
        # implementation calculates the likelihood contributions for all agents in the
        # data.
        simulated_data = simulated_data.loc[simulated_data.Identifier.lt(
            num_agents_est)]

        py = pyth_contributions(state_space, simulated_data,
                                periods_draws_prob, tau, optim_paras)

        num_obs_agent = np.bincount(simulated_data.Identifier.to_numpy())

        f2py = fort_debug.wrapper_contributions(
            periods_rewards_systematic,
            mapping_state_idx,
            periods_emax,
            states_all,
            data_array,
            periods_draws_prob,
            tau,
            num_periods,
            num_draws_prob,
            num_agents_est,
            num_obs_agent,
            num_types,
            edu_spec["start"],
            edu_spec["max"],
            shocks_cholesky,
            delta,
            type_spec_shares,
            type_spec_shifts,
        )

        assert_allclose(py, f2py)

        # Evaluation of criterion function
        x0 = get_optim_paras(optim_paras, num_paras, "all", is_debug)

        py = pyth_criterion(
            x0,
            is_interpolated,
            num_points_interp,
            is_debug,
            simulated_data,
            tau,
            periods_draws_emax,
            periods_draws_prob,
            state_space,
        )

        f2py = fort_debug.wrapper_criterion(
            x0,
            is_interpolated,
            num_draws_emax,
            num_periods,
            num_points_interp,
            is_myopic,
            is_debug,
            data_array,
            num_draws_prob,
            tau,
            periods_draws_emax,
            periods_draws_prob,
            states_all,
            state_space.states_per_period,
            mapping_state_idx,
            max_states_period,
            num_agents_est,
            num_obs_agent,
            num_types,
            edu_spec["start"],
            edu_spec["max"],
            edu_spec["share"],
            type_spec_shares,
            type_spec_shifts,
            num_paras,
        )

        assert_allclose(py, f2py)
Ejemplo n.º 4
0
    def test_1(self):
        """ Testing the equality of an evaluation of the criterion function for a random
        request.
        """
        # Run evaluation for multiple random requests.
        is_deterministic = np.random.choice([True, False], p=[0.10, 0.9])
        is_interpolated = bool(np.random.choice([True, False], p=[0.10, 0.9]))
        is_myopic = np.random.choice([True, False], p=[0.10, 0.9])
        max_draws = np.random.randint(11, 100)
        num_agents = np.random.randint(10, max_draws)

        bound_constr = {"max_draws": max_draws}
        point_constr = {
            "interpolation": {"flag": is_interpolated},
            "program": {"procs": 1, "threads": 1, "version": "python"},
            "estimation": {"maxfun": 0, "agents": num_agents},
            "simulation": {"agents": num_agents},
            "num_periods": np.random.randint(1, 5),
        }

        num_types = np.random.randint(2, 5)

        if is_interpolated:
            point_constr["num_periods"] = np.random.randint(3, 5)

        params_spec, options_spec = generate_random_model(
            bound_constr=bound_constr,
            point_constr=point_constr,
            deterministic=is_deterministic,
            myopic=is_myopic,
            num_types=num_types,
        )

        edu_spec = options_spec["edu_spec"]
        num_periods = point_constr["num_periods"]

        # The use of the interpolation routines is a another special case. Constructing
        #  a request that actually involves the use of the interpolation routine is a
        #  little involved as the number of interpolation points needs to be lower than
        #  the actual number of states. And to know the number of states each period, I
        #  need to construct the whole state space.
        if is_interpolated:
            state_space = StateSpace(
                num_periods, num_types, edu_spec["start"], edu_spec["max"]
            )

            max_states_period = state_space.states_per_period.max()

            options_spec["interpolation"]["points"] = np.random.randint(
                10, max_states_period
            )

        # Write out random components and interpolation grid to align the three
        # implementations.
        write_draws(num_periods, max_draws)
        respy_obj = RespyCls(params_spec, options_spec)
        write_interpolation_grid(respy_obj)

        type_shares = respy_obj.attr["optim_paras"]["type_shares"]

        write_types(type_shares, num_agents)
        write_edu_start(edu_spec, num_agents)
        write_lagged_start(num_agents)

        # Clean evaluations based on interpolation grid,
        base_val, base_data = None, None

        for version in ["python", "fortran"]:
            respy_obj = RespyCls(params_spec, options_spec)

            # Modify the version of the program for the different requests.
            respy_obj.unlock()
            respy_obj.set_attr("version", version)
            respy_obj.lock()

            # Solve the model
            respy_obj = simulate_observed(respy_obj)

            # This parts checks the equality of simulated dataset for the different
            # versions of the code.
            data_frame = pd.read_csv("data.respy.dat", delim_whitespace=True)

            if base_data is None:
                base_data = data_frame.copy()

            assert_frame_equal(base_data, data_frame)

            # This part checks the equality of an evaluation of the criterion function.
            _, crit_val = respy_obj.fit()

            if base_val is None:
                base_val = crit_val

            np.testing.assert_allclose(base_val, crit_val, rtol=1e-05, atol=1e-06)

            # We know even more for the deterministic case.
            if is_deterministic:
                assert crit_val in [-1.0, 0.0]
Ejemplo n.º 5
0
    def test_4(self):
        """ This test ensures that the scaling matrix is identical between the
        alternative versions.
        """
        max_draws = np.random.randint(11, 300)

        bound_constr = {"max_draws": max_draws, "max_agents": max_draws}
        num_agents = np.random.randint(10, max_draws)

        point_constr = {
            "program": {"version": "python"},
            "estimation": {"maxfun": np.random.randint(1, 6), "agents": num_agents},
            "simulation": {"agents": num_agents},
        }

        params_spec, options_spec = generate_random_model(
            point_constr=point_constr, bound_constr=bound_constr
        )
        respy_base = RespyCls(params_spec, options_spec)

        num_agents_sim, optim_paras = dist_class_attributes(
            respy_base, "num_agents_sim", "optim_paras"
        )

        type_shares = optim_paras["type_shares"]
        num_periods = options_spec["num_periods"]

        write_draws(num_periods, max_draws)
        write_interpolation_grid(respy_base)
        write_types(type_shares, num_agents_sim)

        simulate_observed(respy_base)

        base_scaling_matrix = None
        for version in ["fortran", "python"]:
            respy_obj = copy.deepcopy(respy_base)

            # The actual optimizer does not matter for the scaling matrix. We also need
            # to make sure that PYTHON is only called with a single processor.
            if version == "python":
                optimizer_used = "SCIPY-LBFGSB"
                num_procs = 1
            else:
                num_procs = respy_obj.get_attr("num_procs")
                optimizer_used = "FORT-BOBYQA"

            # Create output to process a baseline.
            respy_obj.unlock()
            respy_obj.set_attr("optimizer_used", optimizer_used)
            respy_obj.set_attr("num_procs", num_procs)
            respy_obj.set_attr("version", version)
            respy_obj.set_attr("maxfun", 1)
            respy_obj.lock()

            respy_obj.fit()

            if base_scaling_matrix is None:
                base_scaling_matrix = np.genfromtxt("scaling.respy.out")

            scaling_matrix = np.genfromtxt("scaling.respy.out")
            assert_almost_equal(base_scaling_matrix, scaling_matrix)
Ejemplo n.º 6
0
    def test_3(self):
        """Ensure that the log looks exactly the same for different versions."""
        max_draws = np.random.randint(10, 100)

        bound_constr = {"max_draws": max_draws, "max_agents": max_draws}

        point_constr = {
            "interpolation": {"flag": False},
            "program": {"procs": 1, "threads": 1, "version": "python"},
            "estimation": {"maxfun": 0},
        }

        params_spec, options_spec = generate_random_model(
            point_constr=point_constr, bound_constr=bound_constr
        )
        respy_obj = RespyCls(params_spec, options_spec)

        num_agents_sim, optim_paras, file_sim = dist_class_attributes(
            respy_obj, "num_agents_sim", "optim_paras", "file_sim"
        )

        # Iterate over alternative implementations
        base_sol_log, base_est_info, base_est_log = None, None, None
        base_sim_log = None

        type_shares = respy_obj.attr["optim_paras"]["type_shares"]
        num_periods = options_spec["num_periods"]

        edu_spec = options_spec["edu_spec"]

        write_draws(num_periods, max_draws)
        write_types(type_shares, num_agents_sim)
        write_edu_start(edu_spec, num_agents_sim)
        write_lagged_start(num_agents_sim)

        for version in ["fortran", "python"]:

            respy_obj.unlock()

            respy_obj.set_attr("version", version)

            respy_obj.lock()

            simulate_observed(respy_obj)

            # Check for identical logging
            fname = file_sim + ".respy.sol"
            if base_sol_log is None:
                base_sol_log = open(fname, "r").read()
            assert open(fname, "r").read() == base_sol_log

            # Check for identical logging
            fname = file_sim + ".respy.sim"
            if base_sim_log is None:
                base_sim_log = open(fname, "r").read()
            assert open(fname, "r").read() == base_sim_log

            respy_obj.fit()

            if base_est_info is None:
                base_est_info = open("est.respy.info", "r").read()
                assert open("est.respy.info", "r").read() == base_est_info

            if base_est_log is None:
                base_est_log = open("est.respy.log", "r").readlines()
            compare_est_log(base_est_log)