-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConsoomer.py
111 lines (100 loc) · 4.75 KB
/
Consoomer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import numpy as np
from multiprocessing import Pool
from copy import deepcopy
class Consoomer:
def __init__(self, index, purchases=np.zeros((11), dtype=int)):
self.index = index
self.population = None
self.cards = []
self.purchases = purchases
self.fees = 0
self.points = np.zeros((11), dtype=int)
self.student = 1
self.business = 0
self.bonus_cat_card = []
def init_cards(self, cards_ref):
self.cards_ref = cards_ref
num_cards = np.random.randint(2,9)
for i in range(num_cards):
if i == 0:
self.cards.append(23) #amex gold i already have this one
if i==1:
self.cards.append(42)
else:
card = np.random.randint(0, np.shape(cards_ref)[0])
while card in self.cards or cards_ref[card][0] > self.student or cards_ref[card][1] > self.business:
card = np.random.randint(0, np.shape(cards_ref)[0])
self.cards.append(card)
self.cards = np.asarray(self.cards)
def designate_cards(self):
# randomly assign cards from self.cards into self.purchases repeats allowed
self.purchases = np.random.choice(self.cards, len(self.purchases)).astype(int)
def shuffle_cards(self, shuffle=0.75):
# randomly assign cards from self.cards into self.purchases repeats allowed4
#print(f"Shuffling cards: {self.cards} with distribution {self.purchases}")
for i in range(len(self.purchases)):
if np.random.random() >= shuffle:
self.purchases[i] = np.random.choice(self.cards)
#
#print(f"Shuffled cards: {self.cards} with distribution {self.purchases}")
return self
def mutate_cards(self, retention=0.75):
"""
retention: probability of keeping all cards from previous generation
shuffle: probability of using same card for a given category from previous generation
"""
num_cards = len(self.cards)
num_purchases = len(self.purchases)
for i in range(num_cards):
cur_card = self.cards[i]
if np.random.random() >= retention:
new_card = np.random.randint(0, self.card_mat_len)
while new_card in self.cards or self.cards_ref[new_card][0] > self.student or self.cards_ref[new_card][1] > self.business:
#print(f"New card {new_card} already in cards {self.cards}")
new_card = np.random.randint(0, self.card_mat_len)
self.cards[i] = int(new_card)
mask = self.purchases == cur_card
self.purchases[mask] = new_card
#print(f"Mutated card: {cur_card} to {new_card}")
# shuffle purchases
self = self.shuffle_cards()
#print(f"Mutated cards: {self.cards} with distribution {self.purchases}")
return self
def breed(self, mate, card_mat_len, index=-1):
new_cons = deepcopy(self)
new_cons.cards = []
new_cons.purchases = np.zeros((11), dtype=int)
new_cons.card_mat_len = card_mat_len
#pick length of cards as random choice between the parents length
off = 0
#print(f"\nStart breed: {self.cards}, {mate.cards}")
for i in range(len(new_cons.purchases)):
if len(new_cons.cards) < 6:
#print(self.purchases[i], mate.purchases[i])
new_cons.purchases[i] = np.random.choice([self.purchases[i], mate.purchases[i]])
#print(f"New purchase: {new_cons.purchases[i]}")
if not new_cons.purchases[i] in new_cons.cards:
new_cons.cards = np.append(new_cons.cards, new_cons.purchases[i])
else:
#start copying from the front of the new_cons.purchases array
#for example
#[1,2,3,4,5,x,x,x]
#if we hit 5 card limit at 5, fill in the x's with 1,2,3
new_cons.purchases[i] = new_cons.purchases[0+off]
off += 1
if len(new_cons.cards) == 1:
new_cons.cards = np.append(new_cons.cards, np.random.randint(0, card_mat_len-1))
#print(f"End breed: {new_cons.cards}, {new_cons.purchases}")
#print("Start mutate")
new_cons = new_cons.mutate_cards()
return new_cons
def calc_annual_fee(self, annual_fee_mat, first_year=True):
self.fees = 0
for i in range(len(self.cards)):
self.fees -= annual_fee_mat[int(self.cards[i])]
return self.fees
def calc_bonus_offer(self, offer_points_mat):
self.points = 0
for i in range(len(self.cards)):
self.points += offer_points_mat[int(self.cards[i])]
return self.points