owlplanner 2025.2.8__py3-none-any.whl → 2025.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
owlplanner/abcapi.py CHANGED
@@ -43,7 +43,7 @@ class Row(object):
43
43
  """
44
44
  Add an element at index ``ind`` of value ``val`` to the row.
45
45
  """
46
- assert 0 <= ind and ind < self.nvars, 'Index %d out of range.' % ind
46
+ assert 0 <= ind and ind < self.nvars, "Index %d out of range." % ind
47
47
  self.ind.append(ind)
48
48
  self.val.append(val)
49
49
 
@@ -96,11 +96,11 @@ class ConstraintMatrix(object):
96
96
  self.lb.append(lb)
97
97
  self.ub.append(ub)
98
98
  if lb == ub:
99
- self.key.append('fx')
99
+ self.key.append("fx")
100
100
  elif ub == np.inf:
101
- self.key.append('lo')
101
+ self.key.append("lo")
102
102
  else:
103
- self.key.append('ra')
103
+ self.key.append("ra")
104
104
  self.ncons += 1
105
105
 
106
106
  def addNewRow(self, rowDic, lb, ub):
@@ -154,39 +154,39 @@ class Bounds(object):
154
154
  self.integrality = []
155
155
 
156
156
  def setBinary(self, ii):
157
- assert 0 <= ii and ii < self.nvars, 'Index %d out of range.' % ii
157
+ assert 0 <= ii and ii < self.nvars, "Index %d out of range." % ii
158
158
  self.ind.append(ii)
159
159
  self.lb.append(0)
160
160
  self.ub.append(1)
161
- self.key.append('ra')
161
+ self.key.append("ra")
162
162
  self.integrality.append(ii)
163
163
 
164
164
  def set0_Ub(self, ii, ub):
165
- assert 0 <= ii and ii < self.nvars, 'Index %d out of range.' % ii
165
+ assert 0 <= ii and ii < self.nvars, "Index %d out of range." % ii
166
166
  self.ind.append(ii)
167
167
  self.lb.append(0)
168
168
  self.ub.append(ub)
169
- self.key.append('ra')
169
+ self.key.append("ra")
170
170
 
171
171
  def setLb_Inf(self, ii, lb):
172
- assert 0 <= ii and ii < self.nvars, 'Index %d out of range.' % ii
172
+ assert 0 <= ii and ii < self.nvars, "Index %d out of range." % ii
173
173
  self.ind.append(ii)
174
174
  self.lb.append(lb)
175
175
  self.ub.append(np.inf)
176
- self.key.append('lo')
176
+ self.key.append("lo")
177
177
 
178
178
  def setRange(self, ii, lb, ub):
179
- assert 0 <= ii and ii < self.nvars, 'Index %d out of range.' % ii
179
+ assert 0 <= ii and ii < self.nvars, "Index %d out of range." % ii
180
180
  self.ind.append(ii)
181
181
  self.lb.append(lb)
182
182
  self.ub.append(ub)
183
183
  if lb == ub:
184
- self.key.append('fx')
184
+ self.key.append("fx")
185
185
  else:
186
- self.key.append('ra')
186
+ self.key.append("ra")
187
187
 
188
188
  def keys(self):
189
- keys = ['lo'] * self.nvars
189
+ keys = ["lo"] * self.nvars
190
190
  for ii in range(len(self.ind)):
191
191
  keys[self.ind[ii]] = self.key[ii]
192
192
 
@@ -223,7 +223,7 @@ class Objective(object):
223
223
  self.val = []
224
224
 
225
225
  def setElem(self, ind, val):
226
- assert 0 <= ind and ind < self.nvars, 'Index %d out of range.' % ind
226
+ assert 0 <= ind and ind < self.nvars, "Index %d out of range." % ind
227
227
  self.ind.append(ind)
228
228
  self.val.append(val)
229
229
 
owlplanner/config.py CHANGED
@@ -24,108 +24,112 @@ def saveConfig(plan, file, mylog):
24
24
  Save case parameters and return a dictionary containing all parameters.
