Include Only Unique Values in a PuLP Optimization Solution - python

This post is a related question that spun off of this question.
My goal is to generate an optimal fantasy football lineup given a set of constraints. Due to the nature of the fantasy football league, it is possible that I have the same player multiple times in my inventory, although I can only play one instance of that player in my lineup. I have created an optimization problem using PuLP to generate the lineup, but I need to add a constraint to ensure that a player does not appear in that lineup more than once.
Below is my current model. Any suggestions on how to ensure no duplicate players in my solution are appreciated!
import pandas as pd
import pulp
print('--- (1/4) Defining the problem ---')
# Read csv
raw_data = pd.read_csv('./csv/fantasypros.csv')
# create new columns that has binary numbers if player == a specific position
encoded = pd.get_dummies(raw_data['Pos. Parent']) # <-- One-Hote Encoding
raw_data = raw_data.join(encoded) # <-- joining it to the raw_data table
raw_data["salary"] = raw_data["Point Cost"].astype(float)
model = pulp.LpProblem("NFTdraft", pulp.LpMaximize)
total_points = {}
cost = {}
qb = {}
rb = {}
wr = {}
te = {}
k = {}
dst = {}
dk = {}
num_players = {}
vars_list = []
# i = row index, player = player attributes
for i, player in raw_data.iterrows():
var_name = 'x' + str(i) # Create variable name
decision_var = pulp.LpVariable(var_name, cat='Binary') # Initialize Variables
total_points[decision_var] = player["FPTS"] # Create FPTS Dictionary
cost[decision_var] = player["salary"] # Create Cost Dictionary
# Create Dictionary for Player Types
qb[decision_var] = player["QB"]
rb[decision_var] = player["RB"]
wr[decision_var] = player["WR"]
te[decision_var] = player["TE"]
k[decision_var] = player["K"]
dst[decision_var] = player["DST"]
dk[decision_var] = player["DK"]
num_players[decision_var] = 1.0
objective_function = pulp.LpAffineExpression(total_points)
model += objective_function
total_cost = pulp.LpAffineExpression(cost)
model += (total_cost <= 135)
print('--- (2/4) Defining the constraints ---')
QB_constraint = pulp.LpAffineExpression(qb)
RB_constraint = pulp.LpAffineExpression(rb)
WR_constraint = pulp.LpAffineExpression(wr)
TE_constraint = pulp.LpAffineExpression(te)
K_constraint = pulp.LpAffineExpression(k)
DST_constraint = pulp.LpAffineExpression(dst)
DK_constraint = pulp.LpAffineExpression(dk)
total_players = pulp.LpAffineExpression(num_players)
model += (QB_constraint >= 1)
model += (QB_constraint <= 2)
model += (RB_constraint <= 8)
model += (WR_constraint <= 8)
model += (TE_constraint <= 8)
model += (K_constraint <= 1)
model += (DST_constraint <= 1)
model += (DK_constraint <= 2)
model += (total_players == 10)
print('--- (3/4) Solving the problem ---')
model.solve()
print('--- (4/4) Formatting the results ---')
raw_data["is_drafted"] = 0.0
for var in model.variables():
raw_data.loc[int(var.name[1:]), 'is_drafted'] = var.varValue # <--- CHANGED HERE
my_team = raw_data[raw_data["is_drafted"] == 1.0]
my_team = my_team[["Asset Name", "Player", "Pos. Parent", "Rarity", "Point Cost", "FPTS"]]
print(my_team)
print("Total used amount of salary cap: {}".format(my_team["Point Cost"].sum()))
print("Projected points: {}".format(my_team["FPTS"].sum().round(1)))
print('--- Completed ---')

