Ejemplo n.º 1
0
def test_cyclic_timer_profile_should_compute_duration_correct():

    tested = CyclicTimerProfile(profile=[10, 20, 10, 40],
                                profile_time_steps="2h",
                                start_date=pd.Timestamp("21 March 1956"))

    assert tested.duration() == pd.Timedelta("8h")
Ejemplo n.º 2
0
def test_activity_level_should_be_scaled_according_to_profile_duration():

    clock = Clock(
        start=pd.Timestamp("10 June 2016 5:45pm"),
        # time steps by 15min
        step_duration=pd.Timedelta("1 h"),
        seed=1234)

    # 1 to 12 then 12 to 1, from midnight to midnight
    one_day_timer = CyclicTimerGenerator(
        clock=clock,
        config=CyclicTimerProfile(
            profile=list(range(24)),
            profile_time_steps="1H",
            start_date=pd.Timestamp("1 January 2014 00:00:00"),
        ),
        seed=1234)

    # 14 actions/week should be scaled to activity 2 since profile lasts 1 day
    assert 2 == one_day_timer.activity(n=14, per=pd.Timedelta("7 days"))

    # this one should generate a warning log since the corresponding freq
    # is shorter than the clock step
    assert 48 == one_day_timer.activity(n=4, per=pd.Timedelta("2h"))

    assert .5 == one_day_timer.activity(n=1, per=pd.Timedelta("2 days"))

    assert .5 == one_day_timer.activity(n=.25, per=pd.Timedelta("12h"))

    assert 1. / 360 - one_day_timer.activity(
        n=1, per=pd.Timedelta("360 days")) < 1e-10
Ejemplo n.º 3
0
    def __init__(self, clock, seed, start_hour=9, end_hour=17):

        assert start_hour >= 0
        assert end_hour < 24
        assert start_hour <= end_hour

        # if start_hour = 0, before_work is empty
        before_work = [0] * start_hour
        during_work = [1.] * (end_hour - start_hour + 1)
        # if end_hour = 23, after_work is empty
        after_work = [0] * (23 - end_hour)

        # the sum of before_work, during_work and after_work is always 24
        week_day_profile = before_work + during_work + after_work
        weekend_day_profile = [0] * 24

        week_profile = week_day_profile * 5 + weekend_day_profile * 2

        start_date = pd.Timestamp("6 June 2016 00:00:00")
        CyclicTimerGenerator.__init__(self,
                                      clock=clock,
                                      seed=seed,
                                      config=CyclicTimerProfile(
                                          profile=week_profile,
                                          profile_time_steps="1h",
                                          start_date=start_date))
Ejemplo n.º 4
0
def test_init_cyclictimergenerator():

    # say we have a clock at 5.45pm on 10th June
    clock = Clock(
        start=pd.Timestamp("10 June 2016 5:45pm"),
        # time steps by 15min
        step_duration=pd.Timedelta("15 min"),
        seed=1234)

    # 1 to 12 then 12 to 1, from midnight to midnight
    timer_gen = CyclicTimerGenerator(
        clock=clock,
        config=CyclicTimerProfile(
            profile=list(range(1, 13)) + list(range(12, 0, -1)),
            profile_time_steps="1H",
            start_date=pd.Timestamp("1 January 2014 00:00:00"),
        ),
        seed=1234)

    # after the initialization, the 1h time delta of the profile should have
    # been aligned to the 15min of the clock
    assert timer_gen.profile.index.shape[0] == 24 * 4

    # the first index should be shifted to the time of the clock
    assert timer_gen.profile.index[0] == pd.Timestamp("10 June 2016 5:45pm")
Ejemplo n.º 5
0
def add_mobility_action(circus, params):

    logging.info(" creating customer mobility action")
    mov_prof = [
        1., 1., 1., 1., 1., 1., 1., 1., 5., 10., 5., 1., 1., 1., 1., 1., 1.,
        5., 10., 5., 1., 1., 1., 1.
    ]
    mobility_time_gen = CyclicTimerGenerator(
        clock=circus.clock,
        seed=next(circus.seeder),
        config=CyclicTimerProfile(
            profile=mov_prof,
            profile_time_steps="1H",
            start_date=pd.Timestamp("12 September 2016 00:00.00"),
        ))

    gaussian_activity = NumpyRandomGenerator(
        method="normal",
        loc=params["mean_daily_customer_mobility_activity"],
        scale=params["std_daily_customer_mobility_activity"],
        seed=next(circus.seeder))

    mobility_activity_gen = gaussian_activity.map(f=bound_value(lb=.5))

    mobility_action = circus.create_story(
        name="customer_mobility",
        initiating_actor=circus.actors["customers"],
        actorid_field="CUST_ID",
        timer_gen=mobility_time_gen,
        activity_gen=mobility_activity_gen)

    logging.info(" adding operations")

    mobility_action.set_operations(
        circus.actors["customers"].ops.lookup(
            id_field="CUST_ID",
            select={"CURRENT_SITE": "PREV_SITE"}),

        # selects a destination site (or maybe the same as current... ^^)

        circus.actors["customers"] \
            .get_relationship("POSSIBLE_SITES") \
            .ops.select_one(from_field="CUST_ID", named_as="NEW_SITE"),

        # update the SITE attribute of the customers accordingly
        circus.actors["customers"] \
            .get_attribute("CURRENT_SITE") \
            .ops.update(
                id_field="CUST_ID",
                copy_from_field="NEW_SITE"),

        circus.clock.ops.timestamp(named_as="TIME"),

        # create mobility logs
        FieldLogger(log_id="customer_mobility_logs",
                    cols=["TIME", "CUST_ID", "PREV_SITE",
                          "NEW_SITE"]),
    )