25
25
  """
26
26
  # np.set_printoptions(legacy='1.21')
27
- accountTypes = ['taxable', 'tax-deferred', 'tax-free']
27
+ accountTypes = ["taxable", "tax-deferred", "tax-free"]
28
28
 
29
29
  diconf = {}
30
- diconf['Plan Name'] = plan._name
30
+ diconf["Plan Name"] = plan._name
31
31
 
32
32
  # Basic Info.
33
- diconf['Basic Info'] = {'Status': ['unknown', 'single', 'married'][plan.N_i],
34
- 'Names': plan.inames,
35
- 'Birth year': plan.yobs.tolist(),
36
- 'Life expectancy': plan.expectancy.tolist(),
37
- 'Start date': plan.startDate,
38
- }
33
+ diconf["Basic Info"] = {
34
+ "Status": ["unknown", "single", "married"][plan.N_i],
35
+ "Names": plan.inames,
36
+ "Birth year": plan.yobs.tolist(),
37
+ "Life expectancy": plan.expectancy.tolist(),
38
+ "Start date": plan.startDate,
39
+ }
39
40
 
40
41
  # Assets.
41
- diconf['Assets'] = {}
42
+ diconf["Assets"] = {}
42
43
  for j in range(plan.N_j):
43
44
  amounts = plan.beta_ij[:, j] / 1000
44
- diconf['Assets']['%s savings balances' % accountTypes[j]] = amounts.tolist()
45
+ diconf["Assets"]["%s savings balances" % accountTypes[j]] = amounts.tolist()
45
46
  if plan.N_i == 2:
46
- diconf['Assets']['Beneficiary fractions'] = plan.phi_j.tolist()
47
- diconf['Assets']['Spousal surplus deposit fraction'] = plan.eta
47
+ diconf["Assets"]["Beneficiary fractions"] = plan.phi_j.tolist()
48
+ diconf["Assets"]["Spousal surplus deposit fraction"] = plan.eta
48
49
 
49
50
  # Wages and Contributions.
50
- diconf['Wages and Contributions'] = {'Contributions file name': plan.timeListsFileName}
51
+ diconf["Wages and Contributions"] = {"Contributions file name": plan.timeListsFileName}
51
52
 
52
53
  # Fixed Income.
53
- diconf['Fixed Income'] = {'Pension amounts': (plan.pensionAmounts/1000).tolist(),
54
- 'Pension ages': plan.pensionAges.tolist(),
55
- 'Pension indexed': plan.pensionIndexed,
56
- 'Social security amounts': (plan.ssecAmounts/1000).tolist(),
57
- 'Social security ages': plan.ssecAges.tolist(),
58
- }
59
-
60
- # Rate Selection.
61
- diconf['Rate Selection'] = {'Heirs rate on tax-deferred estate': float(100 * plan.nu),
62
- 'Long-term capital gain tax rate': float(100 * plan.psi),
63
- 'Dividend tax rate': float(100 * plan.mu),
64
- 'Method': plan.rateMethod,
65
- }
66
- if plan.rateMethod in ['user', 'stochastic']:
67
- diconf['Rate Selection']['Values'] = (100 * plan.rateValues).tolist()
68
- if plan.rateMethod in ['stochastic']:
69
- diconf['Rate Selection']['Standard deviations'] = (100 * plan.rateStdev).tolist()
70
- diconf['Rate Selection']['Correlations'] = plan.rateCorr.tolist()
71
- if plan.rateMethod in ['historical average', 'historical', 'histochastic']:
72
- diconf['Rate Selection']['From'] = int(plan.rateFrm)
73
- diconf['Rate Selection']['To'] = int(plan.rateTo)
54
+ diconf["Fixed Income"] = {
55
+ "Pension amounts": (plan.pensionAmounts / 1000).tolist(),
56
+ "Pension ages": plan.pensionAges.tolist(),
57
+ "Pension indexed": plan.pensionIndexed,
58
+ "Social security amounts": (plan.ssecAmounts / 1000).tolist(),
59
+ "Social security ages": plan.ssecAges.tolist(),
60
+ }
61
+
62
+ # Rates Selection.
63
+ diconf["Rates Selection"] = {
64
+ "Heirs rate on tax-deferred estate": float(100 * plan.nu),
65
+ "Long-term capital gain tax rate": float(100 * plan.psi),
66
+ "Dividend tax rate": float(100 * plan.mu),
67
+ "Method": plan.rateMethod,
68
+ }
69
+ if plan.rateMethod in ["user", "stochastic"]:
70
+ diconf["Rates Selection"]["Values"] = (100 * plan.rateValues).tolist()
71
+ if plan.rateMethod in ["stochastic"]:
72
+ diconf["Rates Selection"]["Standard deviations"] = (100 * plan.rateStdev).tolist()
73
+ diconf["Rates Selection"]["Correlations"] = plan.rateCorr.tolist()
74
+ if plan.rateMethod in ["historical average", "historical", "histochastic"]:
75
+ diconf["Rates Selection"]["From"] = int(plan.rateFrm)
76
+ diconf["Rates Selection"]["To"] = int(plan.rateTo)
74
77
  else:
75
- diconf['Rate Selection']['From'] = int(FROM)
76
- diconf['Rate Selection']['To'] = int(TO)
77
-
78
- # Asset Allocations.
79
- diconf['Asset Allocations'] = {'Interpolation method': plan.interpMethod,
80
- 'Interpolation center': float(plan.interpCenter),
81
- 'Interpolation width': float(plan.interpWidth),
82
- 'Type': plan.ARCoord,
83
- }
84
- if plan.ARCoord == 'account':
78
+ diconf["Rates Selection"]["From"] = int(FROM)
79
+ diconf["Rates Selection"]["To"] = int(TO)
80
+
81
+ # Asset Allocation.
82
+ diconf["Asset Allocation"] = {
83
+ "Interpolation method": plan.interpMethod,
84
+ "Interpolation center": float(plan.interpCenter),
85
+ "Interpolation width": float(plan.interpWidth),
86
+ "Type": plan.ARCoord,
87
+ }
88
+ if plan.ARCoord == "account":
85
89
  for accType in accountTypes:
86
- diconf['Asset Allocations'][accType] = plan.boundsAR[accType]
90
+ diconf["Asset Allocation"][accType] = plan.boundsAR[accType]
87
91
  else:
88
- diconf['Asset Allocations']['generic'] = plan.boundsAR['generic']
92
+ diconf["Asset Allocation"]["generic"] = plan.boundsAR["generic"]
89
93
 
90
94
  # Optimization Parameters.
91
- diconf['Optimization Parameters'] = {
92
- 'Spending profile': plan.spendingProfile,
93
- 'Surviving spouse spending percent': int(100 * plan.chi),
94
- }
95
- if plan.spendingProfile == 'smile':
96
- diconf['Optimization Parameters']['Smile dip'] = int(plan.smileDip)
97
- diconf['Optimization Parameters']['Smile increase'] = int(plan.smileIncrease)
98
- diconf['Optimization Parameters']['Smile delay'] = int(plan.smileDelay)
99
-
100
- diconf['Optimization Parameters']['Objective'] = plan.objective
101
- diconf['Solver Options'] = plan.solverOptions
95
+ diconf["Optimization Parameters"] = {
96
+ "Spending profile": plan.spendingProfile,
97
+ "Surviving spouse spending percent": int(100 * plan.chi),
98
+ }
99
+ if plan.spendingProfile == "smile":
100
+ diconf["Optimization Parameters"]["Smile dip"] = int(plan.smileDip)
101
+ diconf["Optimization Parameters"]["Smile increase"] = int(plan.smileIncrease)
102
+ diconf["Optimization Parameters"]["Smile delay"] = int(plan.smileDelay)
103
+
104
+ diconf["Optimization Parameters"]["Objective"] = plan.objective
105
+ diconf["Solver Options"] = plan.solverOptions
102
106
 
103
107
  # Results.
104
- diconf['Results'] = {'Default plots': plan.defaultPlots}
108
+ diconf["Results"] = {"Default plots": plan.defaultPlots}
105
109
 
106
110
  if isinstance(file, str):
107
111
  filename = file
108
- if not file.endswith('.toml'):
109
- filename = filename + '.toml'
110
- if not filename.startswith('case_'):
111
- filename = 'case_' + filename
112
+ if not file.endswith(".toml"):
113
+ filename = filename + ".toml"
114
+ if not filename.startswith("case_"):
115
+ filename = "case_" + filename
112
116
  mylog.vprint("Saving plan case file as '%s'." % filename)
113
117
 
114
118
  try:
115
- with open(filename, 'w') as casefile:
119
+ with open(filename, "w") as casefile:
116
120
  toml.dump(diconf, casefile, encoder=toml.TomlNumpyEncoder())
117
121
  except Exception as e:
118
- raise RuntimeError('Failed to save case file %s: %s' % (filename, e))
122
+ raise RuntimeError("Failed to save case file %s: %s" % (filename, e))
119
123
  elif isinstance(file, StringIO):
120
124
  try:
121
125
  string = toml.dumps(diconf, encoder=toml.TomlNumpyEncoder())
122
126
  file.write(string)
123
127
  except Exception as e:
124
- raise RuntimeError('Failed to save case to StringIO: %s', e)
128
+ raise RuntimeError("Failed to save case to StringIO: %s", e)
125
129
  elif file is None:
126
130
  pass
127
131
  else:
128
- raise ValueError('Argument %s has unknown type' % type(file))
132
+ raise ValueError("Argument %s has unknown type" % type(file))
129
133
 
130
134
  return diconf
131
135
 
@@ -138,146 +142,147 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
138
142
  """