To set the restriction to only allow single player (from your dataframe of duplicate players) you'll need to setup something similar to the other restrictions). Here we'll just one-hot encode on "Player", then loop through that to create the restriction that you have to have 1 or less of each "Player" name.
import pandas as pd
import pulp
print('--- (1/4) Defining the problem ---')
# Read csv
raw_data = pd.read_csv('./csv/fantasypros.csv').drop_duplicates().reset_index(drop=True)
# create new columns that has binary numbers if player == a specific position
encoded = pd.get_dummies(raw_data['Pos. Parent']) #<-- One-Hote Encoding
raw_data = raw_data.join(encoded) #<-- joining it to the raw_data table
# Will be used to create the constraint of not using same player name in lineup
encoded = pd.get_dummies(raw_data['Player']) #<-- One-Hote Encoding
raw_data = raw_data.join(encoded) #<-- joining it to the raw_data table
raw_data["salary"] = raw_data["Point Cost"].astype(float)
model = pulp.LpProblem("NFTdraft", pulp.LpMaximize)
total_points = {}
cost = {}
qb = {}
rb = {}
wr = {}
te = {}
k = {}
dst = {}
dk = {}
num_players = {}
# Here I created a list of all the possible players in the dataframe
# This is used later to construct the dictionary of players, then
# to add each of those into the model
players_list = list(raw_data['Player'].unique())
players_list.sort()
pLAYER_dict = {}
for player in players_list:
pLAYER_dict[player] ={}
vars_list = []
# i = row index, player = player attributes
for i, player in raw_data.iterrows():
#print('Processing row: %s of %s' %((i+1),len(raw_data)))
var_name = 'x' + str(i) # Create variable name
decision_var = pulp.LpVariable(var_name, cat='Binary') # Initialize Variables
total_points[decision_var] = player["FPTS"] # Create FPTS Dictionary
cost[decision_var] = player["salary"] # Create Cost Dictionary
# Create Dictionary for Player Types
qb[decision_var] = player["QB"]
rb[decision_var] = player["RB"]
wr[decision_var] = player["WR"]
te[decision_var] = player["TE"]
k[decision_var] = player["K"]
dst[decision_var] = player["DST"]
dk[decision_var] = player["DK"]
num_players[decision_var] = 1.0
# Here is where I store each value for each player name for the player
for key, v in PLAYER_dict.items():
PLAYER_dict[key].update({decision_var:player[key]})
objective_function = pulp.LpAffineExpression(total_points)
model += objective_function
total_cost = pulp.LpAffineExpression(cost)
model += (total_cost <= 135)
print('--- (2/4) Defining the constraints ---')
QB_constraint = pulp.LpAffineExpression(qb)
RB_constraint = pulp.LpAffineExpression(rb)
WR_constraint = pulp.LpAffineExpression(wr)
TE_constraint = pulp.LpAffineExpression(te)
K_constraint = pulp.LpAffineExpression(k)
DST_constraint = pulp.LpAffineExpression(dst)
DK_constraint = pulp.LpAffineExpression(dk)
total_players = pulp.LpAffineExpression(num_players)
model += (QB_constraint >= 1)
model += (QB_constraint <= 2)
model += (RB_constraint <= 8)
model += (WR_constraint <= 8)
model += (TE_constraint <= 8)
model += (K_constraint <= 1)
model += (DST_constraint <= 1)
model += (DK_constraint <= 2)
model += (total_players == 10)
for k1, v1 in PLAYER_dict.items():
player_constraint = pulp.LpAffineExpression(v1)
model += (player_constraint <= 1)
print('--- (3/4) Solving the problem ---')
model.solve()
print('--- (4/4) Formatting the results ---')
raw_data["is_drafted"] = 0.0
for var in model.variables():
raw_data.loc[int(var.name[1:]), 'is_drafted'] = var.varValue # <--- CHANGED HERE
my_team = raw_data[raw_data["is_drafted"] == 1.0]
my_team = my_team[["Asset Name", "Player", "Pos. Parent", "Rarity", "Point Cost", "FPTS"]]
print(my_team)
print("Total used amount of salary cap: {}".format(my_team["Point Cost"].sum()))
print("Projected points: {}".format(my_team["FPTS"].sum().round(1)))
print('--- Completed ---')
Output:
Asset Name Player ... Point Cost FPTS
59 Arizona WR #1 DeAndre Hopkins ... 19 20.301
375 Carolina RB #1 Christian McCaffrey ... 20 26.500
582 Cincinnati WR #3 Tyler Boyd ... 10 13.000
803 Denver RB #2 Javonte Williams ... 8 11.100
1011 Green Bay WR #4 Randall Cobb ... 5 8.800
1170 Indianapolis QB #2 Jacob Eason ... 5 11.400
1301 Kansas City QB #1 Patrick Mahomes II ... 20 23.900
1349 Kansas City WR #1 Tyreek Hill ... 20 21.100
1658 Minnesota RB #1 Dalvin Cook ... 20 22.500
2729 Washington WR #2 Curtis Samuel ... 8 11.700
[10 rows x 6 columns]
Total used amount of salary cap: 135
Projected points: 170.3
--- Completed ---

Related

Python negative Value Error dimensions are not allowed