Ejemplo n.º 6
0
    def __init__(self, clock, seed):

        start_date = pd.Timestamp("6 June 2016 00:00:00")
        CyclicTimerGenerator.__init__(
            self,
            clock=clock,
            seed=seed,
            config=CyclicTimerProfile(profile=[5., 5., 5., 5., 5., 3., 3.],
                                      profile_time_steps="1D",
                                      start_date=start_date),
        )
Ejemplo n.º 7
0
 def __init__(self, clock, seed):
     # any date starting at midnight is ok...
     start_date = pd.Timestamp("6 June 2016 00:00:00")
     CyclicTimerGenerator.__init__(
         self,
         clock=clock,
         seed=seed,
         config=CyclicTimerProfile(
             profile=[
                 1, .5, .2, .15, .2, .4, 3.8, 7.2, 8.4, 9.1, 9.0, 8.3, 8.1,
                 7.7, 7.4, 7.8, 8.0, 7.9, 9.7, 10.4, 10.5, 8.8, 5.7, 2.8
             ],
             profile_time_steps="1h",
             start_date=start_date,
         ),
     )
Ejemplo n.º 8
0
def build_uganda_populations(circus):

    seeder = seed_provider(12345)

    cells = circus.create_population(name="cells",
                                     ids_gen=SequencialGenerator(prefix="CELL_"),
                                     size=200)
    latitude_generator = FakerGenerator(method="latitude",
                                        seed=next(seeder))
    cells.create_attribute("latitude", init_gen=latitude_generator)

    longitude_generator = FakerGenerator(method="longitude",
                                         seed=next(seeder))
    cells.create_attribute("longitude", init_gen=longitude_generator)

    # the cell "health" is its probability of accepting a call. By default
    # let's says it's one expected failure every 1000 calls
    healthy_level_gen = build_healthy_level_gen(next(seeder))

    cells.create_attribute(name="HEALTH", init_gen=healthy_level_gen)

    city_gen = FakerGenerator(method="city", seed=next(seeder))
    cities = circus.create_population(name="cities", size=200, ids_gen=city_gen)

    cell_city_rel = cities.create_relationship("CELLS")

    cell_city_df = make_random_assign(cells.ids, cities.ids, next(seeder))
    cell_city_rel.add_relations(
        from_ids=cell_city_df["chosen_from_set2"],
        to_ids=cell_city_df["set1"])

    pop_gen = ParetoGenerator(xmin=10000, a=1.4, seed=next(seeder))
    cities.create_attribute("population", init_gen=pop_gen)

    timer_config = CyclicTimerProfile(
        profile=[1, .5, .2, .15, .2, .4, 3.8,
                 7.2, 8.4, 9.1, 9.0, 8.3, 8.1,
                 7.7, 7.4, 7.8, 8.0, 7.9, 9.7,
                 10.4, 10.5, 8.8, 5.7, 2.8],
        profile_time_steps="1h",
        start_date=pd.Timestamp("6 June 2016 00:00:00"))

    return cells, cities, timer_config
Ejemplo n.º 9
0
def run_test_scenario_1(clock_step, simulation_duration, n_stories, per,
                        log_folder):

    circus = Circus(name="tested_circus",
                    master_seed=1,
                    start=pd.Timestamp("8 June 2016"),
                    step_duration=pd.Timedelta(clock_step))

    population = circus.create_population(name="a",
                                          size=1000,
                                          ids_gen=SequencialGenerator(
                                              max_length=3, prefix="id_"))

    daily_profile = CyclicTimerGenerator(
        clock=circus.clock,
        config=CyclicTimerProfile(profile=[1] * 24,
                                  profile_time_steps="1h",
                                  start_date=pd.Timestamp("8 June 2016")),
        seed=1234)

    # each of the 500 populations have a constant 12 logs per day rate
    activity_gen = ConstantGenerator(
        value=daily_profile.activity(n=n_stories, per=per))

    # just a dummy operation to produce some logs
    story = circus.create_story(name="test_story",
                                initiating_population=population,
                                member_id_field="some_id",
                                timer_gen=daily_profile,
                                activity_gen=activity_gen)

    story.set_operations(circus.clock.ops.timestamp(named_as="TIME"),
                         FieldLogger(log_id="the_logs"))

    circus.run(duration=pd.Timedelta(simulation_duration),
               log_output_folder=log_folder)
