Пример #1
0
    def branchexeclp(self, allowaddcons):

        candidate_vars, *_ = self.model.getPseudoBranchCands()
        candidate_mask = [var.getCol().getIndex() for var in candidate_vars]

        state = utilities.extract_state(self.model, self.state_buffer)
        c, e, v = state
        v = v['values'][candidate_mask]

        state_khalil = utilities.extract_khalil_variable_features(self.model, candidate_vars, self.khalil_root_buffer)

        var_feats = np.concatenate([v, state_khalil, np.ones((v.shape[0],1))], axis=1)
        var_feats = utilities._preprocess(var_feats, mode="min-max-2")
        # TODO: Move to(device) inside as_tensor()
        var_feats = torch.as_tensor(var_feats, dtype=torch.float32).to(device)
        
        with torch.no_grad():
            # TODO: drop .cpu().numpy() for faster running time?
            var_logits = self.policy(var_feats).cpu().numpy()

        best_var = candidate_vars[var_logits.argmax()]
        self.model.branchVar(best_var)
        result = scip.SCIP_RESULT.BRANCHED

        # fair node counting
        if result == scip.SCIP_RESULT.REDUCEDDOM:
            self.ndomchgs += 1
        elif result == scip.SCIP_RESULT.CUTOFF:
            self.ncutoffs += 1

        return {'result': result}
Пример #2
0
    def branchexeclp(self, allowaddcons):

        candidate_vars, *_ = self.model.getPseudoBranchCands()
        candidate_mask = [var.getCol().getIndex() for var in candidate_vars]
        state = utilities.extract_state(self.model, self.state_buffer)
        c, e, v = state
        if self.model.getNNodes() == 1:
            state = (
                torch.as_tensor(c['values'], dtype=torch.float32),
                torch.as_tensor(e['indices'], dtype=torch.long),
                torch.as_tensor(e['values'], dtype=torch.float32),
                torch.as_tensor(v['values'], dtype=torch.float32),
                torch.as_tensor(c['values'].shape[0], dtype=torch.int32),
                torch.as_tensor(v['values'].shape[0], dtype=torch.int32),
            )
            state = map(lambda x: x.to(self.device), state)
            with torch.no_grad():
                if self.teacher is not None:
                    root_feats, _ = self.teacher(state)
                    state = root_feats
                self.root_params = self.policy_get_root_params(state)

        v = v['values'][candidate_mask]
        state_khalil = utilities.extract_khalil_variable_features(
            self.model, candidate_vars, self.khalil_root_buffer)

        var_feats = np.concatenate(
            [v, state_khalil, np.ones((v.shape[0], 1))], axis=1)
        var_feats = utilities._preprocess(var_feats, mode="min-max-2")
        var_feats = torch.as_tensor(var_feats, dtype=torch.float32).to(device)

        with torch.no_grad():
            var_logits = self.policy_predict(
                var_feats, self.root_params[candidate_mask]).cpu().numpy()

        best_var = candidate_vars[var_logits.argmax()]
        self.model.branchVar(best_var)
        result = scip.SCIP_RESULT.BRANCHED

        # fair node counting
        if result == scip.SCIP_RESULT.REDUCEDDOM:
            self.ndomchgs += 1
        elif result == scip.SCIP_RESULT.CUTOFF:
            self.ncutoffs += 1

        return {'result': result}
Пример #3
0
    def branchexeclp(self, allowaddcons):

        # SCIP internal branching rule
        if self.policy_type == 'internal':
            result = self.model.executeBranchRule(self.policy, allowaddcons)

        # custom policy branching
        else:
            candidate_vars, *_ = self.model.getPseudoBranchCands()
            candidate_mask = [
                var.getCol().getIndex() for var in candidate_vars
            ]

            state = utilities.extract_state(self.model, self.state_buffer)
            c, e, v = state
            state = (
                torch.as_tensor(c['values'], dtype=torch.float32),
                torch.as_tensor(e['indices'], dtype=torch.long),
                torch.as_tensor(e['values'], dtype=torch.float32),
                torch.as_tensor(v['values'], dtype=torch.float32),
                torch.as_tensor(c['values'].shape[0], dtype=torch.int32),
                torch.as_tensor(v['values'].shape[0], dtype=torch.int32),
            )

            state = map(lambda x: x.to(self.device), state)
            with torch.no_grad():
                _, var_logits = self.policy(state)
                var_logits = torch.squeeze(var_logits, 0).cpu().numpy()

            candidate_scores = var_logits[candidate_mask]
            best_var = candidate_vars[candidate_scores.argmax()]

            self.model.branchVar(best_var)
            result = scip.SCIP_RESULT.BRANCHED

        # fair node counting
        if result == scip.SCIP_RESULT.REDUCEDDOM:
            self.ndomchgs += 1
        elif result == scip.SCIP_RESULT.CUTOFF:
            self.ncutoffs += 1

        return {'result': result}