I am implementing genetic algorithm but I am facing an error after the first generation with the message: ValueError: negative dimensions are not allowed
I actually change the nfilters parameter from nfilters=[74,27,23] to nfilters=[64,128,256], I don't know if it is due to this parameters.
I declared my class sequential as follow:
class CNN(Sequential):
def __init__(self,nfilters,sfilters):
super().__init__()
tf.random.set_seed(0)
self.add(Conv2D(nfilters[0],kernel_size=(sfilters[0],sfilters[0]),padding='same',activation='relu',input_shape=(50,50,3)))
self.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))
self.add(Conv2D(nfilters[1],kernel_size=(sfilters[1],sfilters[1]),padding='same',activation='relu'))
self.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))
self.add(Conv2D(nfilters[2],kernel_size=(sfilters[2],sfilters[2]),padding='same',activation='relu'))
self.add(Conv2D(nfilters[2], kernel_size=(sfilters[2], sfilters[2]), padding='same', activation='relu'))
self.add(Flatten())
self.add(Dropout(0.5))
self.add(Dense(128,activation='relu'))
self.add(Dropout(0.5))
self.add(Dense(128, activation='relu'))
self.add(Dense(num_classes, activation='sigmoid'))
self.compile(loss=keras.losses.binary_crossentropy,
optimizer=tf.optimizers.Adam(learning_rate=0.001),
metrics=['accuracy'])
nfilters = [64,128,256] #nfilters = [74,27,23]
sfilters = [9,3,2] #sfilters = [9,3,2]
Then my class genetic is declared as the following:
class Genetic:
def __init__(self,pop_size,nlayers,max_nfilters,max_sfilters):
self.pop_size = pop_size
self.nlayers = nlayers
self.max_nfilters = max_nfilters
self.max_sfilters = max_sfilters
self.max_acc = 0
self.best_arch = np.zeros((1,6))
self.gen_acc = []
def generate_population(self):
np.random.seed(0)
pop_nlayers = np.random.randint(1,self.max_nfilters,(self.pop_size,self.nlayers))
pop_sfilters = np.random.randint(1,self.max_sfilters,(self.pop_size,self.nlayers))
pop_total = np.concatenate((pop_nlayers,pop_sfilters),axis=1)
return pop_total
def select_parents(self,pop,nparents,fitness):
parents = np.zeros((nparents,pop.shape[1]))
for i in range(nparents):
best = np.argmax(fitness)
parents[i] = pop[best]
fitness[best] = -99999
return parents
def crossover(self,parents):
nchild = self.pop_size - parents.shape[0]
nparents = parents.shape[0]
child = np.zeros((nchild,parents.shape[1]))
for i in range(nchild):
first = i % nparents
second = (i+1) % nparents
child[i,:2] = parents[first][:2]
child[i,2] = parents[second][2]
child[i,3:5] = parents[first][3:5]
child[i,5] = parents[second][5]
return child
def mutation(self,child):
for i in range(child.shape[0]):
val = np.random.randint(1,6)
ind = np.random.randint(1,4) - 1
if child[i][ind] + val > 100:
child[i][ind] -= val
else:
child[i][ind] += val
val = np.random.randint(1,4)
ind = np.random.randint(4,7) - 1
if child[i][ind] + val > 20:
child[i][ind] -= val
else:
child[i][ind] += val
return child
def fitness(self,pop,X,Y,epochs):
pop_acc = []
for i in range(pop.shape[0]):
nfilters = pop[i][0:3]
sfilters = pop[i][3:]
model = CNN(nfilters,sfilters)
#H = model.fit_generator(datagen.flow(X,Y,batch_size=256),epochs=epochs,callbacks=[early_stopping_monitor])
H = model.fit_generator(datagen.flow(X,Y,batch_size=256),steps_per_epoch=len(X_trainRusReshaped) / batch_size,epochs=epochs,validation_data=(X_testRusReshaped, Y_testRusHot),callbacks=[early_stopping_monitor])
acc = H.history['accuracy']
pop_acc.append(max(acc)*100)
if max(pop_acc) > self.max_acc:
self.max_acc = max(pop_acc)
self.best_arch = pop[np.argmax(pop_acc)]
self.gen_acc.append(max(pop_acc))
return pop_acc
def smooth_curve(self,factor,gen):
smoothed_points = []
for point in self.gen_acc:
if smoothed_points:
prev = smoothed_points[-1]
smoothed_points.append(prev*factor + point * (1-factor))
else:
smoothed_points.append(point)
plt.plot(range(gen+1),smoothed_points,'g',label='Smoothed training acc')
plt.xticks(np.arange(gen+1))
plt.legend()
plt.title('Fitness Accuracy vs Generations')
plt.xlabel('Generations')
plt.ylabel('Fitness (%)')
plt.show()
plt.savefig('smoothCurve.png')
When I launch these lines of codes, I have the error after 20 epochs on the first generation:
#Starting Genetic Algoritm
pop_size = 2 #10
nlayers = 3 #3
max_nfilters = 500 #100
max_sfilters = 20
epochs = 20
num_generations = 2 #10
genCNN = Genetic(pop_size,nlayers,max_nfilters,max_sfilters)
pop = genCNN.generate_population()
for i in range(num_generations+1):
pop_acc = genCNN.fitness(pop,X_trainRusReshaped,Y_trainRusHot,epochs)
print('Best Accuracy at the generation {}: {}'.format(i,genCNN.max_acc))
parents = genCNN.select_parents(pop,5,pop_acc.copy())
child = genCNN.crossover(parents)
child = genCNN.mutation(child)
pop = np.concatenate((parents,child),axis=0).astype('int')
Any idea where this error is coming from? I tried to increase max_filters from 100 to 500 but it does not solved anything.

TypeError: argument of type 'method' is not iterable using RL Classifiers