139
143
  mylog = logging.Logger(verbose, logstreams)
140
144
 
141
- accountTypes = ['taxable', 'tax-deferred', 'tax-free']
145
+ accountTypes = ["taxable", "tax-deferred", "tax-free"]
142
146
 
143
- dirname = ''
147
+ dirname = ""
144
148
  if isinstance(file, str):
145
149
  filename = file
146
150
  dirname = os.path.dirname(filename)
147
- if not filename.endswith('.toml'):
148
- filename = filename + '.toml'
151
+ if not filename.endswith(".toml"):
152
+ filename = filename + ".toml"
149
153
 
150
154
  mylog.vprint("Reading plan from case file '%s'." % filename)
151
155
 
152
156
  try:
153
- with open(filename, 'r') as f:
157
+ with open(filename, "r") as f:
154
158
  diconf = toml.load(f)
155
159
  except Exception as e:
156
- raise FileNotFoundError('File %s not found: %s' % (filename, e))
160
+ raise FileNotFoundError("File %s not found: %s" % (filename, e))
157
161
  elif isinstance(file, BytesIO):
158
162
  try:
159
- string = file.getvalue().decode('utf-8')
163
+ string = file.getvalue().decode("utf-8")
160
164
  diconf = toml.loads(string)
161
165
  except Exception as e:
