I am trying to find the optimal dispatch for a battery across different markets for buying and selling energy. I ran into the problem, that the battery is simultansouly charging and discharging in the same market. How does my constraint look like to avoid simultaneous charging and discharging?
Here is my example:
def battery_optimisation(data: pd.DataFrame, technical_parameters=None, include_revenue=True, solver: str='glpk'):
# Battery's technical specification
MIN_BATTERY_CAPACITY = 0
MAX_BATTERY_CAPACITY = 100
MAX_RAW_POWER = 40
INITIAL_CAPACITY = 0
EFFICIENCY = 1
battery = ConcreteModel()
solvername='glpk'
solverpath_folder='C:\\glpk-4.65\\w64'
solverpath_exe='C:\\glpk-4.65\\w64\\glpsol'
opt = SolverFactory(solver,executable=solverpath_exe)
battery.Period = Set(initialize=list(data.period), ordered=True)
battery.Price = Param(initialize=list(data.spot_hourly), within=Any)
battery.intraday = Param(initialize=list(data.id_hourly), within=Any)
battery.fcr_hourly = Param(initialize=list(data.fcr_hourly), within=Any)
battery.afrr_up = Param(initialize=list(data.afrr_up_energy_hourly), within=Any)
battery.afrr_down = Param(initialize=list(data.afrr_down_energy_hourly), within=Any)
# battery variables
battery.Capacity = Var(battery.Period, bounds=(MIN_BATTERY_CAPACITY, MAX_BATTERY_CAPACITY))
battery.Charge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.Discharge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.charge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.discharge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
battery.power_balance =Var(battery.Period, doc='binary variable', within=Binary, initialize=0)
battery.power_p = Var(battery.Period, doc='energy derivative with respect to time', initialize=0)
# Set constraints for the battery
# Defining the battery objective (function to be maximise)
def maximise_profit(battery):
rev = sum(data.id_hourly[i] * (battery.discharge_power_intra[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.fcr_hourly[i] * (battery.discharge_power_fcr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.afrr_up_energy_hourly[i] * (battery.discharge_power_afrr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
sum(data.spot_hourly[i] * (battery.discharge_power_dah[i] / 2 * EFFICIENCY) for i in battery.Period)
cost = sum(data.id_hourly[i] * (battery.charge_power_intra[i] / 2) for i in battery.Period) + \
sum(data.fcr_hourly[i] * (battery.charge_power_fcr[i] / 2) for i in battery.Period) + \
sum(data.afrr_down_energy_hourly[i] * (battery.charge_power_afrr[i] / 2) for i in battery.Period) + \
sum(data.spot_hourly[i] * (battery.charge_power_dah[i] / 2) for i in battery.Period)
return rev - cost
# CONSTRAINT - BATTERY CAN'T CHARGE OVER CAPACITY
def over_charge(battery, i):
battery_charge = battery.charge_power_intra[i] + \
battery.charge_power_fcr[i] + \
battery.charge_power_afrr[i] + \
battery.charge_power_dah[i]
return battery_charge <= (MAX_BATTERY_CAPACITY - battery.Capacity[i]) * 2 / EFFICIENCY
# CONSTRAINT - CAN DISCHARGE MORE THAN CAPITY
def over_discharge(battery, i):
battery_charge = battery.discharge_power_intra[i] + \
battery.discharge_power_fcr[i] + \
battery.discharge_power_afrr[i] + \
battery.discharge_power_dah[i]
return battery_charge <= battery.Capacity[i] * 2
# CONSTRAINT - BATTERY CAN'T DISCHARGE IF PRICES ARE NEGATIVE
def negative_discharge_spot(battery, i):
# if the spot price is not positive, suppress discharge
if battery.Price.extract_values_sparse()[None][i] <= 0:
return battery.Discharge_power[i] == 0
# otherwise skip the current constraint
return Constraint.Skip
# CONSTRAINT - CAPACITY RULE
def capacity_constraint(battery, i):
# Assigning battery's starting capacity at the beginning
if i == battery.Period.first():
return battery.Capacity[i] == INITIAL_CAPACITY
# if not update the capacity normally
battery_capacity = (battery.Capacity[i-1] \
+ ((battery.charge_power_intra[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_fcr[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_afrr[i-1] / 2 * EFFICIENCY) \
+ (battery.charge_power_dah[i-1] / 2 * EFFICIENCY)) \
- ((battery.discharge_power_intra[i-1] / 2) \
+ (battery.discharge_power_fcr[i-1] / 2) \
+ (battery.discharge_power_afrr[i-1] / 2) \
+ (battery.discharge_power_dah[i-1] / 2)))
return battery.Capacity[i] == battery_capacity
# def _p_balance(battery, i):
# return battery.discharge_power_fcr[i] <= 0 | battery.charge_power_fcr[i] <= 0
# Set constraint and objective for the battery
battery.capacity_constraint = Constraint(battery.Period, rule=capacity_constraint)
battery.over_charge = Constraint(battery.Period, rule=over_charge)
battery.over_discharge = Constraint(battery.Period, rule=over_discharge)
battery.negative_discharge = Constraint(battery.Period, rule=negative_discharge_spot)
battery.objective = Objective(rule=maximise_profit, sense=maximize)
# battery._p_balance = Constraint(battery.Period, rule=_p_balance)
# Maximise the objective
opt.solve(battery, tee=False)
If you look at the results, you can see that in the 'FCR' market it is simultanously charging and discharging.
I have tried:
Naive approach. Supply an OR-condition:
def _p_balance(battery, i):
return battery.discharge_power_fcr[i] == 0 | battery.charge_power_fcr[i] == 0
Multiplying:
def _p_balance(battery, i):
return battery.discharge_power_fcr[i] * battery.charge_power_fcr[i] == 0
-> This make the problem non-linear, which is not supported by GLPK.
This isn't a full answer, but too long for a comment.
You don't really have a model for "the battery" here. You have a market model for 4 energy markets, I think.
You don't have much in explanatory comments in your code, but I think you have 4 markets: IntraDay, Day Ahead, FCR, AFRR that each have a price and cost associated with them. So you are effectively modeling a distribution system, and it would be totally legit if there was some price disparity to produce the output you show. If FCR cost is low, and price is high (in the FCR market and others), you could buy a massive quantity and sell it in the same market or the others, which appears to be happening.
So, if we look at your objective function, esp. the FCR part in isolation, it appears you are using the same cost value as a multiplier for both cost & rev. The only difference is EFFICIENCY. ...And your EFFICIENCY is set to 1, so the cost is neutral for whatever you do in FCR market, so the solution the solver provides may have both charge and discharge... the OBJ value will be neutral to this. So, try changing your efficiency to something slightly < 1 and I think you will see (partial) improvement.
also a nits: You have Capacity[i] as a variable. Typically "capacity" is a fixed value, like 10MJ. I'd rename it "charge" or "state"
You shouldn't have to constrain discharge when price is negative... the OBJ should handle that for you and I think the change in efficiency will negate that constraint.
Related
I am trying to build a simple form which calculates which machine would run a film width the quickest, the parameters and capabilities of each machine are held in a django model.
The width of the film and how much of it will be entered in the form and the quantity needed. The function should work out which machine(s) can run it, what the max speed is and the average speed over the machines that are capable.
I want to return the values of the calculation and maybe run a for loop and display the values for each machine in a results.html template in a table. I also want to display average times across machines capable of running the widths of film.
I had some success with lists but would like to use a class that I can use in the template and do away with the lists.
Any help with this would be much appreciated as I am getting pretty lost in it!
I have only started on the 'Layflat Tubing' function in the hope that I can get it right and just copy down to the other functions.
from django.views.generic.base import TemplateView
from django.shortcuts import render
import math, datetime
from settings.models import Extruder
class Result:
def __init__(self, ext_no, width, speed=0, ):
self.ext_no = ext_no
self.width = width
self.speed = speed
def __str__(self):
return self.ext_no
extruders = Extruder.objects.all()
class FilmSpeedView(TemplateView):
template_name = 'calculations/film-speed.html'
class BagWeightView(TemplateView):
template_name = 'calculations/bag-weight.html'
class CalculatorsView(TemplateView):
template_name = 'calculations/calculators.html'
def result(request):
film_type=''
film_width=''
measure=''
speeds = [0]
quantity = 0
max_speed = 0
ave_speed = 0
ave_time = 0
max_time = 0
a=[]
b=[]
c=[]
d=[]
e=[]
if request.method=="GET":
film_type = str(request.GET["film_type"])
film_width = int(request.GET["film_width"])
edge_trim = int(request.GET["edge_trim"])
quantity =int(request.GET["quantity"])
measure = str(request.GET["measure"])
if measure == "metric":
film_width = int(film_width)
else:
film_width = film_width * 25.4
if edge_trim is None:
edge_trim = 0
else:
edge_trim = int(edge_trim)
if str(film_type) == 'Layflat Tubing':
film_type = "LFT"
for extruder in extruders:
bur = film_width / extruder.die_size
if film_width < extruder.min_width:
b.append(extruder.name + ' : Film too narrow')
extruder = Result(ext_no = extruder.ext_no, width = 'too narrow')
elif film_width > extruder.max_width:
b.append(extruder.name + ' : Film too wide')
extruder = Result(ext_no = extruder.ext_no, width = 'too wide')
else:
percentage = film_width / extruder.max_width
speed = extruder.max_kgs_hr * percentage
extruder = Result(ext_no = extruder.ext_no, speed = round(extruder.max_kgs_hr * percentage, 2), width = 'ok')
speeds.append(speed)
max_speed = max(speeds)
ave_speed = sum(speeds) / len(speeds)
ave_time = float(quantity) / ave_speed * 60.0
max_time = float(quantity) / max_speed * 60.0
else:
film_type = "Invalid Film Type"
m = a
n = b
o = c
g = str(round(ave_speed, 2)) + 'kg\'s/h'
h = str(datetime.timedelta(minutes=ave_time))
i = str(datetime.timedelta(minutes=30))
j = str(round(max_speed, 2)) + 'kg\'s/h'
k = str(datetime.timedelta(minutes=max_time))
return render(request, 'calculations/result.html', {'a':a, 'b':b, 'c':c, 'd':d, 'e':e, 'g':g, 'h':h, 'i':i, 'j':j, 'k':k, 'm':m, 'n':n, 'o':o, 'bur':bur,})
I want to use boost.python to use multi-index columns dataframe in c++.
※multi-index columns dataframe is like
I changed the type of multi-index columns dataframe into csv.
My csv file looks like this on spreadsheet
The reason why I want to use this data is for backtest. This is my backtest code in python that I want to translate to c++.
import pandas as pd
import numpy as np
from utils import load_data, load_list_csv, to_int
class No_Strategy():
def __init__(self, codes, unit, cash, position):
self.codes = codes
self.unit = unit
self.cash = cash
self.buy_signal = [0]*len(codes)
self.sell_signal = [0]*len(codes)
self.valid = 0
self.position = position
self.pass_st = 0 # 전략에 들어가지도 못한 경우
def set_data(self, prev_fs_row, fs_row, indi_row):
self.prev_fs = prev_fs_row
self.fs = fs_row # multi dimensional df
self.indi = indi_row
def _strat(self, prev_fs, curr_fs, curr_indi):
curr_rev = prev_rev = curr_ni = prev_ni = ni_growth = curr_asset = noncurr_asset = curr_asset_rat = 0
try:
prev_rev = int(prev_fs['매출액'].replace(",",""))
curr_rev = int(curr_fs['매출액'].replace(",",""))
except:
self.pass_st += 1
return 0, 0
rev_growth=(curr_rev-prev_rev)/prev_rev
try:
prev_ni = int(prev_fs['당기순이익'].replace(",",""))
curr_ni = int(curr_fs['당기순이익'].replace(",",""))
except:
self.pass_st += 1
return 0, 0
ni_growth=(curr_ni-prev_ni)/prev_ni
try:
curr_asset = int(curr_fs['유동자산'].replace(",",""))
noncurr_asset = int(curr_fs['비유동자산'].replace(",",""))
except:
self.pass_st += 1
return 0, 0
curr_asset_rat = curr_asset / noncurr_asset
#### this is the buy strategy! You can change the below ####
if (curr_indi.golden_cross) or (curr_indi.rsi_k < 0.65) :
return 1, 0
#### ************************************************** ####
#### this is the sell strategy! You can change the below ####
if (curr_indi.dead_cross):
return 0, 1
#### ************************************************** ####
return 0, 0
def run(self):
for i, code in enumerate(self.codes):
self.valid = 0
prev_fs = self.prev_fs[code]
curr_fs = self.fs[code]
curr_indi = self.indi[code]
prev_fs_cell = None
curr_fs_cell = None
try:
prev_fs_cell = prev_fs.iloc[0].replace(",","")
try:
curr_fs_cell = curr_fs.iloc[0].replace(",","")
except:
self.pass_st += 1
pass
except:
self.pass_st += 1
pass
if (curr_fs_cell != None) & (prev_fs_cell != None):
self.valid = 1
buy, sell = self._strat(prev_fs, curr_fs, curr_indi)
if self.valid == 0:
self.pass_st += 1
continue
else: # buy or sell signal get
price = curr_indi['close']
if buy:
if self.cash >= self.unit * price:
self.buy_signal[i] = self.unit
self.position[i] += self.unit
self.cash -= price * self.unit
elif sell:
if self.position[i] > 0 :
sell_num = self.position[i] - int(self.position[i]/2)
self.sell_signal[i] = sell_num
self.position[i] = int(self.position[i]/2) # 1-> 1 sell, 4 -> 2 sell ....
self.cash += price * sell_num
##title
class Broker():
def __init__(self, codes):
self.cash = 200000000 #2억
self.cash_df = None #pd.DataFrame(columns=['cash'])
self.position = [0]*len(codes)
self.position_df = None #pd.DataFrame(columns=codes) # for accumulated profit calculation
self.buy_signal = None #pd.DataFrame(columns=codes) # codes = KOSPI_stock_names
self.sell_signal = None #pd.DataFrame(columns=codes)
self.codes = codes # 012934, 3281, ...
self.unit = 1 # 주식 매매 단위
self.pass_st = 0
def set_strat(self, strategy):
self.strategy = strategy # class
def set_time(self, time_index): # time_index type: pd.Index / time range for indi df
self.buy_signal = pd.DataFrame(columns = self.codes, index = time_index) #set_index(time_index)
self.sell_signal = pd.DataFrame(columns = self.codes, index = time_index) #.set_index(time_index)
self.position_df = pd.DataFrame(columns = self.codes, index = time_index)
self.cash_df = pd.DataFrame(columns = ['cash'], index = time_index)#.set_index(time_index)
self.time_index = time_index
def set_data(self, fs, indi, price):
self.fs = fs # multi dimensional df / start: 0th - nth
self.indi = indi # multi dimensional df / start : 1th - nth
self.price = price # 2 dimensional (date X codes : close price)
def update_data(self, strategy, date):
self.cash = strategy.cash
self.cash_df.loc[date] = strategy.cash
self.position = strategy.position
self.position_df.loc[date] = strategy.position #list
self.buy_signal.loc[date] = strategy.buy_signal #list
self.sell_signal.loc[date] = strategy.sell_signal #list
self.pass_st += strategy.pass_st
def run(self):
for date in self.time_index: #아마 수정해야 할 확률 높음
if date.year == 2021:
break
else:
prev_fs_row = self.fs.loc[date.year-1] # ex: 2014
fs_row = self.fs.loc[date.year] # 2015
indi_row = self.indi.loc[date] # 2015
strategy = self.strategy(self.codes, self.unit, self.cash, self.position)
strategy.set_data(prev_fs_row, fs_row, indi_row)
strategy.run()
self.update_data(strategy, date)
def performance(self):
# !!!! 2020년까지의 결과만 성능 평가 ####
cash_df = self.cash_df[self.cash_df.index < '2021']
position_df = self.position_df[self.position_df.index < '2021']
price = self.price[self.price.index < '2021']
buy_signal = self.buy_signal[self.buy_signal.index < '2021']
sell_signal = self.sell_signal[self.sell_signal.index < '2021']
last_price = price.iloc[-1]
total_remain_num = self.position # last(2020) position data
total_buy = (price * buy_signal).sum(axis=1).sum()
total_sell = (price * sell_signal).sum(axis=1).sum()
total_remain = (last_price * total_remain_num).sum()
print(f'remain 개수: {total_remain_num}, total_remain: {total_remain} total_buy: {total_buy}, total_sell={total_sell}')
profit = total_sell + total_remain - total_buy
try:
return_mean = profit / total_buy
except:
print("no buy")
return
accum_df = (cash_df['cash'] + ((price.fillna(0) * position_df).sum(axis=1))).to_frame() # row sum
daily_return_df = (accum_df - accum_df.shift(1))/accum_df.shift(1)-1
SSE = ((daily_return_df - return_mean)**2).sum().item()
std = np.sqrt(SSE/(accum_df.shape[0]-1)) # route(sigma(x-x_bar)^2 / (n-1))
sharp = return_mean / std
self.return_mean = return_mean
self.sharp = sharp
print(f'return_mean: {return_mean}, sharp: {sharp}')
code_path = GDRIVE_DATA_PATH + 'codes.csv'
fs_path = GDRIVE_DATA_PATH + 'fs_total.csv'
indi_path = GDRIVE_DATA_PATH + 'indi_total.csv'
price_path = GDRIVE_DATA_PATH + 'prices.csv'
fs_total = load_data("fs_total.csv")
indi_total = load_data("indi_total.csv") # stock price and indicator(Golden cross, RSI, etc.)
prices = load_data("prices.csv") # stock close price data rows:date, cols: stock code.
time_index = indi_total.index # time index of indi_total multi-index columns
broker = Broker(codes)
broker.set_strat(No_Strategy)
broker.set_time(time_index)
broker.set_data(fs_total, indi_total, prices)
broker.run()
broker.performance()
I want to translate it not changing much in flow of the code.
But I cannot find how to get multi-index columns dataframe in c++, and transfer its row data to No_Strategy to decide whether invest into the stock.
※ I uploaded similar question before and get thankful answer, but it is too complicated for me so I question one more time with detail information.
look at https://github.com/hosseinmoein/DataFrame. It has about 95% of Pandas functionality in a much faster framework
I'm trying to implement Gaussian Mixture Model with Expectation–Maximization algorithm and I get this error.
This is the Gaussian Mixture model that I used:
class GaussianMixture:
"Model mixture of two univariate Gaussians and their EM estimation"
def __init__(self, data, mu_min=min(data), mu_max=max(data), sigma_min=.1, sigma_max=1, mix=.5):
self.data = data
#init with multiple gaussians
self.one = Gaussian(uniform(mu_min, mu_max),
uniform(sigma_min, sigma_max))
self.two = Gaussian(uniform(mu_min, mu_max),
uniform(sigma_min, sigma_max))
#as well as how much to mix them
self.mix = mix
def Estep(self):
"Perform an E(stimation)-step, freshening up self.loglike in the process"
# compute weights
self.loglike = 0. # = log(p = 1)
for datum in self.data:
# unnormalized weights
wp1 = self.one.pdf(datum) * self.mix
wp2 = self.two.pdf(datum) * (1. - self.mix)
# compute denominator
den = wp1 + wp2
# normalize
wp1 /= den
wp2 /= den
# add into loglike
self.loglike += log(wp1 + wp2)
# yield weight tuple
yield (wp1, wp2)
def Mstep(self, weights):
"Perform an M(aximization)-step"
# compute denominators
(left, rigt) = zip(*weights)
one_den = sum(left)
two_den = sum(rigt)
# compute new means
self.one.mu = sum(w * d / one_den for (w, d) in zip(left, data))
self.two.mu = sum(w * d / two_den for (w, d) in zip(rigt, data))
# compute new sigmas
self.one.sigma = sqrt(sum(w * ((d - self.one.mu) ** 2)
for (w, d) in zip(left, data)) / one_den)
self.two.sigma = sqrt(sum(w * ((d - self.two.mu) ** 2)
for (w, d) in zip(rigt, data)) / two_den)
# compute new mix
self.mix = one_den / len(data)
def iterate(self, N=1, verbose=False):
"Perform N iterations, then compute log-likelihood"
def pdf(self, x):
return (self.mix)*self.one.pdf(x) + (1-self.mix)*self.two.pdf(x)
def __repr__(self):
return 'GaussianMixture({0}, {1}, mix={2.03})'.format(self.one,
self.two,
self.mix)
def __str__(self):
return 'Mixture: {0}, {1}, mix={2:.03})'.format(self.one,
self.two,
self.mix)
And then , while training I get that error in the conditional statement.
# Check out the fitting process
n_iterations = 5
best_mix = None
best_loglike = float('-inf')
mix = GaussianMixture(data)
for _ in range(n_iterations):
try:
#train!
mix.iterate(verbose=True)
if mix.loglike > best_loglike:
best_loglike = mix.loglike
best_mix = mix
except (ZeroDivisionError, ValueError, RuntimeWarning): # Catch division errors from bad starts, and just throw them out...
pass
Any ideas why I have the following error?
AttributeError: GaussianMixture instance has no attribute 'loglike'
The loglike attribute is only created when you call the Estep method.
def Estep(self):
"Perform an E(stimation)-step, freshening up self.loglike in the process"
# compute weights
self.loglike = 0. # = log(p = 1)
You didn't call Estep between creating the GaussianMixture instance and mix.loglike:
mix = GaussianMixture(data)
for _ in range(n_iterations):
try:
#train!
mix.iterate(verbose=True)
if mix.loglike > best_loglike:
And the iterate method is empty (It looks like you forgot some code here).
def iterate(self, N=1, verbose=False):
"Perform N iterations, then compute log-likelihood"
So, there'll be no loglike attribute set on the mix instance by the time you do if mix.loglike. Hence, the AttributeError.
You need to do one of the following:
Call the Estep method (since you set self.loglike there)
Define a loglike attribute in __init__
I am coding an optimization problem. The model is giving infeasible solution. I want to check which constraint is giving infeasible solution. So far, I have checked online, but have not been able to come up with the solution to the problem. Can anyone help me? For example:in the code below, because of constraint 3 model is infeasible. How do I determine it from the solution? Thanks
from gurobipy import *
# Create a new model
m = Model("mip1")
# Create variables
x1 = m.addVar(vtype=GRB.INTEGER, name="x1")
x2 = m.addVar(vtype=GRB.INTEGER, name="x2")
# Integrate new variables
m.update()
# Set objective
m.setObjective(7*x1 + 2*x2, GRB.MAXIMIZE)
m.addConstr(-x1 + 2 * x2 <= 4, "constraint-0")
m.addConstr(5*x1 + x2 <= 20, "constraint-1")
m.addConstr(-2*x1 -2*x2 <= -7, "constraint-2")
m.addConstr(x1 <= -2, "constraint-3")
m.addConstr(x2 <= 4, "constraint-4")
m.optimize()
for v in m.getVars():
print('%s %g' % (v.varName, v.x))
print('Obj: %g' % m.objVal)
an exemple :
from gurobipy import *
# Create a new model
m = Model("mip1")
# Create variables
x1= m.addVar(lb=0,ub=62,vtype=GRB.INTEGER,name="x1")
x2 = m.addVar(lb=0,ub=50, vtype=GRB.INTEGER,name="x2")
m.update()
m.addConstr(-x1 + 2*x2 <= 4, "constraint-0")
m.addConstr(5*x1 + x2 <= 20, "constraint-1")
m.addConstr(-2*x1 -2*x2 <= -25, "constraint-2")
m.addConstr(x1 <= 2, "constraint-3")
#m.addConstr(x2 <= 50, "constraint-4")
m.update()
# Set objective
m.setObjective(7*x1 + 2*x2, GRB.MAXIMIZE)
m.update()
m.optimize()
status = m.status
if status == GRB.Status.OPTIMAL:
for v in m.getVars():
print('%s %g' % (v.varName, v.x))
print('Obj: %g' % m.objVal)
elif status == GRB.Status.INFEASIBLE:
print('Optimization was stopped with status %d' % status)
# do IIS
m.computeIIS()
for c in m.getConstrs():
if c.IISConstr:
print('%s' % c.constrName)
I have a script as follows:
import numpy as np
import pandas as pd
import pdb
# conventions: W = fitness, A = affinity ; sex: 1=M, 0=F; alien: 1=alien,
# 0=native
# pop array order: W, A, sex, alien
def mkpop(n):
W = np.repeat(a=1, repeats=n)
A = np.random.normal(1, 0.1, size=n)
A[A < 0] = 0
alien = np.repeat(a=False, repeats=n)
sex = np.random.randint(0, 2, n)
pop = np.array([W, A, sex, alien])
pop = np.transpose(pop)
return pop
def migrate(pop, n=10, gParams=[1, 0.1]):
W = np.random.gamma(shape=gParams[0], scale=gParams[1], size=n)
A = np.repeat(1, n)
# 0 is native; 1 is alien
alien = np.repeat(True, n)
# 0 is female
sex = np.random.randint(0, 2, n)
popAlien = np.array([W, A, sex, alien])
popAlien = np.transpose(popAlien)
pop = np.vstack((pop, popAlien))
return pop
def mate(pop):
# split into male and female
f = pop[pop[:, 2] == 0]
m = pop[pop[:, 2] == 1]
# create transition matricies for native and alien mates
# m with native = m.!alien.transpose * f.alien
# negate alien
naLog = list(np.asarray(m[:, 3]) == False)
naPdMat = np.outer(naLog, f[:, 1])
# mate with alien = m.alien.transpose * affinity
alPdMat = np.outer(m[:, 3], f[:, 1])
# add transition matrices for probability density matrix
pdMat = alPdMat + naPdMat
# transition matrix is equal to the pd matrix / column sumso
colSums = np.sum(pdMat, axis=0)
pMat = pdMat / colSums
# select mates
def choice(x):
ch = np.random.choice(a=range(0, len(x)), p=x)
return ch
mCh = np.apply_along_axis(choice, 0, pMat)
mCh = m[mCh, :]
WMid = (f[:, 0] + mCh[:, 0]) / 2
AMid = (f[:, 1] + mCh[:, 1]) / 2
# assign fitness based on group affiliation; only native/alien matings have
# modified fitness
# reassign fitness and affinity based on group id and midparent vals
W1 = np.where(
(f[:, 3] == mCh[:, 3]) |
((f[:, 3] == 1) & (mCh[:, 3] == 0))
)
WMid[W1] = 1
# number of offspring is a poisson-distributed variable with lambda=2W
nOff = map(lambda x: np.random.poisson(lam=x), 2 * WMid)
# generate offspring
# expand list of nOff to numbers of offspring per pair
# realized offspring is index posisions of W and A vals to be replicated
# for offspring
# this can be rewritten to return a matrix of the appropriate length. This
# should work
midVals = np.array([WMid, AMid]).T
realOff = np.array([0, 0])
for i in range(0, len(nOff)):
sibs = np.repeat([np.array(midVals[i])], [nOff[i]], axis=0)
realOff = np.vstack((realOff, sibs))
offspring = np.delete(realOff, 0, 0)
sex = np.random.randint(0, 2, len(offspring))
alien = np.repeat(0, len(offspring))
otherStats = np.array([sex, alien]).T
offspring = np.hstack([offspring, otherStats])
return offspring # should return offspring
def sim(nInit, nGen=100, nAlien=10, gParams=[1, 0.1]):
gen = 0
pop = mkpop
stats = pd.DataFrame(columns=('gen', 'W', 'WMean', 'AMean', 'WVar', 'AVar'))
while gen < nGen:
pop = migrate(pop, nAlien, gParams)
offspring = mate(pop)
var = np.var(offspring, axis=0)
mean = np.mean(offspring, axis=0)
N = len(offspring)
W = N / nInit
genStats = N.append(W, gen, mean, var)
stats = stats.append(genStats)
print(N, gen)
gen = gen + 1
return stats
print mkpop(100)
print mate(mkpop(100))
#
sim(100, 100, 10, [1, 0.1])
Running this script, outputs NameError: name 'sim' is not defined. It is apparent from the commands before the final one that all the other functions defined within this script work without a hitch. I'm not sure what is going on here, and there is probably some very easy fix that I'm overlooking. Ctags recognizes this function just fine. It's entirely possibe that sim() doesn't actually work yet, as I haven't been able to debug it.
Your sim function defined in mate function scope so it's invisible to global scope. You need to fix your indentation for sim function