I am working on a classification problem using Reinforcement Learning using the link https://github.com/gcamfer/Anomaly-ReactionRL/blob/master/Notebooks/AE_RL_awid.ipynb
I am facing error in the part of code shown below:
if __name__ == "__main__":
# Train batch
batch_size = 1
# batch of memory ExpRep
minibatch_size = 10
ExpRep = True
iterations_episode = 100
# Initialization of the enviroment
env = RLenv("train",batch_size=batch_size,
iterations_episode=iterations_episode)
# obs_size = size of the state
obs_size = env.data_shape[1]-len(env.all_attack_names)
#num_episodes = int(env.data_shape[0]/(iterations_episode)/10)
num_episodes = 100
'''
Definition for the defensor agent.
'''
defender_valid_actions = list(range(len(env.attack_types))) # only detect type of attack
defender_num_actions = len(defender_valid_actions)
def_epsilon = 1 # exploration
min_epsilon = 0.01 # min value for exploration
def_gamma = 0.001
def_decay_rate = 0.999
def_hidden_size = 100
def_hidden_layers = 2
def_learning_rate = .01
defender_agent = DefenderAgent(defender_valid_actions,obs_size,"EpsilonGreedy",
epoch_length = iterations_episode,
epsilon = def_epsilon,
min_epsilon = min_epsilon,
decay_rate = def_decay_rate,
gamma = def_gamma,
hidden_size=def_hidden_size,
hidden_layers=def_hidden_layers,
minibatch_size = minibatch_size,
mem_size = 1000,
learning_rate=def_learning_rate,
ExpRep=ExpRep)
#Pretrained defender
#defender_agent.model_network.model.load_weights("models/type_model.h5")
'''
Definition for the attacker agent.
In this case the exploration is better to be greater
The correlation sould be greater too so gamma bigger
'''
attack_valid_actions = list(range(len(env.attack_names)))
attack_num_actions = len(attack_valid_actions)
att_epsilon = 1
min_epsilon = 0.99 # min value for exploration
att_gamma = 0.001
att_decay_rate = 0.99
att_hidden_layers = 1
att_hidden_size = 100
att_learning_rate = 0.2
attacker_agent = AttackAgent(attack_valid_actions,obs_size,"EpsilonGreedy",
epoch_length = iterations_episode,
epsilon = att_epsilon,
min_epsilon = min_epsilon,
decay_rate = att_decay_rate,
gamma = att_gamma,
hidden_size=att_hidden_size,
hidden_layers=att_hidden_layers,
minibatch_size = minibatch_size,
mem_size = 1000,
learning_rate=att_learning_rate,
ExpRep=ExpRep)
# Statistics
att_reward_chain = []
def_reward_chain = []
att_loss_chain = []
def_loss_chain = []
def_total_reward_chain = []
att_total_reward_chain = []
# Print parameters
print("-------------------------------------------------------------------------------")
print("Total epoch: {} | Iterations in epoch: {}"
"| Minibatch from mem size: {} | Total Samples: {}|".format(num_episodes,
iterations_episode,minibatch_size,
num_episodes*iterations_episode))
print("-------------------------------------------------------------------------------")
print("Dataset shape: {}".format(env.data_shape))
print("-------------------------------------------------------------------------------")
print("Attacker parameters: Num_actions={} | gamma={} |"
" epsilon={} | ANN hidden size={} | "
"ANN hidden layers={}|".format(attack_num_actions,
att_gamma,att_epsilon, att_hidden_size,
att_hidden_layers))
print("-------------------------------------------------------------------------------")
print("Defense parameters: Num_actions={} | gamma={} | "
"epsilon={} | ANN hidden size={} |"
" ANN hidden layers={}|".format(defender_num_actions,
def_gamma,def_epsilon,def_hidden_size,
def_hidden_layers))
print("-------------------------------------------------------------------------------")
# Main loop
attacks_by_epoch = []
attack_labels_list = []
for epoch in range(num_episodes):
start_time = time.time()
att_loss = 0.
def_loss = 0.
def_total_reward_by_episode = 0
att_total_reward_by_episode = 0
# Reset enviromet, actualize the data batch with random state/attacks
states = env.reset()
# Get actions for actual states following the policy
attack_actions = attacker_agent.act(states)
states = env.get_states(attack_actions)
done = False
attacks_list = []
# Iteration in one episode
for i_iteration in range(iterations_episode):
attacks_list.append(attack_actions[0])
# apply actions, get rewards and new state
act_time = time.time()
defender_actions = defender_agent.act(states)
#Enviroment actuation for this actions
next_states,def_reward, att_reward,next_attack_actions, done = env.act(defender_actions,attack_actions)
# If the epoch*batch_size*iterations_episode is largest than the df
attacker_agent.learn(states,attack_actions,next_states,att_reward,done)
defender_agent.learn(states,defender_actions,next_states,def_reward,done)
act_end_time = time.time()
# Train network, update loss after at least minibatch_learns
if ExpRep and epoch*iterations_episode + i_iteration >= minibatch_size:
def_loss += defender_agent.update_model()
att_loss += attacker_agent.update_model()
elif not ExpRep:
def_loss += defender_agent.update_model()
att_loss += attacker_agent.update_model()
update_end_time = time.time()
# Update the state
states = next_states
attack_actions = next_attack_actions
# Update statistics
def_total_reward_by_episode += np.sum(def_reward,dtype=np.int32)
att_total_reward_by_episode += np.sum(att_reward,dtype=np.int32)
attacks_by_epoch.append(attacks_list)
# Update user view
def_reward_chain.append(def_total_reward_by_episode)
att_reward_chain.append(att_total_reward_by_episode)
def_loss_chain.append(def_loss)
att_loss_chain.append(att_loss)
end_time = time.time()
print("\r\n|Epoch {:03d}/{:03d}| time: {:2.2f}|\r\n"
"|Def Loss {:4.4f} | Def Reward in ep {:03d}|\r\n"
"|Att Loss {:4.4f} | Att Reward in ep {:03d}|"
.format(epoch, num_episodes,(end_time-start_time),
def_loss, def_total_reward_by_episode,
att_loss, att_total_reward_by_episode))
print("|Def Estimated: {}| Att Labels: {}".format(env.def_estimated_labels,
env.def_true_labels))
attack_labels_list.append(env.def_true_labels)
and the error I am facing is
TypeError: argument of type 'method' is not iterable
Any help would be appreciated. Thanks in advance.

