SearchLibrium 0.0.129__tar.gz → 0.0.131__tar.gz
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.
Potentially problematic release.
This version of SearchLibrium might be problematic. Click here for more details.
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/PKG-INFO +1 -1
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/pyproject.toml +1 -1
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/harmony.py +5 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/search.py +126 -65
- searchlibrium-0.0.131/src/SearchLibrium/version.txt +1 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/PKG-INFO +1 -1
- searchlibrium-0.0.129/src/SearchLibrium/version.txt +0 -1
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/README.md +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/setup.cfg +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/Halton.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/MixedLogit.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/Mode_Activity_Nested.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/RandomP.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/SEARCH_SM_MARIO.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/Two_Level_Nest.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/__init__.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/__main__.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/_choice_model.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/_device.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/banditsa.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/bhhh/minimize.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/boxcox_functions.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/call_meta.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/constraints_builder.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/hspbil.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/latent_class.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/main.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/main_debug.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/mdcev.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/misc.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/mixed_logit.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/mixed_nested.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/mixedrrm.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/multinomial_logit.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/multinomial_nested.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/multinomial_probit.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/ordered_logit.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/ordered_logit_mixed.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/predict.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/rrm.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/sapbil.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/selection_models.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/setup.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/siman.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/test_lc_de.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/test_mario_searches.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/test_sapbil_vs_banditsa.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/threshold.py +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/SOURCES.txt +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/dependency_links.txt +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/entry_points.txt +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/requires.txt +0 -0
- {searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SearchLibrium
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.131
|
|
4
4
|
Summary: A Python package for econometric models driven by search
|
|
5
5
|
Author: Mario Fernando Taco Morales, Alexander Paz, Prithvi Beeramole, Robert Burdett
|
|
6
6
|
Author-email: Zeke Ahern <z.ahern@qut.edu.au>
|
|
@@ -73,7 +73,7 @@ Documentation = "https://pypi.org/project/SearchLibrium/"
|
|
|
73
73
|
realpython = "SearchLibrium.__main__:main"
|
|
74
74
|
|
|
75
75
|
[tool.bumpver]
|
|
76
|
-
current_version = "0.0.
|
|
76
|
+
current_version = "0.0.131"
|
|
77
77
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
78
78
|
commit_message = "[skip ci] Bump version {old_version} -> {new_version}"
|
|
79
79
|
commit = true
|
|
@@ -1647,6 +1647,11 @@ class HarmonySearch(Search):
|
|
|
1647
1647
|
''' call_search can use the same driver code as call_siman. '''
|
|
1648
1648
|
''' ---------------------------------------------------------------- '''
|
|
1649
1649
|
|
|
1650
|
+
def copy_solution(self, sol):
|
|
1651
|
+
"""Deep-copy a Solution — mirror of Search.copy_solution for SA-compat."""
|
|
1652
|
+
import copy
|
|
1653
|
+
return copy.deepcopy(sol)
|
|
1654
|
+
|
|
1650
1655
|
def run_search(self, existing_sols=None):
|
|
1651
1656
|
# {
|
|
1652
1657
|
"""Override the inherited no-op run_search with the real HS loop."""
|
|
@@ -1223,6 +1223,20 @@ class Search():
|
|
|
1223
1223
|
self.idnum = idnum
|
|
1224
1224
|
self.local_impr = 0
|
|
1225
1225
|
|
|
1226
|
+
# ── Banlist: specifications that have already failed ────────────
|
|
1227
|
+
# Signatures (SHA-256 hashes) of specs that crashed or returned
|
|
1228
|
+
# non-converged / infinite results. These are never visited again.
|
|
1229
|
+
self._banlist = set()
|
|
1230
|
+
|
|
1231
|
+
# ── Variable-level failure tracker ──────────────────────────────
|
|
1232
|
+
# {varname: count} — how many times each variable appeared in a
|
|
1233
|
+
# failed (non-convergent, exception, infinite-LL) specification.
|
|
1234
|
+
# When count exceeds _var_attrition_limit the variable is removed
|
|
1235
|
+
# from the available lists so it never appears again for the
|
|
1236
|
+
# remainder of the search.
|
|
1237
|
+
self._var_failures = {}
|
|
1238
|
+
self._var_attrition_limit = 15 # failures before permanent removal
|
|
1239
|
+
|
|
1226
1240
|
# ── Latent class feature toggles ────────────────────────────────
|
|
1227
1241
|
self.optimise_class = kwargs.get('optimise_class', False)
|
|
1228
1242
|
self.optimise_membership = kwargs.get('optimise_membership', False)
|
|
@@ -2160,6 +2174,24 @@ class Search():
|
|
|
2160
2174
|
if 'corvars' in solution and v in solution['corvars']:
|
|
2161
2175
|
solution['corvars'] = [x for x in solution['corvars'] if x != v]
|
|
2162
2176
|
|
|
2177
|
+
def _cull_attrited_vars(self):
|
|
2178
|
+
"""Remove variables from the available pools that have exceeded the
|
|
2179
|
+
failure threshold. Once removed they stay out for the rest of
|
|
2180
|
+
the search, freeing the algorithm to focus on viable variables.
|
|
2181
|
+
"""
|
|
2182
|
+
limit = self._var_attrition_limit
|
|
2183
|
+
forced = set(self._get_forced_vars())
|
|
2184
|
+
to_kill = {v for v, cnt in self._var_failures.items()
|
|
2185
|
+
if cnt >= limit and v not in forced}
|
|
2186
|
+
if not to_kill:
|
|
2187
|
+
return
|
|
2188
|
+
for v in sorted(to_kill):
|
|
2189
|
+
if hasattr(self.param, 'avail_asvars') and v in self.param.avail_asvars:
|
|
2190
|
+
self.param.avail_asvars.remove(v)
|
|
2191
|
+
if hasattr(self.param, 'avail_isvars') and v in self.param.avail_isvars:
|
|
2192
|
+
self.param.avail_isvars.remove(v)
|
|
2193
|
+
print(f" [attrition] '{v}' removed from search after {self._var_failures[v]} failures")
|
|
2194
|
+
|
|
2163
2195
|
def _apply_latent_class_constraints(self, solution, lc_constraints):
|
|
2164
2196
|
"""Apply constraints specific to latent class models."""
|
|
2165
2197
|
# Example: force variables to appear only in certain classes
|
|
@@ -3685,6 +3717,11 @@ class Search():
|
|
|
3685
3717
|
''' ---------------------------------------------------------- '''
|
|
3686
3718
|
def evaluate_solution(self, sol):
|
|
3687
3719
|
# {
|
|
3720
|
+
sig = self.setup_signature(sol)
|
|
3721
|
+
if sig in self._banlist:
|
|
3722
|
+
sol['converged'] = False
|
|
3723
|
+
return (sol, False)
|
|
3724
|
+
|
|
3688
3725
|
as_vars, is_vars, rand_vars, bc_vars, corvars, asc_ind = self.get_components(sol)
|
|
3689
3726
|
all_vars = is_vars + as_vars
|
|
3690
3727
|
all_vars = [var for var in self.param.varnames if var in all_vars]
|
|
@@ -3692,17 +3729,32 @@ class Search():
|
|
|
3692
3729
|
# Estimate model if input variables are present in specification
|
|
3693
3730
|
if not all_vars:
|
|
3694
3731
|
sol['converged'] = False
|
|
3732
|
+
self._banlist.add(sig)
|
|
3695
3733
|
return (sol, False)
|
|
3696
3734
|
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3735
|
+
try:
|
|
3736
|
+
# Run backward elimination if enabled (default True), otherwise a single fit
|
|
3737
|
+
all_sig = getattr(self.param, 'all_sig', True)
|
|
3738
|
+
if all_sig:
|
|
3739
|
+
sol, converged = self.backward_eliminate(sol)
|
|
3740
|
+
else:
|
|
3741
|
+
result = self.evaluate_model(sol)
|
|
3742
|
+
aic, bic, loglik, mae, asvars, isvars, randvars, bcvars, corvars, converged, sol = result
|
|
3743
|
+
sol['bcvars'] = bcvars
|
|
3744
|
+
sol['aic'], sol['bic'], sol['loglik'], sol['mae'] = aic, bic, loglik, mae
|
|
3745
|
+
except Exception:
|
|
3746
|
+
sol['converged'] = False
|
|
3747
|
+
self._banlist.add(sig)
|
|
3748
|
+
if hasattr(self, 'best_solution') and self.best_solution is not None:
|
|
3749
|
+
fail_vars = set(as_vars + is_vars)
|
|
3750
|
+
base_as = set(self.best_solution.get('asvars', []))
|
|
3751
|
+
base_is = set(self.best_solution.get('isvars', []))
|
|
3752
|
+
new_vars = fail_vars - (base_as | base_is)
|
|
3753
|
+
if new_vars:
|
|
3754
|
+
for v in new_vars:
|
|
3755
|
+
self._var_failures[v] = self._var_failures.get(v, 0) + 1
|
|
3756
|
+
self._cull_attrited_vars()
|
|
3757
|
+
return (sol, False)
|
|
3706
3758
|
|
|
3707
3759
|
if converged or (isinstance(sol.get('loglik'), float) and math.isfinite(sol.get('loglik', float('nan')))):
|
|
3708
3760
|
# {
|
|
@@ -3720,6 +3772,20 @@ class Search():
|
|
|
3720
3772
|
# {
|
|
3721
3773
|
self.not_converged += 1
|
|
3722
3774
|
sol['converged'] = False
|
|
3775
|
+
# ── Banlist: never visit this exact specification again
|
|
3776
|
+
self._banlist.add(sig)
|
|
3777
|
+
# ── Variable attrition: only blame vars ADDED vs the
|
|
3778
|
+
# currently-accepted best (neighbour) model.
|
|
3779
|
+
# Skip entirely on init / startup — no baseline yet.
|
|
3780
|
+
if hasattr(self, 'best_solution') and self.best_solution is not None:
|
|
3781
|
+
fail_vars = set(as_vars + is_vars)
|
|
3782
|
+
base_as = set(self.best_solution.get('asvars', []))
|
|
3783
|
+
base_is = set(self.best_solution.get('isvars', []))
|
|
3784
|
+
new_vars = fail_vars - (base_as | base_is)
|
|
3785
|
+
if new_vars:
|
|
3786
|
+
for v in new_vars:
|
|
3787
|
+
self._var_failures[v] = self._var_failures.get(v, 0) + 1
|
|
3788
|
+
self._cull_attrited_vars()
|
|
3723
3789
|
# ── Convergence diagnostic: explain why the model did not converge
|
|
3724
3790
|
self._diagnose_nonconvergence(sol, model_n=sol.get('model_n', ''))
|
|
3725
3791
|
# }
|
|
@@ -4009,17 +4075,8 @@ class Search():
|
|
|
4009
4075
|
model.fit()
|
|
4010
4076
|
|
|
4011
4077
|
|
|
4012
|
-
#
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
def fit_random_regret(self, df):
|
|
4016
|
-
model = RandomRegret(df=df, short=False, normalize=True)
|
|
4017
|
-
#a = (df, s)
|
|
4018
|
-
# model.setup_long()
|
|
4019
|
-
# model.setup(X, y, varnames,alts , isvars, transvars, ids, weights, panels, avail, base_alt)
|
|
4020
|
-
model.fit()
|
|
4021
|
-
model.report()
|
|
4022
|
-
return model
|
|
4078
|
+
# fit_random_regret moved below with transvars support
|
|
4079
|
+
# (see evaluate_rrm section)
|
|
4023
4080
|
|
|
4024
4081
|
|
|
4025
4082
|
|
|
@@ -4166,40 +4223,27 @@ class Search():
|
|
|
4166
4223
|
|
|
4167
4224
|
def evaluate_nested_logit(self, sol):
|
|
4168
4225
|
"""Evaluates a Nested Logit model."""
|
|
4169
|
-
|
|
4170
|
-
sol =self.apply_constraints(sol)
|
|
4226
|
+
sol = self.apply_constraints(sol)
|
|
4171
4227
|
as_vars, is_vars, asc_ind = sol['asvars'], sol['isvars'], sol['asc_ind']
|
|
4172
|
-
|
|
4173
|
-
state = sol['state']
|
|
4174
|
-
|
|
4175
|
-
#state['nest_vars']
|
|
4176
|
-
#sol = self.apply_constraints(sol)
|
|
4177
|
-
#sol = self.repair_solution(sol)
|
|
4178
|
-
# Define nests and lambda values (adjust based on your data)
|
|
4179
|
-
# TODO NEED TO FEED IN THE NESTS FROM params
|
|
4228
|
+
bc_vars = self.define_bc_vars(sol)
|
|
4180
4229
|
nests = self.param.nests
|
|
4181
4230
|
lambdas = self.param.lambdas
|
|
4182
|
-
#lambdas_mapping = self.param.lambdas_mapping
|
|
4183
4231
|
|
|
4184
|
-
# Filter the variables to include in the model
|
|
4185
4232
|
all_vars = as_vars + is_vars
|
|
4186
4233
|
if len(all_vars) == 0:
|
|
4187
4234
|
raise ValueError('need a variable: todo debug why')
|
|
4188
4235
|
all_vars = [var for var in self.param.varnames if var in all_vars]
|
|
4189
4236
|
nest_vars = [var for var in self.param.varnest if var in all_vars]
|
|
4190
4237
|
|
|
4191
|
-
#to do if nest_vars is None repair
|
|
4192
|
-
# if nest vars)not in all_var repair
|
|
4193
|
-
|
|
4194
|
-
# Prepare data for the nested logit model
|
|
4195
4238
|
X, y = self.param.df[all_vars].values, self.param.choices
|
|
4196
4239
|
X_nest = self.param.df[nest_vars]
|
|
4197
4240
|
|
|
4198
|
-
# Fit the Nested Logit model
|
|
4199
4241
|
model = NestedLogit(_jax=getattr(self.param, '_jax', True))
|
|
4200
|
-
model.setup(X=X, X_nest
|
|
4242
|
+
model.setup(X=X, X_nest=X_nest, y=y, varnames=all_vars, isvars=is_vars,
|
|
4201
4243
|
alts=self.param.alt_var, ids=self.param.choice_id,
|
|
4202
|
-
nests=nests, lambdas=lambdas, fit_intercept=asc_ind,
|
|
4244
|
+
nests=nests, lambdas=lambdas, fit_intercept=asc_ind,
|
|
4245
|
+
transvars=bc_vars,
|
|
4246
|
+
return_grad=self.param.grad, return_hess=self.param.hess)
|
|
4203
4247
|
|
|
4204
4248
|
model.fit()
|
|
4205
4249
|
|
|
@@ -4234,6 +4278,7 @@ class Search():
|
|
|
4234
4278
|
sol = self.apply_constraints(sol)
|
|
4235
4279
|
as_vars, is_vars, asc_ind = sol['asvars'], sol['isvars'], sol['asc_ind']
|
|
4236
4280
|
randvars = sol.get('randvars', {})
|
|
4281
|
+
bc_vars = self.define_bc_vars(sol)
|
|
4237
4282
|
|
|
4238
4283
|
nests = self.param.nests
|
|
4239
4284
|
lambdas = self.param.lambdas
|
|
@@ -4257,6 +4302,7 @@ class Search():
|
|
|
4257
4302
|
nests=nests,
|
|
4258
4303
|
lambdas=lambdas,
|
|
4259
4304
|
randvars=randvars,
|
|
4305
|
+
transvars=bc_vars,
|
|
4260
4306
|
panels=self.param.ind_id,
|
|
4261
4307
|
fit_intercept=asc_ind,
|
|
4262
4308
|
n_draws=n_draws,
|
|
@@ -4277,30 +4323,26 @@ class Search():
|
|
|
4277
4323
|
|
|
4278
4324
|
|
|
4279
4325
|
def evaluate_nested_logit_ml(self, sol):
|
|
4280
|
-
"""Evaluates a Nested Logit model."""
|
|
4281
|
-
# Extract relevant model parameters
|
|
4326
|
+
"""Evaluates a Multi-Layer Nested Logit model."""
|
|
4282
4327
|
as_vars, is_vars, asc_ind = sol['asvars'], sol['isvars'], sol['asc_ind']
|
|
4328
|
+
bc_vars = self.define_bc_vars(sol)
|
|
4283
4329
|
|
|
4284
|
-
# Define nests and lambda values (adjust based on your data)
|
|
4285
|
-
#TODO NEED TO FEED IN THE NESTS FROM params
|
|
4286
4330
|
nests = self.param.nests
|
|
4287
4331
|
lambdas = self.param.lambdas
|
|
4288
4332
|
lambdas_mapping = self.param.lambdas_mapping
|
|
4289
4333
|
|
|
4290
|
-
# Filter the variables to include in the model
|
|
4291
4334
|
all_vars = as_vars + is_vars
|
|
4292
|
-
if len(all_vars) ==0:
|
|
4335
|
+
if len(all_vars) == 0:
|
|
4293
4336
|
raise ValueError('need a variable: todo debug why')
|
|
4294
4337
|
all_vars = [var for var in self.param.varnames if var in all_vars]
|
|
4295
4338
|
|
|
4296
|
-
# Prepare data for the nested logit model
|
|
4297
4339
|
X, y = self.param.df[all_vars].values, self.param.choices
|
|
4298
4340
|
|
|
4299
|
-
# Fit the Nested Logit model
|
|
4300
4341
|
model = MultiLayerNestedLogit()
|
|
4301
4342
|
model.setup(X=X, y=y, varnames=all_vars, isvars=is_vars,
|
|
4302
|
-
|
|
4303
|
-
|
|
4343
|
+
alts=self.param.alt_var, ids=self.param.choice_id,
|
|
4344
|
+
nests=nests, lambdas=lambdas, lambdas_mapping=lambdas_mapping,
|
|
4345
|
+
transvars=bc_vars, fit_intercept=asc_ind, return_grad=False)
|
|
4304
4346
|
|
|
4305
4347
|
model.fit()
|
|
4306
4348
|
|
|
@@ -4383,26 +4425,42 @@ class Search():
|
|
|
4383
4425
|
|
|
4384
4426
|
return sub, all_attr_vars
|
|
4385
4427
|
|
|
4386
|
-
def fit_random_regret(self, df, use_jax=True):
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
model
|
|
4428
|
+
def fit_random_regret(self, df, use_jax=True, transvars=None):
|
|
4429
|
+
if transvars:
|
|
4430
|
+
# Build model via setup() so transvars flow through pre_process
|
|
4431
|
+
# RRM uses attribute_vars as the model variables
|
|
4432
|
+
all_vars = list(df.columns.difference(['id', 'alt', 'choice', 'weight']))
|
|
4433
|
+
X = df[all_vars].values
|
|
4434
|
+
y = df['choice'].values.astype(np.int32)
|
|
4435
|
+
alts = df['alt'].values.astype(np.int32)
|
|
4436
|
+
ids = df['id'].values.astype(np.int32)
|
|
4437
|
+
model = RandomRegret()
|
|
4438
|
+
model.setup(X=X, y=y, varnames=all_vars, alts=alts, ids=ids,
|
|
4439
|
+
transvars=[v for v in transvars if v in all_vars])
|
|
4440
|
+
if use_jax:
|
|
4441
|
+
model.fit_jax()
|
|
4442
|
+
else:
|
|
4443
|
+
model.fit()
|
|
4390
4444
|
else:
|
|
4391
|
-
model
|
|
4445
|
+
model = RandomRegret(df=df, short=False, normalize=True)
|
|
4446
|
+
if use_jax:
|
|
4447
|
+
model.fit_jax()
|
|
4448
|
+
else:
|
|
4449
|
+
model.fit()
|
|
4392
4450
|
model.report()
|
|
4393
4451
|
return model
|
|
4394
4452
|
|
|
4395
4453
|
def evaluate_rrm(self, sol):
|
|
4396
4454
|
as_vars, is_vars, asc_ind = sol['asvars'], sol['isvars'], sol['asc_ind']
|
|
4455
|
+
bc_vars = self.define_bc_vars(sol)
|
|
4456
|
+
bc_vars = [v for v in bc_vars if v not in self.param.isvarnames]
|
|
4397
4457
|
|
|
4398
4458
|
df, attr_vars = self._build_rrm_df(self.param.df, as_vars, is_vars)
|
|
4399
|
-
model = self.fit_random_regret(df=df)
|
|
4459
|
+
model = self.fit_random_regret(df=df, transvars=bc_vars)
|
|
4400
4460
|
sol['model'] = model
|
|
4401
4461
|
sol['coeff'] = model.coeff_est if hasattr(model, 'coeff_est') else model.beta
|
|
4402
4462
|
converged = model.converged
|
|
4403
4463
|
aic, bic, loglik = model.aic, model.bic, model.loglik
|
|
4404
|
-
bc_vars = self.define_bc_vars(sol)
|
|
4405
|
-
bc_vars = [v for v in bc_vars if v not in self.param.isvarnames]
|
|
4406
4464
|
rand_vars, cor_vars = {}, []
|
|
4407
4465
|
|
|
4408
4466
|
if self.mae_is_an_objective():
|
|
@@ -4432,7 +4490,8 @@ class Search():
|
|
|
4432
4490
|
try:
|
|
4433
4491
|
model.setup(X=X, y=y, varnames=all_vars, alts=self.param.alt_var,
|
|
4434
4492
|
isvars=is_vars, ids=self.param.choice_id,
|
|
4435
|
-
randvars=rand_vars,
|
|
4493
|
+
randvars=rand_vars, transvars=bc_vars,
|
|
4494
|
+
panels=self.param.ind_id,
|
|
4436
4495
|
avail=self.param.avail, base_alt=self.param.base_alt,
|
|
4437
4496
|
maxiter=self.param.maxiter, ftol=self.param.ftol,
|
|
4438
4497
|
gtol=self.param.gtol)
|
|
@@ -4457,12 +4516,13 @@ class Search():
|
|
|
4457
4516
|
def evaluate_ordered_logit(self,sol):
|
|
4458
4517
|
|
|
4459
4518
|
as_vars, is_vars, asc_ind = sol['asvars'], sol['isvars'], sol['asc_ind']
|
|
4519
|
+
bc_vars = self.define_bc_vars(sol)
|
|
4520
|
+
bc_vars = [var for var in bc_vars if var not in self.param.isvarnames]
|
|
4460
4521
|
|
|
4461
4522
|
|
|
4462
4523
|
all_vars = as_vars + is_vars
|
|
4463
4524
|
|
|
4464
4525
|
all_vars = [var for var in self.param.varnames if var in all_vars]
|
|
4465
|
-
all_vars = all_vars
|
|
4466
4526
|
|
|
4467
4527
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
4468
4528
|
#df_long = misc.wide_to_long(self.param.df, id_col='id', alt_list=self.param.alt_var, alt_name='alt')
|
|
@@ -4470,13 +4530,13 @@ class Search():
|
|
|
4470
4530
|
#y = df_long['choice']
|
|
4471
4531
|
X, y = self.param.df[all_vars], self.param.choices
|
|
4472
4532
|
J = len(np.unique(self.param.alt_var))
|
|
4473
|
-
model = self.fit_ordered_logit(X=X, y=y, ids
|
|
4474
|
-
|
|
4533
|
+
model = self.fit_ordered_logit(X=X, y=y, ids=self.param.choice_id,
|
|
4534
|
+
varnames=all_vars, choices=J,
|
|
4535
|
+
transvars=bc_vars)
|
|
4536
|
+
sol['model'] = model
|
|
4475
4537
|
sol['coeff'] = model.coeff_est
|
|
4476
4538
|
converged = model.converged
|
|
4477
4539
|
aic, bic, loglik = model.aic, model.bic, model.loglik
|
|
4478
|
-
bc_vars = self.define_bc_vars(sol)
|
|
4479
|
-
bc_vars = [var for var in bc_vars if var not in self.param.isvarnames]
|
|
4480
4540
|
alts = self.param.alt_var
|
|
4481
4541
|
rand_vars, cor_vars = {}, []
|
|
4482
4542
|
|
|
@@ -4498,7 +4558,7 @@ class Search():
|
|
|
4498
4558
|
return tuple
|
|
4499
4559
|
|
|
4500
4560
|
|
|
4501
|
-
def fit_ordered_logit(self, X, y, ids, varnames, choices):
|
|
4561
|
+
def fit_ordered_logit(self, X, y, ids, varnames, choices, transvars=None):
|
|
4502
4562
|
|
|
4503
4563
|
|
|
4504
4564
|
moll = OrderedLogitLong(X=X.values,
|
|
@@ -4509,7 +4569,8 @@ class Search():
|
|
|
4509
4569
|
distr='logit',
|
|
4510
4570
|
start=None,
|
|
4511
4571
|
normalize=False,
|
|
4512
|
-
fit_intercept=False
|
|
4572
|
+
fit_intercept=False,
|
|
4573
|
+
transvars=transvars or [])
|
|
4513
4574
|
|
|
4514
4575
|
moll.fit(method='BFGS')
|
|
4515
4576
|
moll.report()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.0.131
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SearchLibrium
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.131
|
|
4
4
|
Summary: A Python package for econometric models driven by search
|
|
5
5
|
Author: Mario Fernando Taco Morales, Alexander Paz, Prithvi Beeramole, Robert Burdett
|
|
6
6
|
Author-email: Zeke Ahern <z.ahern@qut.edu.au>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.0.129
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium/test_sapbil_vs_banditsa.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{searchlibrium-0.0.129 → searchlibrium-0.0.131}/src/SearchLibrium.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|