Esempio n. 1
0
def test_execute():
    ins = Pair()
    ins.set([
        {
            SIZE_KEY: 0.5,
            IID_KEY: '1',
            USER_KEY: 'Bob',
            CATEGORY_KEY: 'ICP_A'
        },
        {
            SIZE_KEY: 2,
            IID_KEY: '2',
            USER_KEY: 'Bob',
            CATEGORY_KEY: 'ICP_B'
        },
        {
            SIZE_KEY: 1,
            IID_KEY: '3',
            USER_KEY: 'Lily',
            CATEGORY_KEY: 'ICP_A'
        },
        {
            SIZE_KEY: 8,
            IID_KEY: '4',
            USER_KEY: 'Bob',
            CATEGORY_KEY: 'ICP_A'
        },
        {
            SIZE_KEY: 4,
            IID_KEY: '5',
            USER_KEY: 'Lily',
            CATEGORY_KEY: 'ICP_B'
        },
    ])
    ret = ins.execute()
    print(ret)
Esempio n. 2
0
class GameSimulation:
    def __init__(self, sd: list[dict] or int):
        self._simula_user(sd)
        # self.data, self.all_size = simula_user(sd)
        self.pair_ins = Pair()
        self.paired: dict = dict()
        self.icp = dict()
        self.all_icp = dict()
        self.vote_result: list[dict] = []
        self.all_vote_result = {}
        self.all_user_reward = {}
        self.all_user_ei = {}
        self.sid = None
        self.user_size = {}
        self.user_real_size = {}
        self.user_reward = {}
        self.user_ei = {}

    def _simula_user(self, data):
        if isinstance(data, int):
            data = repeat(dict(), data)
        self.users = {}
        self.user_factor = {}
        self.all_user_factor = defaultdict(list)

        for i, d in enumerate(data):
            uid = d.get(USER_KEY) or str(i)
            greed = d.get(GREED_KEY) or DEFAULT_GREED
            dissent_tolerance = d.get(
                DISSENT_TOLERANCE_KEY) or DEFAULT_DISSENT_TOLERANCE
            objective_voting = d.get(
                SUBJECTIVE_VOTING_KEY) or DEFAULT_OBJECTIVE_VOTING
            reward_tolerance = d.get('rt') or round(random.gauss(4, 1))
            reliability_factor = 1
            self.user_factor[uid] = {
                'greed': greed,
                'dissent_tolerance': dissent_tolerance,
                'objective_voting': objective_voting,
                'reward_tolerance': reward_tolerance,
                'reliability_factor': reliability_factor
            }
            name = d.get(UNAME_KEY) or faker.name()
            self.users[uid] = {USER_KEY: uid, UNAME_KEY: name}
            print(f'用户 id={uid} {name} 加入了, 他的贪婪值是 {greed}, '
                  f'异议容忍度是 {dissent_tolerance}, '
                  f'报酬落差容忍度是 {reward_tolerance}, '
                  f'主观投票度是 {objective_voting}, '
                  f'目前可靠系数 1')
            self.all_user_factor[uid].append(self.user_factor[uid])

    def simula_icp(self, sid):
        all_size = 0
        self.icp = dict()
        self.sid = sid
        self.user_size = {}
        self.user_real_size = {}
        self.user_reward = {}
        self.user_ei = {}
        for u in self.users:
            icp_num = 3
            icp, size, real_size = self._gen_icp(u, icp_num)
            self.user_size[u] = size
            self.user_real_size[u] = real_size
            print(f'用户 id={u} {self.users[u][UNAME_KEY]} '
                  f'本次产出了 {icp_num} 个 ICP, '
                  f'实际工作 size={real_size}, '
                  f'申报 size={size}')
            all_size += size
            self.icp[u] = icp
        self.all_icp[sid] = self.icp

    def _gen_icp(self, uid: str, num: int) -> (list, float):
        icp = []
        all_size = 0
        all_real_size = 0
        for i in range(num):
            real_value = round(random.gauss(8, 1), 1)
            if real_value <= 0:
                continue
            iid = f'{uid}.{i}'
            offset = random.gauss(self.user_factor[uid]['greed'],
                                  self.user_factor[uid]['dissent_tolerance'])
            size = round(real_value + offset, 1)
            if size <= 0:
                size = 0.1
            icp.append({
                USER_KEY: uid,
                IID_KEY: iid,
                'title': f'this is {uid}-{i} icp.',
                'real_value': real_value,
                SIZE_KEY: size,
                CATEGORY_KEY: ascii_uppercase[random.randint(0, 25)]
            })
            all_size += size
            all_real_size += real_value
        return icp, all_size, all_real_size

    def do_pair(self):
        need_pair = []
        for x in self.icp.values():
            need_pair += x
        self.pair_ins.set(need_pair)
        self.paired = self.pair_ins.execute()
        return self.paired

    def do_vote(self, u, pv):
        if len(self.paired) == 0:
            raise NotYetPairedError
        for p in self.paired[u]:
            p[VOTED_KEY] = pv[p[PID_KEY]]
            self.vote_result.append(p)

    def auto_vote(self, u):
        ov = self.user_factor[u]['objective_voting']
        for p in self.paired[u]:
            pa_size = p[PAIR_KEY][0][SIZE_KEY]
            pb_size = p[PAIR_KEY][1][SIZE_KEY]
            ov_value = random.gauss(pa_size / pb_size, ov)
            if ov_value < 1:
                p[VOTED_KEY] = 0
            else:
                p[VOTED_KEY] = 1
            # if pa_size < pb_size:
            #     p[VOTED_KEY] = 0
            # else:
            #     p[VOTED_KEY] = 1
            self.vote_result.append(p)

    def all_auto_vote(self):
        if len(self.paired) == 0:
            raise NotYetPairedError
        self.vote_result = []
        for u in self.paired:
            self.auto_vote(u)
        self.all_vote_result[self.sid] = self.vote_result

    def _calculate_es(self):
        if len(self.vote_result) == 0:
            raise NotYetVotedError
        user_es = defaultdict(Decimal)
        for vr in self.vote_result:
            if vr[VOTED_KEY] == -1:
                raise NotYetVoteError
            for i, p in enumerate(vr[PAIR_KEY]):
                if i == vr[VOTED_KEY]:
                    user_es[p[USER_KEY]] += Decimal(str(p[SIZE_KEY]))
                else:
                    user_es[p[USER_KEY]] += Decimal('0')
        return user_es

    def stat_v2(self):
        user_es = self._calculate_es()
        not_good_user = {}
        for u in user_es:

            self.user_ei[u] = float(user_es[u]) / (self.user_size[u] * 2)
            if self.user_ei[u] == 0:
                self.user_ei[u] = 0.1
            if self.user_ei[u] < 0.5:
                print([
                    self.user_factor[u]["reliability_factor"], self.user_ei[u]
                ])
                self.user_factor[u]["reliability_factor"] = geometric_mean([
                    self.user_factor[u]["reliability_factor"], self.user_ei[u]
                ])
            else:
                self.user_factor[u]["reliability_factor"] = harmonic_mean([
                    self.user_factor[u]["reliability_factor"], self.user_ei[u]
                ])
            if self.user_ei[u] < 0.5:
                self.user_reward[u] = self.user_size[u] * self.user_factor[u][
                    "reliability_factor"]
                if self.user_ei[u] < 0.25:
                    not_good_user[u] = self.user_factor[u][
                        "reliability_factor"]
            else:
                self.user_reward[u] = self.user_size[u]

            self.user_factor[u]['dissent_tolerance'] = math.log(
                len(self.all_icp)
            ) + self.all_user_factor[u][0]['dissent_tolerance']

            rc = random.gauss(self.user_reward[u] / self.user_size[u],
                              self.user_factor[u]['dissent_tolerance'])
            if rc < 1:
                self.user_factor[u][
                    'greed'] = self.user_factor[u]['greed'] * 0.9

            print(f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                  f'实际 size={self.user_real_size[u]}, '
                  f'申报了 {self.user_size[u]}, 最终得到了 '
                  f'{self.user_reward[u]}, 他本次的 EI 值为 {self.user_ei[u]}'
                  f'他的可靠系数为 {self.user_factor[u]["reliability_factor"]}, '
                  f'由于他具有异议容忍度, 他心理估计值为 {rc}, '
                  f'他的贪婪度为 {self.user_factor[u]["greed"]}')
        if len(not_good_user) > 0:
            sorted_not_good = sorted(not_good_user.keys(),
                                     key=lambda x: not_good_user[x])
            print(sorted_not_good)
            print(
                f'用户 id={sorted_not_good[0]} {self.users[sorted_not_good[0]][UNAME_KEY]}, 被淘汰了'
            )
            del self.users[sorted_not_good[0]]
        else:
            print('没有用户被淘汰')

    def stat_v1(self):
        user_es = self._calculate_es()

        for u in user_es:

            self.user_ei[u] = float(user_es[u]) / (self.user_size[u] * 2)
            if self.user_ei[u] < 0.8:
                self.user_factor[u]["reliability_factor"] = geometric_mean([
                    self.user_factor[u]["reliability_factor"], self.user_ei[u]
                ])
            if self.user_factor[u]["reliability_factor"] < 0.8:
                self.user_reward[u] = self.user_size[u] * self.user_factor[u][
                    "reliability_factor"]
            else:
                self.user_reward[u] = self.user_size[u]

            if self.user_real_size[u] > self.user_size[u]:
                # 奉献型人格
                if self.user_reward[u] < self.user_size[u]:
                    pt = self.user_size[u] - self.user_reward[u]
                    if pt >= self.user_factor[u]['reward_tolerance']:
                        print(
                            f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                            f'本次具有"奉献型", 实际 size={self.user_real_size[u]}'
                            f'申报了 {self.user_size[u]}, 但只得到了 '
                            f'{self.user_reward[u]}, 他的容忍度为 {self.user_factor[u]["reward_tolerance"]} '
                            f'损失太大, 最终, 他选择了离开')
                        del self.users[u]
                    else:
                        self.user_factor[u]['reward_tolerance'] -= pt
                        self.user_factor[u]['dissent_tolerance'] = math.log(
                            len(self.all_icp)
                        ) + self.all_user_factor[u][0]['dissent_tolerance']
                        print(
                            f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                            f'本次具有"奉献型", 实际 size={self.user_real_size[u]}'
                            f'申报了 {self.user_size[u]}, 但只得到了 '
                            f'{self.user_reward[u]}, 他愿意接受这次的损失'
                            f'他的容忍度只剩下 {self.user_factor[u]["reward_tolerance"]} '
                            f'可能下次再受损, 他就离开了')
                else:
                    self.user_factor[u]['dissent_tolerance'] = math.log(
                        len(self.all_icp)
                    ) + self.all_user_factor[u][0]['dissent_tolerance']
                    print(f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                          f'本次具有"奉献型", 实际 size={self.user_real_size[u]}'
                          f'申报了 {self.user_size[u]}, 最终得到了 '
                          f'{self.user_reward[u]}, 他在默默支持, 也得到了应得的. ')
            if self.user_real_size[u] <= self.user_size[u]:
                # 贪婪型人格
                if self.user_real_size[u] < self.user_reward[
                        u] < self.user_size[u]:
                    # 自我相信: 凭本事贪到了
                    self.user_factor[u]['dissent_tolerance'] = math.log(
                        len(self.all_icp)
                    ) + self.all_user_factor[u][0]['dissent_tolerance']
                    print(f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                          f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                          f'申报了 {self.user_size[u]}, 最终得到了 '
                          f'{self.user_reward[u]}, 他贪的不多, 所以虽然没有全部拿到, '
                          f'但是, 他满意他的所得. ')
                elif self.user_reward[u] > self.user_size[u]:
                    # 根据 dt 判断, 1. 是不是贪多了, 下次少贪点, 2. 机会很大可以加大力度
                    rc = random.gauss(self.user_reward[u] / self.user_size[u],
                                      self.user_factor[u]['dissent_tolerance'])
                    if rc > 1:
                        # 1. 是不是贪多了, 下次少贪点
                        self.user_factor[u][
                            'greed'] = self.user_factor[u]['greed'] * (
                                (self.user_reward[u] / self.user_real_size[u])
                                - 1)
                        print(
                            f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                            f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                            f'申报了 {self.user_size[u]}, 最终得到了 '
                            f'{self.user_reward[u]}, 他所得要高于自己的贡献,'
                            f'由于他具有异议容忍度, 他心理估计值为 {rc}, '
                            f'他过意不去, 觉得自己是不是贪多了, '
                            f'决定下次少贪点, 他的贪婪度修正为了 {self.user_factor[u]["greed"]}'
                        )
                    else:
                        # 2. 机会很大可以加大力度
                        self.user_factor[u][
                            'greed'] = self.user_factor[u]['greed'] * 1.1
                        self.user_factor[u]['dissent_tolerance'] = math.log(
                            len(self.all_icp)
                        ) + self.all_user_factor[u][0]['dissent_tolerance']
                        print(
                            f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                            f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                            f'申报了 {self.user_size[u]}, 最终得到了 '
                            f'{self.user_reward[u]}, 他所得要高于自己的贡献,'
                            f'由于他具有异议容忍度, 他心理估计值为 {rc}, '
                            f'他过意不去, 觉得自己是不是贪多了, '
                            f'决定下次少贪点, 他的贪婪度修正为了 {self.user_factor[u]["greed"]}'
                        )
                elif self.user_reward[u] == self.user_size[u]:
                    self.user_factor[u]['dissent_tolerance'] = math.log(
                        len(self.all_icp)
                    ) + self.all_user_factor[u][0]['dissent_tolerance']
                    print(f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                          f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                          f'申报了 {self.user_size[u]}, 最终得到了 '
                          f'{self.user_reward[u]}, 他很满意, 他贪到了他期望拿到的')
                else:
                    # 贪失败了, 根据 dt 判断, 1. 减少自己的贪婪值, 2. 这次运气不行
                    # 亏太多了, 那就离开
                    pt = self.user_real_size[u] - self.user_reward[u]
                    if pt >= self.user_factor[u]['reward_tolerance']:
                        print(
                            f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                            f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                            f'申报了 {self.user_size[u]}, 最终得到了 '
                            f'{self.user_reward[u]}, 他贪失败了, 并且他觉得划不来, '
                            f'他的容忍度是 {self.user_factor[u]["reward_tolerance"]}, '
                            f'他选择离开(happy)')
                        del self.users[u]
                    else:
                        rc = random.gauss(
                            self.user_reward[u] / self.user_size[u],
                            self.user_factor[u]['dissent_tolerance'])
                        if rc > 1:
                            # 这次运气不行, 下次再试试
                            print(
                                f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                                f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                                f'申报了 {self.user_size[u]}, 最终得到了 '
                                f'{self.user_reward[u]}, 他贪失败了, '
                                f'由于他具有异议容忍度, 他心理估计值为 {rc}, '
                                f'他觉得这次只是个巧合, 所以他不打算收敛自己的贪婪, 他决定下次再试试')
                        else:
                            # 1. 减少自己的贪婪值
                            self.user_factor[u][
                                'greed'] = self.user_factor[u]['greed'] * 0.9
                            print(
                                f'用户 id={u} {self.users[u][UNAME_KEY]}, '
                                f'本次具有"贪婪型", 实际 size={self.user_real_size[u]}'
                                f'申报了 {self.user_size[u]}, 最终得到了 '
                                f'{self.user_reward[u]}, 他贪失败了, '
                                f'由于他具有异议容忍度, 他心理估计值为 {rc}, '
                                f'他觉得或许是自己太过分了, 他调整自己的贪婪度为 {self.user_factor[u]["greed"]}'
                            )