Python Pulp - Multiple ADP contraints for snake draft

I am new to python/pulp and I am trying to replicate an excel solver snake draft problem in python. I have found a couple of python optimizer solutions for dfs. My model is similar with the exception of instead of a single constraint for salary, I have multiple constraints based on ADP. For instance, if I am in a 10 team league with the 7th pick and I want to optimize my first 8 picks. My 1st ADP constraint would be 8 of my picks would have an ADP higher than 6. 2nd constraint would be at least 7 of my picks would have an ADP higher than 13. 3rd - at least 6 picks have an ADP higher than 26 and so forth for 8 rounds. The suggestion that was made was to make a binary helper column which I have done for each round. This approach seems cumbersome and is not useful if I want to create a loop for each draft position's optimal lineup. Is there a better way to write the code for the Rnd1 thru the Rnd8 sections of the code. Thanks
Fantasy Football Data
availables = players.groupby(["Position", "Rk", "PLAYER", "TEAM", "EPPG", "Rnd1", "Rnd2",
"Rnd3", "Rnd4", "Rnd5", "Rnd6", "Rnd7", "Rnd8"]).agg('count')
availables = availables.reset_index()
ADPs = {}
points = {}
R1s = {}
R2s = {}
R3s = {}
R4s = {}
R5s = {}
R6s = {}
R7s = {}
R8s = {}
lineups_dict = {}
for pos in availables.Position.unique():
available_pos = availables[availables.Position == pos]
point = list(available_pos[['PLAYER', 'EPPG']].set_index("PLAYER").to_dict().values())[0]
R1 = list(available_pos[['PLAYER', 'Rnd1']].set_index("PLAYER").to_dict().values())[0]
R2 = list(available_pos[['PLAYER', 'Rnd2']].set_index("PLAYER").to_dict().values())[0]
R3 = list(available_pos[['PLAYER', 'Rnd3']].set_index("PLAYER").to_dict().values())[0]
R4 = list(available_pos[['PLAYER', 'Rnd4']].set_index("PLAYER").to_dict().values())[0]
R5 = list(available_pos[['PLAYER', 'Rnd5']].set_index("PLAYER").to_dict().values())[0]
R6 = list(available_pos[['PLAYER', 'Rnd6']].set_index("PLAYER").to_dict().values())[0]
R7 = list(available_pos[['PLAYER', 'Rnd7']].set_index("PLAYER").to_dict().values())[0]
R8 = list(available_pos[['PLAYER', 'Rnd8']].set_index("PLAYER").to_dict().values())[0]
points[pos] = point
R1s[pos] = R1
R2s[pos] = R2
R3s[pos] = R3
R4s[pos] = R4
R5s[pos] = R5
R6s[pos] = R6
R7s[pos] = R7
R8s[pos] = R8
pos_num_available = {
"QB": 1,
"RB": 3,
"TE": 1,
"WR": 3,
"DEF": 0,
"K": 0
}
for lineup in range(1,9):
_vars = {k: LpVariable.dict(k, v, cat='Binary') for k, v in points.items()}
prob = LpProblem("Fantasy", LpMaximize)
rewards = []
Rnd_1 = []
Rnd_2 = []
Rnd_3 = []
Rnd_4 = []
Rnd_5 = []
Rnd_6 = []
Rnd_7 = []
Rnd_8 = []
for k, v in _vars.items():
rewards += lpSum([points[k][i] * _vars[k][i] for i in v])
Rnd_1 += lpSum([R1s[k][i] * _vars[k][i] for i in v])
Rnd_2 += lpSum([R2s[k][i] * _vars[k][i] for i in v])
Rnd_3 += lpSum([R3s[k][i] * _vars[k][i] for i in v])
Rnd_4 += lpSum([R4s[k][i] * _vars[k][i] for i in v])
Rnd_5 += lpSum([R5s[k][i] * _vars[k][i] for i in v])
Rnd_6 += lpSum([R6s[k][i] * _vars[k][i] for i in v])
Rnd_7 += lpSum([R7s[k][i] * _vars[k][i] for i in v])
Rnd_8 += lpSum([R8s[k][i] * _vars[k][i] for i in v])
prob += lpSum([_vars[k][i] for i in v]) == pos_num_available[k]
prob += lpSum(rewards)
prob += Rnd_1 >= 8
prob += Rnd_2 >= 7
prob += Rnd_3 >= 6
prob += Rnd_4 >= 5
prob += Rnd_5 >= 4
prob += Rnd_6 >= 3
prob += Rnd_7 >= 2
prob += Rnd_8 >= 1
if not lineup == 1:
prob += (lpSum(rewards) <= total_score-0.01)
prob.solve()
score= str(prob.objective)
constraints = [str(const) for const in prob.constraints.values()]
lineupList = []
for v in prob.variables():
score = score.replace(v.name, str(v.varValue))
if v.varValue !=0:
lineupList.append(v.name)
ADP constraint examples

