-
Hi all, I was struggling with dealing with environment(RootPrimalSearch, but still some features are unclear for me. It would be thankful if anyone answer following questions.
Best, |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 2 replies
-
Dear @HanbumKo ,
The way the
Yes, you should be able to extract this information within your observation function, e.g., m = model.as_pyscipopt()
nsols = m.getNSols() # the number of primal solutions stored within SCIP
if nsols > 0:
bestsol = m.getBestSol() # best primal solution found by SCIP so far
bestsolvalue = m.getSolObjVal(bestsol) # solution objective value
From within your observation function, you can retrieve SCIP variables, their name and their index as follows: vars = m.getVars(self, transformed=True) # SCIP transformed variables
for var in vars:
print(f"var {var.getIndex()}: '{var.name}'") # variable index and name The environment expects primal solution in the transformed variable space, so pay attention to the You should mind though that in the m.writeProblem(filename='tranformed_problem.mps', trans=True, genericnames=False) and then inspect that file by loading it into PySCIPOpt with permutation deactivated (which should be the default). Hope this helps. Let me know if anything is still not clear. Best, |
Beta Was this translation helpful? Give feedback.
-
I got other questions too.
vars = m.getVars(self, transformed=True)
for var in vars:
print(var.getIndex(), end=" ") I can see index numbers range [1083, 2165], but action_set has range [0, 1049]. Then how to deal with this?
class RootPrimalSearch(ObjectiveLimitEnvironment):
__Dynamics__ = RootPrimalSearchDynamics
__DefaultInformationFunction__ = DefaultInformationFunction
env = RootPrimalSearch(observation_function=ecole.observation.NodeBipartite(), ...)
observation, action_set, reward_offset, done, information = env.reset(instance, ...)
print(observation.column_features.shape) # [1083, 19] its variable features has shape[1083, 19], and if I want to extract variable's features in action_set, for var_index in action_set:
print("variable index :", var_index, "has feature",observation.column_features[var_index, :]) Above script is correct? Best, |
Beta Was this translation helpful? Give feedback.
-
Dear @HanbumKo , Unfortunately there exists different ways to identify variables from index in SCIP, and all those at the moment cohabit in Ecole. We are aiming at improving this in future versions of Ecole (see this issue), but I'm afraid this won't happen while the competition is running. Here is the long explanation:
Short answer: index class ObservationFunction():
def __init__(self, problem):
# called once for each problem benchmark
self.nbp = ec.observation.NodeBipartite() # instanciate a nested observation function
self.problem = problem # to devise problem-specific observations
def seed(self, seed):
# called before each episode
# use this seed to make your code deterministic
pass
def before_reset(self, model):
# called when a new episode is about to start
self.nbp.before_reset(model) # reset the nested observation function
def extract(self, model, done):
obs = self.nbp.extract(model, done) # extract the nested observation
if done:
return None
m = model.as_pyscipopt()
# get variables from columns
lp_columns = m.getLPColsData()
lp_variables = [col.getVar() for col in lp_columns]
# or columns from variables
lp_variables_2 = [var for var in m.getVars(transformed=True) if var.isInLP()]
lp_columns_2 = [var.getCol() for var in lp_variables_2]
# both should be equivalent
assert all([var.ptr() in [var.ptr() for var in lp_variables] for var in lp_variables_2]) # we have to comapre pointers otherwise PySCIPOpt creates an equality expression
assert all([var.ptr() in [var.ptr() for var in lp_variables_2] for var in lp_variables])
assert all([col in lp_columns for col in lp_columns_2])
assert all([col in lp_columns_2 for col in lp_columns])
# extract the current LP solution value and the objective coefficient of each variable in the current LP
lp_var_lpsols = np.asarray([var.getLPSol() for var in lp_variables])
lp_var_objs = np.asarray([var.getObj() for var in lp_variables])
# extract the same information from the NodeBipartite observation
lp_column_indexes = np.asarray([col.getLPPos() for col in lp_columns])
assert obs.column_features.shape[0] == len(lp_column_indexes)
assert all([lp_idx >= 0 and lp_idx < obs.column_features.shape[0] for lp_idx in lp_column_indexes])
lp_var_lpsols_2 = obs.column_features[lp_column_indexes, int(obs.ColumnFeatures.solution_value)]
lp_var_objs_2 = obs.column_features[lp_column_indexes, int(obs.ColumnFeatures.objective)]
# both should be equivalent (up to the objective normalization in NodeBipartite)
obj_norm = 1 if np.linalg.norm(lp_var_objs) == 0 else np.linalg.norm(lp_var_objs)
assert all(lp_var_lpsols == lp_var_lpsols_2)
assert all([m.isEQ(o1 / obj_norm, o2) for o1, o2 in zip(lp_var_objs, lp_var_objs_2)])
raise Exception("Everything is ok")
observation = (lp_var_lpsols, lp_var_objs)
return observation Hope that helps. Best, |
Beta Was this translation helpful? Give feedback.
Dear @HanbumKo ,
Unfortunately there exists different ways to identify variables from index in SCIP, and all those at the moment cohabit in Ecole. We are aiming at improving this in future versions of Ecole (see this issue), but I'm afraid this won't happen while the competition is running.
Here is the long explanation:
SCIPvarGetIndex()
). This is called the original problem, and the original variables, which are created during the PROBLEM stage of SCIP (when an instance files is read).