162
- raise RuntimeError('Cannot read from BytesIO: %s' % e)
166
+ raise RuntimeError("Cannot read from BytesIO: %s" % e)
163
167
  elif isinstance(file, StringIO):
164
168
  try:
165
169
  string = file.getvalue()
166
170
  diconf = toml.loads(string)
167
171
  except Exception as e:
168
- raise RuntimeError('Cannot read from StringIO: %s' % e)
172
+ raise RuntimeError("Cannot read from StringIO: %s" % e)
169
173
  else:
170
- raise ValueError('%s not a valid type' % type(file))
174
+ raise ValueError("%s not a valid type" % type(file))
171
175
 
172
176
  # Basic Info.
173
- name = diconf['Plan Name']
174
- inames = diconf['Basic Info']['Names']
177
+ name = diconf["Plan Name"]
178
+ inames = diconf["Basic Info"]["Names"]
175
179
  # status = diconf['Basic Info']['Status']
176
- yobs = diconf['Basic Info']['Birth year']
177
- expectancy = diconf['Basic Info']['Life expectancy']
178
- startDate = diconf['Basic Info']['Start date']
180
+ yobs = diconf["Basic Info"]["Birth year"]
181
+ expectancy = diconf["Basic Info"]["Life expectancy"]
182
+ startDate = diconf["Basic Info"]["Start date"]
179
183
  icount = len(yobs)
180
184
 
181
- mylog.vprint('Plan for %d individual%s: %s.' % (icount, ['', 's'][icount - 1], inames))
185
+ mylog.vprint("Plan for %d individual%s: %s." % (icount, ["", "s"][icount - 1], inames))
182
186
  p = plan.Plan(inames, yobs, expectancy, name, startDate=startDate, verbose=True, logstreams=logstreams)