QuantLib bond pricing with credit spread not working after setting values of key rate quote

I am using SpreadedLinearZeroInterpolatedTermStructure class to price bond. I have 35 key rates, from 1M to 30Y. I also have a daily spot curve. So I want to input 35 key rates extracted from the daily spot curve to the class, then change key rates to see what's the bond price.
Giving credit to GB, and his article here:
http://gouthamanbalaraman.com/blog/bonds-with-spreads-quantlib-python.html
I followed his method which worked well, the bond price is changing due to the different values set to key rates.
Then I substituted his flat curve with my daily spot curve, his handles list with my handles (35 handles in it), and his two dates with my 35 dates.
I set values to some of the key rates while the NPV stayed still(even I gave a huge shock). I also tried to give only two key rates on a zero curve, and it worked. So I guess it's because 35 key rates is way too much? Any help is appreciated
import QuantLib as ql
# =============================================================================
# normal yc term structure
# =============================================================================
todaysDate = ql.Date(24,5,2019)
ql.Settings.instance().evaluationDate = todaysDate
KR1 = [0, 1, 3, 6, 9] # KR in month unit
KR2 = [x for x in range(1,31)] # KR in year unit
spotDates = [] # starting from today
for kr in KR1:
p = ql.Period(kr,ql.Months)
spotDates.append(todaysDate+p)
for kr in KR2:
p = ql.Period(kr,ql.Years)
spotDates.append(todaysDate+p)
spotRates = [0.02026,
0.021569,
0.02326,
0.025008,
0.026089,
0.026679,
0.028753,
0.029376,
0.030246,
0.031362,
0.033026,
0.034274,
0.033953,
0.033474,
0.033469,
0.033927,
0.03471,
0.035596,
0.036396,
0.036994,
0.037368,
0.037567,
0.037686,
0.037814,
0.037997,
0.038247,
0.038562,
0.038933,
0.039355,
0.039817,
0.040312,
0.040832,
0.041369,
0.041922,
0.042487] # matching points
dayCount = ql.Thirty360()
calendar = ql.China()
interpolation = ql.Linear()
compounding = ql.Compounded
compoundingFrequency = ql.Annual
spotCurve = ql.ZeroCurve(spotDates, spotRates, dayCount, calendar,
interpolation,compounding, compoundingFrequency)
spotCurveHandle = ql.YieldTermStructureHandle(spotCurve)
# =============================================================================
# bond settings
# =============================================================================
issue_date = ql.Date(24,5,2018)
maturity_date = ql.Date(24,5,2023)
tenor = ql.Period(ql.Semiannual)
calendar = ql.China()
business_convention = ql.Unadjusted
date_generation = ql.DateGeneration.Backward
month_end = False
schedule = ql.Schedule(issue_date,maturity_date,tenor,calendar,
business_convention, business_convention,
date_generation,month_end)
settlement_days = 0
day_count = ql.Thirty360()
coupon_rate = 0.03
coupons = [coupon_rate]
face_value = 100
fixed_rate_bond = ql.FixedRateBond(settlement_days,
face_value,
schedule,
coupons,
day_count)
#bond_engine = ql.DiscountingBondEngine(spotCurveHandle)
#fixed_rate_bond.setPricingEngine(bond_engine)
#print(fixed_rate_bond.NPV())
# =============================================================================
# non-parallel shift of yc
# =============================================================================
#def KRshocks(kr0=0.0, kr_1M=0.0, kr_3M=0.0, kr_6M=0.0, kr_9M=0.0,
# kr_1Y=0.0,kr_2Y=0.0, kr_3Y=0.0, kr_4Y=0.0, kr_5Y=0.0, kr_6Y=0.0,
# kr_7Y=0.0, kr_8Y=0.0, kr_9Y=0.0, kr_10Y=0.0, kr_11Y=0.0, kr_12Y=0.0,
# kr_13Y=0.0, kr_14Y=0.0, kr_15Y=0.0, kr_16Y=0.0, kr_17Y=0.0, kr_18Y=0.0,
# kr_19Y=0.0, kr_20Y=0.0, kr_21Y=0.0, kr_22Y=0.0, kr_23Y=0.0, kr_24Y=0.0,
# kr_25Y=0.0, kr_26Y=0.0, kr_27Y=0.0, kr_28Y=0.0, kr_29Y=0.0, kr_30Y=0.0):
# '''
#
# Parameters:
# Input shocks for each key rate.
# kr0 = today's spot rate shock;
# kr_1M = 0.083 year(1 month) later spot rate shock;
# kr_1Y = 1 year later spot rate shock;
# .
# .
# .
#
# '''
#
# krs = list(locals().keys())
# KRHandles = {}
# for k in krs:
# KRHandles['{}handle'.format(k)] = ql.QuoteHandle(ql.SimpleQuote(locals()[k]))
# return list(KRHandles.values())
#handles = KRshocks()
kr = ['kr0', 'kr_1M', 'kr_3M', 'kr_6M', 'kr_9M', 'kr_1Y','kr_2Y', 'kr_3Y',
'kr_4Y', 'kr_5Y', 'kr_6Y','kr_7Y', 'kr_8Y', 'kr_9Y', 'kr_10Y', 'kr_11Y',
'kr_12Y', 'kr_13Y', 'kr_14Y', 'kr_15Y', 'kr_16Y', 'kr_17Y', 'kr_18Y',
'kr_19Y', 'kr_20Y', 'kr_21Y', 'kr_22Y', 'kr_23Y', 'kr_24Y','kr_25Y',
'kr_26Y', 'kr_27Y', 'kr_28Y', 'kr_29Y', 'kr_30Y']
#KRQuotes = {}
handles = []
#for k in range(len(kr)):
# KRQuotes['{}'.format(kr[k])] = ql.SimpleQuote(spotRates[k])
# handles.append(ql.QuoteHandle(ql.SimpleQuote(spotRates[k])))
kr0 = ql.SimpleQuote(spotRates[0])
kr_1M = ql.SimpleQuote(spotRates[1])
kr_3M = ql.SimpleQuote(spotRates[2])
kr_6M = ql.SimpleQuote(spotRates[3])
kr_9M = ql.SimpleQuote(spotRates[4])
kr_1Y = ql.SimpleQuote(spotRates[5])
kr_2Y = ql.SimpleQuote(spotRates[6])
kr_3Y = ql.SimpleQuote(spotRates[7])
kr_4Y = ql.SimpleQuote(spotRates[8])
kr_5Y = ql.SimpleQuote(spotRates[9])
kr_6Y = ql.SimpleQuote(spotRates[10])
kr_7Y = ql.SimpleQuote(spotRates[11])
kr_8Y = ql.SimpleQuote(spotRates[12])
kr_9Y = ql.SimpleQuote(spotRates[13])
kr_10Y = ql.SimpleQuote(spotRates[14])
kr_11Y = ql.SimpleQuote(spotRates[15])
kr_12Y = ql.SimpleQuote(spotRates[16])
kr_13Y = ql.SimpleQuote(spotRates[17])
kr_14Y = ql.SimpleQuote(spotRates[18])
kr_15Y = ql.SimpleQuote(spotRates[19])
kr_16Y = ql.SimpleQuote(spotRates[20])
kr_17Y = ql.SimpleQuote(spotRates[21])
kr_18Y = ql.SimpleQuote(spotRates[22])
kr_19Y = ql.SimpleQuote(spotRates[23])
kr_20Y = ql.SimpleQuote(spotRates[24])
kr_21Y = ql.SimpleQuote(spotRates[25])
kr_22Y = ql.SimpleQuote(spotRates[26])
kr_23Y = ql.SimpleQuote(spotRates[27])
kr_24Y = ql.SimpleQuote(spotRates[28])
kr_25Y = ql.SimpleQuote(spotRates[29])
kr_26Y = ql.SimpleQuote(spotRates[30])
kr_27Y = ql.SimpleQuote(spotRates[31])
kr_28Y = ql.SimpleQuote(spotRates[32])
kr_29Y = ql.SimpleQuote(spotRates[33])
kr_30Y = ql.SimpleQuote(spotRates[34])
handles.append(ql.QuoteHandle(kr0))
handles.append(ql.QuoteHandle(kr_1M))
handles.append(ql.QuoteHandle(kr_3M))
handles.append(ql.QuoteHandle(kr_6M))
handles.append(ql.QuoteHandle(kr_9M))
handles.append(ql.QuoteHandle(kr_1Y))
handles.append(ql.QuoteHandle(kr_2Y))
handles.append(ql.QuoteHandle(kr_3Y))
handles.append(ql.QuoteHandle(kr_4Y))
handles.append(ql.QuoteHandle(kr_5Y))
handles.append(ql.QuoteHandle(kr_6Y))
handles.append(ql.QuoteHandle(kr_7Y))
handles.append(ql.QuoteHandle(kr_8Y))
handles.append(ql.QuoteHandle(kr_9Y))
handles.append(ql.QuoteHandle(kr_10Y))
handles.append(ql.QuoteHandle(kr_11Y))
handles.append(ql.QuoteHandle(kr_12Y))
handles.append(ql.QuoteHandle(kr_13Y))
handles.append(ql.QuoteHandle(kr_14Y))
handles.append(ql.QuoteHandle(kr_15Y))
handles.append(ql.QuoteHandle(kr_16Y))
handles.append(ql.QuoteHandle(kr_17Y))
handles.append(ql.QuoteHandle(kr_18Y))
handles.append(ql.QuoteHandle(kr_19Y))
handles.append(ql.QuoteHandle(kr_20Y))
handles.append(ql.QuoteHandle(kr_21Y))
handles.append(ql.QuoteHandle(kr_22Y))
handles.append(ql.QuoteHandle(kr_23Y))
handles.append(ql.QuoteHandle(kr_24Y))
handles.append(ql.QuoteHandle(kr_25Y))
handles.append(ql.QuoteHandle(kr_26Y))
handles.append(ql.QuoteHandle(kr_27Y))
handles.append(ql.QuoteHandle(kr_28Y))
handles.append(ql.QuoteHandle(kr_29Y))
handles.append(ql.QuoteHandle(kr_30Y))
ts_spreaded2 = ql.SpreadedLinearZeroInterpolatedTermStructure(spotCurveHandle,
handles,
spotDates)
ts_spreaded_handle2 = ql.YieldTermStructureHandle(ts_spreaded2)
bond_engine = ql.DiscountingBondEngine(ts_spreaded_handle2)
fixed_rate_bond.setPricingEngine(bond_engine)
#print(fixed_rate_bond.NPV())
kr0.setValue(0.1)
kr_10Y.setValue(0.2)
kr_12Y.setValue(0.2)
print(fixed_rate_bond.NPV())
no errors came out but the bond price is the same as the price before spreads added