Пример #4
0
    def branchexeclp(self, allowaddcons):
        self.iteration_counter += 1

        query_expert = self.rng.rand() < self.query_expert_prob
        if query_expert or self.model.getNNodes() == 1:
            candidate_vars, *_ = self.model.getPseudoBranchCands()
            candidate_mask = [
                var.getCol().getLPPos() for var in candidate_vars
            ]

            state = utilities.extract_state(self.model)
            state_khalil = utilities.extract_khalil_variable_features(
                self.model, candidate_vars, self.khalil_root_buffer)

            result = self.model.executeBranchRule('vanillafullstrong',
                                                  allowaddcons)
            cands_, scores, npriocands, bestcand = self.model.getVanillafullstrongData(
            )
            best_var = cands_[bestcand]

            self.add_obs(best_var, (state, state_khalil), (cands_, scores))
            if self.model.getNNodes() == 1:
                self.state = [state, state_khalil, self.obss[0]]

            self.model.branchVar(best_var)
            result = scip.SCIP_RESULT.BRANCHED
        else:
            result = self.model.executeBranchRule(self.exploration_policy,
                                                  allowaddcons)

        # fair node counting
        if result == scip.SCIP_RESULT.REDUCEDDOM:
            self.ndomchgs += 1
        elif result == scip.SCIP_RESULT.CUTOFF:
            self.ncutoffs += 1

        return {'result': result}
Пример #5
0
    def branchexeclp(self, allowaddcons):

        # SCIP internal branching rule
        if self.policy_type == 'internal':
            result = self.model.executeBranchRule(self.policy, allowaddcons)

        # custom policy branching
        else:
            candidate_vars, *_ = self.model.getPseudoBranchCands()
            candidate_mask = [
                var.getCol().getLPPos() for var in candidate_vars
            ]

            # initialize root buffer for Khalil features extraction
            if self.model.getNNodes() == 1 \
                    and self.policy_type == 'ml-competitor' \
                    and self.feat_specs['type'] in ('khalil', 'all'):
                utilities.extract_khalil_variable_features(
                    self.model, [], self.khalil_root_buffer)

            if len(candidate_vars) == 1:
                best_var = candidate_vars[0]

            elif self.policy_type == 'gcnn':
                state = utilities.extract_state(self.model, self.state_buffer)

                # convert state to tensors
                c, e, v = state
                state = (
                    tf.convert_to_tensor(c['values'], dtype=tf.float32),
                    tf.convert_to_tensor(e['indices'], dtype=tf.int32),
                    tf.convert_to_tensor(e['values'], dtype=tf.float32),
                    tf.convert_to_tensor(v['values'], dtype=tf.float32),
                    tf.convert_to_tensor([c['values'].shape[0]],
                                         dtype=tf.int32),
                    tf.convert_to_tensor([v['values'].shape[0]],
                                         dtype=tf.int32),
                )

                var_logits = self.policy(
                    state, tf.convert_to_tensor(False)).numpy().squeeze(0)

                candidate_scores = var_logits[candidate_mask]
                best_var = candidate_vars[candidate_scores.argmax()]

            elif self.policy_type == 'ml-competitor':

                # build candidate features
                candidate_states = []
                if self.feat_specs['type'] in ('all', 'gcnn_agg'):
                    state = utilities.extract_state(self.model,
                                                    self.state_buffer)
                    candidate_states.append(
                        utilities.compute_extended_variable_features(
                            state, candidate_mask))
                if self.feat_specs['type'] in ('all', 'khalil'):
                    candidate_states.append(
                        utilities.extract_khalil_variable_features(
                            self.model, candidate_vars,
                            self.khalil_root_buffer))
                candidate_states = np.concatenate(candidate_states, axis=1)

                # feature preprocessing
                candidate_states = utilities.preprocess_variable_features(
                    candidate_states, self.feat_specs['augment'],
                    self.feat_specs['qbnorm'])

                # feature normalization
                candidate_states = (candidate_states -
                                    self.feat_shift) / self.feat_scale

                candidate_scores = self.policy.predict(candidate_states)
                best_var = candidate_vars[candidate_scores.argmax()]

            else:
                raise NotImplementedError

            self.model.branchVar(best_var)
            result = scip.SCIP_RESULT.BRANCHED

        # fair node counting
        if result == scip.SCIP_RESULT.REDUCEDDOM:
            self.ndomchgs += 1
        elif result == scip.SCIP_RESULT.CUTOFF:
            self.ncutoffs += 1

        return {'result': result}