183
187
 
184
188
  # Assets.
185
189
  balances = {}
186
190
  for acc in accountTypes:
187
- balances[acc] = diconf['Assets']['%s savings balances' % acc]
188
- p.setAccountBalances(taxable=balances['taxable'], taxDeferred=balances['tax-deferred'],
189
- taxFree=balances['tax-free'])
191
+ balances[acc] = diconf["Assets"]["%s savings balances" % acc]
192
+ p.setAccountBalances(
193
+ taxable=balances["taxable"], taxDeferred=balances["tax-deferred"], taxFree=balances["tax-free"]
194
+ )
190
195
  if icount == 2:
191
- phi_j = diconf['Assets']['Beneficiary fractions']
196
+ phi_j = diconf["Assets"]["Beneficiary fractions"]
192
197
  p.setBeneficiaryFractions(phi_j)
193
- eta = diconf['Assets']['Spousal surplus deposit fraction']
198
+ eta = diconf["Assets"]["Spousal surplus deposit fraction"]
194
199
  p.setSpousalDepositFraction(eta)
195
200
 
196
201
  # Wages and Contributions.
197
- timeListsFileName = diconf['Wages and Contributions']['Contributions file name']
198
- if timeListsFileName != 'None':
202
+ timeListsFileName = diconf["Wages and Contributions"]["Contributions file name"]
203
+ if timeListsFileName != "None":
199
204
  if readContributions:
200
205
  if os.path.exists(timeListsFileName):
201
206
  myfile = timeListsFileName
202
- elif dirname != '' and os.path.exists(dirname + '/' + timeListsFileName):
203
- myfile = dirname + '/' + timeListsFileName
207
+ elif dirname != "" and os.path.exists(dirname + "/" + timeListsFileName):
208
+ myfile = dirname + "/" + timeListsFileName
204
209
  else:
205
210
  raise FileNotFoundError("File '%s' not found." % timeListsFileName)
206
211
  p.readContributions(myfile)
207
212
  else:
208
213
  p.timeListsFileName = timeListsFileName
209
- mylog.vprint('Ignoring to read contributions file %s.' % timeListsFileName)
214
+ mylog.vprint("Ignoring to read contributions file %s." % timeListsFileName)
210
215
 
211
216
  # Fixed Income.
212
- ssecAmounts = np.array(diconf['Fixed Income']['Social security amounts'], dtype=np.float32)
213
- ssecAges = np.array(diconf['Fixed Income']['Social security ages'], dtype=np.int32)
217
+ ssecAmounts = np.array(diconf["Fixed Income"]["Social security amounts"], dtype=np.float32)
218
+ ssecAges = np.array(diconf["Fixed Income"]["Social security ages"], dtype=np.int32)
214
219
  p.setSocialSecurity(ssecAmounts, ssecAges)
215
- pensionAmounts = np.array(diconf['Fixed Income']['Pension amounts'], dtype=np.float32)
216
- pensionAges = np.array(diconf['Fixed Income']['Pension ages'], dtype=np.int32)
217
- pensionIndexed = diconf['Fixed Income']['Pension indexed']
220
+ pensionAmounts = np.array(diconf["Fixed Income"]["Pension amounts"], dtype=np.float32)
221
+ pensionAges = np.array(diconf["Fixed Income"]["Pension ages"], dtype=np.int32)
222
+ pensionIndexed = diconf["Fixed Income"]["Pension indexed"]
218
223
  p.setPension(pensionAmounts, pensionAges, pensionIndexed)
219
224
 
220
- # Rate Selection.
221
- p.setDividendRate(float(diconf['Rate Selection']['Dividend tax rate']))
222
- p.setLongTermCapitalTaxRate(float(diconf['Rate Selection']['Long-term capital gain tax rate']))
223
- p.setHeirsTaxRate(float(diconf['Rate Selection']['Heirs rate on tax-deferred estate']))
225
+ # Rates Selection.
226
+ p.setDividendRate(float(diconf["Rates Selection"]["Dividend tax rate"]))
227
+ p.setLongTermCapitalTaxRate(float(diconf["Rates Selection"]["Long-term capital gain tax rate"]))
228
+ p.setHeirsTaxRate(float(diconf["Rates Selection"]["Heirs rate on tax-deferred estate"]))
224
229
 