ID3 Algorithm in Python

I am trying to plot a decision tree using ID3 in Python. I am really new to Python and couldn't understand the implementation of the following code. I need to know how I can apply this code to my data.
from math import log
import operator
def entropy(data):
entries = len(data)
labels = {}
for feat in data:
label = feat[-1]
if label not in labels.keys():
labels[label] = 0
labels[label] += 1
entropy = 0.0
for key in labels:
probability = float(labels[key])/entries
entropy -= probability * log(probability,2)
return entropy
def split(data, axis, val):
newData = []
for feat in data:
if feat[axis] == val:
reducedFeat = feat[:axis]
reducedFeat.extend(feat[axis+1:])
newData.append(reducedFeat)
return newData
def choose(data):
features = len(data[0]) - 1
baseEntropy = entropy(data)
bestInfoGain = 0.0;
bestFeat = -1
for i in range(features):
featList = [ex[i] for ex in data]
uniqueVals = set(featList)
newEntropy = 0.0
for value in uniqueVals:
newData = split(data, i, value)
probability = len(newData)/float(len(data))
newEntropy += probability * entropy(newData)
infoGain = baseEntropy - newEntropy
if (infoGain > bestInfoGain):
bestInfoGain = infoGain
bestFeat = i
return bestFeat
def majority(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys(): classCount[vote] = 0
classCount[vote] += 1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def tree(data,labels):
classList = [ex[-1] for ex in data]
if classList.count(classList[0]) == len(classList):
return classList[0]
if len(data[0]) == 1:
return majority(classList)
bestFeat = choose(data)
bestFeatLabel = labels[bestFeat]
theTree = {bestFeatLabel:{}}
del(labels[bestFeat])
featValues = [ex[bestFeat] for ex in data]
uniqueVals = set(featValues)
for value in uniqueVals:
subLabels = labels[:]
theTree[bestFeatLabel][value] = tree(split/(data, bestFeat, value),subLabels)
return theTree
So what I did after this is the following:
infile=open("SData.csv","r")
data=infile.read()
tree(data)
The error which I got is "1 argument is missing" which is the label which I have to define and this is where I don't know what I have to put. I tried the variable for which I have to make the decision tree but it doesn't work:
tree(data,MinTemp)
Here I get an error "MinTemp is not defined".
Please help me out and let me know what I should do to have a look at the tree.
Following is the part of data and I want to generate a tree for MinTemp
MinTemp,Rainfall,Tempat9,RHat9,CAat9,WSat9
high,no,mild,normal,overcast,weak
high,no,mild,normal,cloudy,weak
high,no,mild,normal,cloudy,mild
high,yes,mild,high,cloudy,weak
high,yes,mild,high,cloudy,mild
medium,yes,mild,high,cloudy,mild
high,no,mild,high,overcast,weak
high,no,mild,normal,sunny,weak
high,no,hot,normal,sunny,weak
high,no,hot,normal,overcast,weak

Categories