Ejemplo n.º 10
0
    def add_mobility(self, subs, cells):
        """
        adds a CELL attribute to the customer population + a mobility story that
        randomly moves customers from CELL to CELL among their used cells.
        """
        logging.info("Adding mobility ")

        # mobility time profile: assign high mobility activities to busy hours
        # of the day
        mov_prof = [
            1., 1., 1., 1., 1., 1., 1., 1., 5., 10., 5., 1., 1., 1., 1., 1.,
            1., 5., 10., 5., 1., 1., 1., 1.
        ]
        mobility_time_gen = CyclicTimerGenerator(
            clock=self.clock,
            seed=next(self.seeder),
            config=CyclicTimerProfile(
                profile=mov_prof,
                profile_time_steps="1H",
                start_date=pd.Timestamp("12 September 2016 00:00.00")))

        # Mobility network, i.e. choice of cells per user, i.e. these are the
        # weighted "used cells" (as in "most used cells) for each user
        mobility_weight_gen = NumpyRandomGenerator(method="exponential",
                                                   scale=1.,
                                                   seed=next(self.seeder))

        mobility_rel = subs.create_relationship("POSSIBLE_CELLS")

        logging.info(" creating bipartite graph ")
        mobility_df = pd.DataFrame.from_records(make_random_bipartite_data(
            subs.ids, cells.ids, 0.4, seed=next(self.seeder)),
                                                columns=["USER_ID", "CELL"])

        logging.info(" adding mobility relationships to customer")
        mobility_rel.add_relations(from_ids=mobility_df["USER_ID"],
                                   to_ids=mobility_df["CELL"],
                                   weights=mobility_weight_gen.generate(
                                       mobility_df.shape[0]))

        logging.info(" creating customer's CELL attribute ")

        # Initialize the mobility by allocating one first random cell to each
        # customer among its network
        subs.create_attribute(name="CELL", init_relationship="POSSIBLE_CELLS")

        # Mobility story itself, basically just a random hop from cell to cell,
        # that updates the "CELL" attributes + generates mobility logs
        logging.info(" creating mobility story")
        mobility_story = self.create_story(
            name="mobility",
            initiating_population=subs,
            member_id_field="A_ID",
            timer_gen=mobility_time_gen,
        )

        logging.info(" adding operations")
        mobility_story.set_operations(
            subs.ops.lookup(id_field="A_ID", select={"CELL": "PREV_CELL"}),

            # selects a destination cell (or maybe the same as current... ^^)
            mobility_rel.ops.select_one(from_field="A_ID",
                                        named_as="NEW_CELL"),

            # update the CELL attribute of the customers accordingly
            subs.get_attribute("CELL").ops.update(member_id_field="A_ID",
                                                  copy_from_field="NEW_CELL"),
            self.clock.ops.timestamp(named_as="TIME"),

            # create mobility logs
            operations.FieldLogger(
                log_id="mobility_logs",
                cols=["TIME", "A_ID", "PREV_CELL", "NEW_CELL"]),
        )

        logging.info(" done")
Ejemplo n.º 11
0
after_work = [0] * (23 - end_hour)

# the sum of before_work, during_work and after_work is always 24
week_day_profile = before_work + during_work + after_work
# weekend_day_profile = [0] * 24

# week_profile = week_day_profile * 5 + weekend_day_profile * 2
# week_profile = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 1.0, 1.0, 0, 0, 0, 1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

#for testing purposes, ensures that all days have logs
week_profile = week_day_profile * 7

story_timer_gen = CyclicTimerGenerator(clock=example1.clock,
                                       seed=next(example1.seeder),
                                       config=CyclicTimerProfile(
                                           profile=week_profile,
                                           profile_time_steps="1h",
                                           start_date=start_date))

low_activity = story_timer_gen.activity(n=10, per=pd.Timedelta("1 day"))
med_activity = story_timer_gen.activity(n=15, per=pd.Timedelta("1 day"))
high_activity = story_timer_gen.activity(n=num_log, per=pd.Timedelta("1 day"))

activity_gen = NumpyRandomGenerator(
    method="choice",
    a=[low_activity, med_activity, high_activity],
    p=[0, 0, 1],
    seed=next(example1.seeder))

hello_world = example1.create_story(
    name="hello_world",
    initiating_population=person,