225
230
  frm = None
226
231
  to = None
227
232
  rateValues = None
228
233
  stdev = None
229
234
  rateCorr = None
230
- rateMethod = diconf['Rate Selection']['Method']
231
- if rateMethod in ['historical average', 'historical', 'histochastic']:
232
- frm = diconf['Rate Selection']['From']
235
+ rateMethod = diconf["Rates Selection"]["Method"]
236
+ if rateMethod in ["historical average", "historical", "histochastic"]:
237
+ frm = diconf["Rates Selection"]["From"]
233
238
  if not isinstance(frm, int):
234
239
  frm = int(frm)
235
- to = int(diconf['Rate Selection']['To'])
240
+ to = int(diconf["Rates Selection"]["To"])
236
241
  if not isinstance(to, int):
237
242
  to = int(to)
238
- if rateMethod in ['user', 'stochastic']:
239
- rateValues = np.array(diconf['Rate Selection']['Values'], dtype=np.float32)
240
- if rateMethod in ['stochastic']:
241
- stdev = np.array(diconf['Rate Selection']['Standard deviations'], dtype=np.float32)
242
- rateCorr = np.array(diconf['Rate Selection']['Correlations'], dtype=np.float32)
243
+ if rateMethod in ["user", "stochastic"]:
244
+ rateValues = np.array(diconf["Rates Selection"]["Values"], dtype=np.float32)
245
+ if rateMethod in ["stochastic"]:
246
+ stdev = np.array(diconf["Rates Selection"]["Standard deviations"], dtype=np.float32)
247
+ rateCorr = np.array(diconf["Rates Selection"]["Correlations"], dtype=np.float32)
243
248
  p.setRates(rateMethod, frm, to, rateValues, stdev, rateCorr)
244
249
 
245
250
  # Asset Allocation.
246
251
  boundsAR = {}
247
252
  p.setInterpolationMethod(
248
- diconf['Asset Allocations']['Interpolation method'],
249
- float(diconf['Asset Allocations']['Interpolation center']),
250
- float(diconf['Asset Allocations']['Interpolation width']),
253
+ diconf["Asset Allocation"]["Interpolation method"],
254
+ float(diconf["Asset Allocation"]["Interpolation center"]),
255
+ float(diconf["Asset Allocation"]["Interpolation width"]),
251
256
  )
252
- allocType = diconf['Asset Allocations']['Type']
253
- if allocType == 'account':
257
+ allocType = diconf["Asset Allocation"]["Type"]
258
+ if allocType == "account":
254
259
  for aType in accountTypes:
255
- boundsAR[aType] = np.array(diconf['Asset Allocations'][aType], dtype=np.float32)
260
+ boundsAR[aType] = np.array(diconf["Asset Allocation"][aType], dtype=np.float32)
256
261
 
257
262
  p.setAllocationRatios(
258
263
  allocType,
259
- taxable=boundsAR['taxable'],
260
- taxDeferred=boundsAR['tax-deferred'],
261
- taxFree=boundsAR['tax-free'],
264
+ taxable=boundsAR["taxable"],
265
+ taxDeferred=boundsAR["tax-deferred"],
266
+ taxFree=boundsAR["tax-free"],
262
267
  )
263
- elif allocType == 'individual' or allocType == 'spouses':
264
- boundsAR['generic'] = np.array(diconf['Asset Allocations']['generic'], dtype=np.float32)
268
+ elif allocType == "individual" or allocType == "spouses":
269
+ boundsAR["generic"] = np.array(diconf["Asset Allocation"]["generic"], dtype=np.float32)
265
270
  p.setAllocationRatios(
266
271
  allocType,
267
- generic=boundsAR['generic'],
272
+ generic=boundsAR["generic"],
268
273
  )
269
274
  else:
270
- raise ValueError('Unknown asset allocation type %s.' % allocType)
275
+ raise ValueError("Unknown asset allocation type %s." % allocType)
271
276
 
272
277
  # Optimization Parameters.