Пример #6
0
    def branchexeclp(self, allowaddcons):

        if self.model.getNNodes() == 1:
            # initialize root buffer for Khalil features extraction
            utilities.extract_khalil_variable_features(self.model, [], self.khalil_root_buffer)

        # once in a while, also run the expert policy and record the (state, action) pair
        query_expert = self.rng.rand() < self.query_expert_prob
        if query_expert:
            state = utilities.extract_state(self.model)
            cands, *_ = self.model.getPseudoBranchCands()
            state_khalil = utilities.extract_khalil_variable_features(self.model, cands, self.khalil_root_buffer)

            result = self.model.executeBranchRule('vanillafullstrong', allowaddcons)
            cands_, scores, npriocands, bestcand = self.model.getVanillafullstrongData()

            assert result == scip.SCIP_RESULT.DIDNOTRUN
            assert all([c1.getCol().getLPPos() == c2.getCol().getLPPos() for c1, c2 in zip(cands, cands_)])

            action_set = [c.getCol().getLPPos() for c in cands]
            expert_action = action_set[bestcand]

            data = [state, state_khalil, expert_action, action_set, scores]

            # Do not record inconsistent scores. May happen if SCIP was early stopped (time limit).
            if not any([s < 0 for s in scores]):

                filename = f'{self.out_dir}/sample_{self.episode}_{self.sample_counter}.pkl'
                with gzip.open(filename, 'wb') as f:
                    pickle.dump({
                        'episode': self.episode,
                        'instance': self.instance,
                        'seed': self.seed,
                        'node_number': self.model.getCurrentNode().getNumber(),
                        'node_depth': self.model.getCurrentNode().getDepth(),
                        'data': data,
                        }, f)

                self.out_queue.put({
                    'type': 'sample',
                    'episode': self.episode,
                    'instance': self.instance,
                    'seed': self.seed,
                    'node_number': self.model.getCurrentNode().getNumber(),
                    'node_depth': self.model.getCurrentNode().getDepth(),
                    'filename': filename,
                })

                self.sample_counter += 1

        # if exploration and expert policies are the same, prevent running it twice
        if not query_expert or (not self.follow_expert and self.exploration_policy != 'vanillafullstrong'):
            result = self.model.executeBranchRule(self.exploration_policy, allowaddcons)

        # apply 'vanillafullstrong' branching decision if needed
        if query_expert and self.follow_expert or self.exploration_policy == 'vanillafullstrong':
            assert result == scip.SCIP_RESULT.DIDNOTRUN
            cands, scores, npriocands, bestcand = self.model.getVanillafullstrongData()
            self.model.branchVar(cands[bestcand])
            result = scip.SCIP_RESULT.BRANCHED

        return {"result": result}