273
- p.objective = diconf['Optimization Parameters']['Objective']
274
-
275
- profile = diconf['Optimization Parameters']['Spending profile']
276
- survivor = int(diconf['Optimization Parameters']['Surviving spouse spending percent'])
277
- if profile == 'smile':
278
- dip = int(diconf['Optimization Parameters']['Smile dip'])
279
- increase = int(diconf['Optimization Parameters']['Smile increase'])
280
- delay = int(diconf['Optimization Parameters']['Smile delay'])
278
+ p.objective = diconf["Optimization Parameters"]["Objective"]
279
+
280
+ profile = diconf["Optimization Parameters"]["Spending profile"]
281
+ survivor = int(diconf["Optimization Parameters"]["Surviving spouse spending percent"])
282
+ if profile == "smile":
283
+ dip = int(diconf["Optimization Parameters"]["Smile dip"])
284
+ increase = int(diconf["Optimization Parameters"]["Smile increase"])
285
+ delay = int(diconf["Optimization Parameters"]["Smile delay"])
281
286
  else:
282
287
  dip = 15
283
288
  increase = 12
@@ -286,9 +291,9 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
286
291
  p.setSpendingProfile(profile, survivor, dip, increase, delay)
287
292
 
288
293
  # Solver Options.
289
- p.solverOptions = diconf['Solver Options']
294
+ p.solverOptions = diconf["Solver Options"]
290
295
 
291
296
  # Results.
292
- p.setDefaultPlots(diconf['Results']['Default plots'])
297
+ p.setDefaultPlots(diconf["Results"]["Default plots"])
293
298
 
294
299
  return p
owlplanner/logging.py CHANGED
@@ -19,15 +19,15 @@ class Logger(object):
19
19
  self._prevState = self._verbose
20
20
  if logstreams is None or logstreams == [] or len(logstreams) > 2:
21
21
  self._logstreams = [sys.stdout, sys.stderr]
22
- self.vprint('Using stdout and stderr as stream loggers.')
22
+ self.vprint("Using stdout and stderr as stream loggers.")
23
23
  elif len(logstreams) == 2:
24
24
  self._logstreams = logstreams
25
- self.vprint('Using logstreams as stream loggers.')
25
+ self.vprint("Using logstreams as stream loggers.")
26
26
  elif len(logstreams) == 1:
27
- self._logstreams = 2*logstreams
28
- self.vprint('Using logstream as stream logger.')
27
+ self._logstreams = 2 * logstreams
28
+ self.vprint("Using logstream as stream logger.")
29
29
  else:
30
- raise ValueError('Log streams %r must be a list.' % logstreams)
30
+ raise ValueError("Log streams %r must be a list." % logstreams)
31
31
 
32
32
  def setVerbose(self, verbose=True):
33
33
  """
@@ -36,7 +36,7 @@ class Logger(object):
36
36
  """
37
37
  self._prevState = self._verbose
38
38
  self._verbose = verbose
39
- self.vprint('Setting verbose to', verbose)
39
+ self.vprint("Setting verbose to", verbose)
40
40
 
41
41
  return self._prevState
42
42
 
@@ -51,9 +51,9 @@ class Logger(object):
51
51
  Unconditional printing regardless of the value of the verbose variable
52
52
  previously set.
53
53
  """
54
- if 'file' not in kwargs:
54
+ if "file" not in kwargs:
55
55
  file = self._logstreams[0]
56
- kwargs['file'] = file
56
+ kwargs["file"] = file
57
57
 
58
58
  print(*args, **kwargs)
59
59
  file.flush()
@@ -71,14 +71,14 @@ class Logger(object):
71
71
  Print message and exit. Use to print error messages on stderr.
72
72
  The exit() used throws an exception in an interactive environment.
73
73
  """
74
- if 'file' not in kwargs:
74
+ if "file" not in kwargs:
75
75
  file = self._logstreams[1]
76
- kwargs['file'] = file
76
+ kwargs["file"] = file
77
77
 
78
78
  if self._verbose:
79
- print('ERROR:', *args, **kwargs)
80
- print('Exiting...')
79
+ print("ERROR:", *args, **kwargs)
80
+ print("Exiting...")
81
81
  file.flush()
82
82
 
83
- raise Exception('Fatal error.')
83
+ raise Exception("Fatal error.")
84
84
  # sys.exit(-1)