Пример #7
0
    def branchexeclp(self, allowaddcons):

        if self.model.getNNodes() == 1:
            # initialize root buffer for Khalil features extraction
            utilities.extract_khalil_variable_features(self.model, [], self.khalil_root_buffer)

        depth = self.model.getDepth()
        if self.visited_maxDepth < depth:
            self.visited_maxDepth = depth

        # once in a while, also run the expert policy and record the (state, action) pair
        # if not self.sampleForTraining: # if generating valid set or test set
        #     query_expert = (self.rng.random() < self.query_expert_prob)
        # else:
        with self.lock:
            if depth not in self.depthDict_accessTimes:
                self.depthDict_accessTimes[depth] = 1
            else:
                self.depthDict_accessTimes[depth] += 1

        if self.samplingStrategy == 'uniform5': # validation 和 test set 都用 uniform5
            query_expert = (self.rng.random() < self.query_expert_prob)
        elif self.samplingStrategy == 'depthK':
            query_expert = (self.rng.random() < self.query_expert_prob) or ((depth < self.depthK) and (self.model.getNNodes() <= self.NNodeK))
        elif self.samplingStrategy == 'depthK2':
            # 要通过读取depthTable来计算采样概率
            with self.lock:
                if depth not in self.depthDict_sampleTimes.keys():
                    query_expert = True
                else:
                    valSum = sum(self.depthDict_sampleTimes.values())
                    scores = {k:valSum/v for k,v in self.depthDict_sampleTimes.items()}
                    query_expert_prob = scores[depth] / sum(scores.values())
                    query_expert = (self.rng.random() < query_expert_prob)
        elif self.samplingStrategy == 'depthK3':
            # 给采样概率增加上下界
            with self.lock:
                if depth not in self.depthDict_sampleTimes:
                    query_expert_prob = 0.5
                else:
                    valSum = sum(self.depthDict_sampleTimes.values())
                    scores = {k:valSum/v for k,v in self.depthDict_sampleTimes.items()}
                    query_expert_prob = scores[depth] / sum(scores.values())
                    query_expert_prob = min(max(0.05, query_expert_prob), 0.5)
                query_expert = (self.rng.random() < query_expert_prob)
        elif self.samplingStrategy == 'depthK_adaptive':            
            bin_size = 5
            depth_binned = depth // bin_size

            query_expert_prob = self.query_expert_prob
            if (depth_binned in self.depthTable_SolSB_binned5.index) and (self.depthTable_SolSB_binned5.loc[depth_binned].item() > self.query_expert_prob):
                query_expert_prob = self.depthTable_SolSB_binned5.loc[depth_binned].item()
            query_expert = (self.rng.random() < query_expert_prob)
        elif self.samplingStrategy == 'depthK_adaptive2': 
            query_expert_prob = self.query_expert_prob
            if depth >= 5 and depth < 20:
                query_expert_prob = 0.13
            query_expert = (self.rng.random() < query_expert_prob)
        else:
            raise ValueError("Argument samplingStrategy can only be chosen from ['uniform5', 'depthK', 'depthK2', 'depthK3', 'depthK_adaptive]")

        if query_expert:
            # global lck, depthTable
            if self.sampleForTraining:
                with self.lock:
                    if depth not in self.depthDict_sampleTimes:
                        self.depthDict_sampleTimes[depth] = 1
                    else:
                        self.depthDict_sampleTimes[depth] += 1

            state = utilities.extract_state(self.model)
            cands, *_ = self.model.getPseudoBranchCands()
            state_khalil = utilities.extract_khalil_variable_features(self.model, cands, self.khalil_root_buffer)

            result = self.model.executeBranchRule('vanillafullstrong', allowaddcons)
            cands_, scores, npriocands, bestcand = self.model.getVanillafullstrongData()


            assert result == scip.SCIP_RESULT.DIDNOTRUN
            assert all([c1.getCol().getLPPos() == c2.getCol().getLPPos() for c1, c2 in zip(cands, cands_)])

            action_set = [c.getCol().getLPPos() for c in cands]
            expert_action = action_set[bestcand]

            data = [state, state_khalil, expert_action, action_set, scores]

            # Do not record inconsistent scores. May happen if SCIP was early stopped (time limit).
            if not any([s < 0 for s in scores]):

                filename = f'{self.out_dir}/sample_{self.episode}_{self.sample_counter}.pkl'
                with gzip.open(filename, 'wb') as f:
                    pickle.dump({
                        'episode': self.episode,
                        'instance': self.instance,
                        'seed': self.seed,
                        'node_number': self.model.getCurrentNode().getNumber(),
                        'node_depth': self.model.getCurrentNode().getDepth(),
                        'data': data,
                        }, f)

                self.out_queue.put({
                    'type': 'sample',
                    'episode': self.episode,
                    'instance': self.instance,
                    'seed': self.seed,
                    'node_number': self.model.getCurrentNode().getNumber(),
                    'node_depth': self.model.getCurrentNode().getDepth(),
                    'filename': filename,
                })

                self.sample_counter += 1

        # if exploration and expert policies are the same, prevent running it twice
        if not query_expert or (not self.follow_expert and self.exploration_policy != 'vanillafullstrong'):
            result = self.model.executeBranchRule(self.exploration_policy, allowaddcons)

        # apply 'vanillafullstrong' branching decision if needed
        if query_expert and self.follow_expert or self.exploration_policy == 'vanillafullstrong':
            assert result == scip.SCIP_RESULT.DIDNOTRUN
            cands, scores, npriocands, bestcand = self.model.getVanillafullstrongData()
            self.model.branchVar(cands[bestcand])
            result = scip.SCIP_RESULT.BRANCHED

        return {"result": result}