Edit on GitHub

boundml.instances

 1from .ecole_instances import *
 2from .instances import *
 3from .miplib import *
 4from .folder_instances import *
 5
 6__all__ = [
 7    "Instances",
 8    "FolderInstances",
 9    "MipLibInstances",
10] + [
11    "CapacitatedFacilityLocationGenerator",
12    "CombinatorialAuctionGenerator",
13    "IndependentSetGenerator",
14    "SetCoverGenerator"
15] if HAS_ECOLE_FORK else []
class Instances(abc.ABC):
 7class Instances(ABC):
 8    """
 9    An Instances object is an iterator that yields pyscipopt.Model.
10    """
11    def __iter__(self):
12        return self
13
14    @abstractmethod
15    def __next__(self) -> Model:
16        raise NotImplementedError("Subclasses must implement this method.")

An Instances object is an iterator that yields pyscipopt.Model.

class FolderInstances(boundml.instances.Instances):
11class FolderInstances(Instances):
12    """
13    FolderInstances allows to iterate through the instances in a folder.
14    """
15    _archives_urls = {
16        "collection": "https://miplib.zib.de/downloads/collection.zip",
17        "benchmark": "https://miplib.zib.de/downloads/benchmark.zip"
18    }
19
20    def __init__(self, folder: str, filter: Callable[[str], bool] = lambda x: True):
21        """
22        Parameters
23        ----------
24        folder : str
25            Name of the folder containing the instances.
26        filter : Callable[[str], bool]
27            Filter instances based on their name to work only with a desired subset of instances
28        """
29        self._instances_dir = folder
30
31        self._instances_files = [name for name in os.listdir(self._instances_dir) if filter(name)]
32        self._instances_files.sort()
33        self._index = 0
34
35    def __next__(self):
36        if self._index >= len(self._instances_files):
37            raise StopIteration
38
39        path = os.path.join(self._instances_dir, self._instances_files[self._index])
40        model = Model()
41        model.setParam("display/verblevel", 0)
42        model.readProblem(path)
43        self._index += 1
44        return model
45
46    def seed(self, seed: int):
47        """
48        Shuffle the instances based on the given seed
49        Parameters
50        ----------
51        seed : int
52        """
53        random.Random(seed).shuffle(self._instances_files)
54        self._index = 0
55
56    def __len__(self):
57        return len(self._instances_files)

FolderInstances allows to iterate through the instances in a folder.

FolderInstances( folder: str, filter: Callable[[str], bool] = <function FolderInstances.<lambda>>)
20    def __init__(self, folder: str, filter: Callable[[str], bool] = lambda x: True):
21        """
22        Parameters
23        ----------
24        folder : str
25            Name of the folder containing the instances.
26        filter : Callable[[str], bool]
27            Filter instances based on their name to work only with a desired subset of instances
28        """
29        self._instances_dir = folder
30
31        self._instances_files = [name for name in os.listdir(self._instances_dir) if filter(name)]
32        self._instances_files.sort()
33        self._index = 0
Parameters
  • folder (str): Name of the folder containing the instances.
  • filter (Callable[[str], bool]): Filter instances based on their name to work only with a desired subset of instances
def seed(self, seed: int):
46    def seed(self, seed: int):
47        """
48        Shuffle the instances based on the given seed
49        Parameters
50        ----------
51        seed : int
52        """
53        random.Random(seed).shuffle(self._instances_files)
54        self._index = 0

Shuffle the instances based on the given seed

Parameters
  • seed (int):
class MipLibInstances(boundml.instances.FolderInstances):
 17class MipLibInstances(FolderInstances):
 18    """
 19    MipLibInstances allow to iterate through MipLib instances.
 20    It downloads archive files once and cache it as long with all the extracted instances.
 21    It is highly recommended to use the argument force_download and force_extract if the process is killed while
 22    performing one of these operations.
 23    By default, MipLibInstances iterates through the instances ordered by alphabetical order, a seed can be set to
 24    randomize the order.
 25    """
 26    _archives_urls = {
 27        "collection": "https://miplib.zib.de/downloads/collection.zip",
 28        "benchmark": "https://miplib.zib.de/downloads/benchmark.zip"
 29    }
 30
 31    def __init__(self, subset: str = "benchmark", force_download: bool = False, force_extract: bool = False,
 32                 filter: Callable[[str], bool] = lambda x: True):
 33        """
 34        Parameters
 35        ----------
 36        subset : str
 37            Name of the subset of instances to used, either "collection" or "benchmark"
 38        force_download : bool
 39            Force the download even if the file already exists.
 40        force_extract : bool
 41            Force the extraction even if the folder already exists.
 42        filter : Callable[[str], bool]
 43            Filter instances based on their name (name.mps) to work only with a desired subset of instances
 44        """
 45        # Create a cache directory specific to your library
 46        self._cache_dir = Path(user_cache_dir("boundml"))
 47        self._cache_dir.mkdir(parents=True, exist_ok=True)
 48        self._zip_file = self._cache_dir.joinpath(f"{subset}.zip")
 49        self._instances_dir = self._cache_dir.joinpath(f"{subset}")
 50
 51        if subset in MipLibInstances._archives_urls:
 52            url = MipLibInstances._archives_urls[subset]
 53        else:
 54            raise ValueError(f"Unknown subset: {subset}. Must be one of {MipLibInstances._archives_urls}")
 55
 56        self._download(url, force_download)
 57        self._extract(force_download or force_extract)
 58
 59        super().__init__(str(self._instances_dir), filter)
 60
 61    def _download(self, url: str, force: bool = False):
 62        if force or not self._zip_file.exists():
 63            resp = requests.get(url, stream=True)
 64            total = int(resp.headers.get('content-length', 0))
 65            with open(self._zip_file, 'wb') as file, tqdm(
 66                    desc=str("Downloading MIPLIB instances"),
 67                    total=total,
 68                    unit='iB',
 69                    unit_scale=True,
 70                    unit_divisor=1024,
 71            ) as bar:
 72                for data in resp.iter_content(chunk_size=1024):
 73                    size = file.write(data)
 74                    bar.update(size)
 75
 76    def _extract(self, force: bool = False):
 77        if force or not self._instances_dir.exists():
 78            if self._instances_dir.exists():
 79                shutil.rmtree(self._instances_dir)
 80
 81            print("Extracting collections.zip...")
 82            self._instances_dir.mkdir(exist_ok=True)
 83            with zipfile.ZipFile(self._zip_file, 'r') as zip_ref:
 84                zip_ref.extractall(self._instances_dir)
 85
 86            files = os.listdir(self._instances_dir)
 87            with tqdm(
 88                    desc=str("Extracting instances"),
 89                    total=len(files),
 90                    unit='it',
 91                    unit_scale=True,
 92                    unit_divisor=1,
 93            ) as bar:
 94                for file in files:
 95                    path = os.path.join(self._instances_dir, file)
 96                    dest_path = ".".join(path.split(".")[:-1])
 97                    with gzip.open(path, 'rb') as f_in:
 98                        with open(dest_path, 'wb') as f_out:
 99                            shutil.copyfileobj(f_in, f_out)
100                    os.remove(path)
101
102                    bar.update(1)

MipLibInstances allow to iterate through MipLib instances. It downloads archive files once and cache it as long with all the extracted instances. It is highly recommended to use the argument force_download and force_extract if the process is killed while performing one of these operations. By default, MipLibInstances iterates through the instances ordered by alphabetical order, a seed can be set to randomize the order.

MipLibInstances( subset: str = 'benchmark', force_download: bool = False, force_extract: bool = False, filter: Callable[[str], bool] = <function MipLibInstances.<lambda>>)
31    def __init__(self, subset: str = "benchmark", force_download: bool = False, force_extract: bool = False,
32                 filter: Callable[[str], bool] = lambda x: True):
33        """
34        Parameters
35        ----------
36        subset : str
37            Name of the subset of instances to used, either "collection" or "benchmark"
38        force_download : bool
39            Force the download even if the file already exists.
40        force_extract : bool
41            Force the extraction even if the folder already exists.
42        filter : Callable[[str], bool]
43            Filter instances based on their name (name.mps) to work only with a desired subset of instances
44        """
45        # Create a cache directory specific to your library
46        self._cache_dir = Path(user_cache_dir("boundml"))
47        self._cache_dir.mkdir(parents=True, exist_ok=True)
48        self._zip_file = self._cache_dir.joinpath(f"{subset}.zip")
49        self._instances_dir = self._cache_dir.joinpath(f"{subset}")
50
51        if subset in MipLibInstances._archives_urls:
52            url = MipLibInstances._archives_urls[subset]
53        else:
54            raise ValueError(f"Unknown subset: {subset}. Must be one of {MipLibInstances._archives_urls}")
55
56        self._download(url, force_download)
57        self._extract(force_download or force_extract)
58
59        super().__init__(str(self._instances_dir), filter)
Parameters
  • subset (str): Name of the subset of instances to used, either "collection" or "benchmark"
  • force_download (bool): Force the download even if the file already exists.
  • force_extract (bool): Force the extraction even if the folder already exists.
  • filter (Callable[[str], bool]): Filter instances based on their name (name.mps) to work only with a desired subset of instances
class CapacitatedFacilityLocationGenerator(boundml.instances.ecole_instances.EcoleInstances):
23class CapacitatedFacilityLocationGenerator(EcoleInstances):
24    def __init__(self, *args, **kwargs):
25        super().__init__(ecole.instance.CapacitatedFacilityLocationGenerator(*args, **kwargs))

An Instances object is an iterator that yields pyscipopt.Model.

CapacitatedFacilityLocationGenerator(*args, **kwargs)
24    def __init__(self, *args, **kwargs):
25        super().__init__(ecole.instance.CapacitatedFacilityLocationGenerator(*args, **kwargs))
class CombinatorialAuctionGenerator(boundml.instances.ecole_instances.EcoleInstances):
27class CombinatorialAuctionGenerator(EcoleInstances):
28    def __init__(self, *args, **kwargs):
29        super().__init__(ecole.instance.CombinatorialAuctionGenerator(*args, **kwargs))

An Instances object is an iterator that yields pyscipopt.Model.

CombinatorialAuctionGenerator(*args, **kwargs)
28    def __init__(self, *args, **kwargs):
29        super().__init__(ecole.instance.CombinatorialAuctionGenerator(*args, **kwargs))
class IndependentSetGenerator(boundml.instances.ecole_instances.EcoleInstances):
31class IndependentSetGenerator(EcoleInstances):
32    def __init__(self, *args, **kwargs):
33        super().__init__(ecole.instance.IndependentSetGenerator(*args, **kwargs))

An Instances object is an iterator that yields pyscipopt.Model.

IndependentSetGenerator(*args, **kwargs)
32    def __init__(self, *args, **kwargs):
33        super().__init__(ecole.instance.IndependentSetGenerator(*args, **kwargs))
class SetCoverGenerator(boundml.instances.ecole_instances.EcoleInstances):
35class SetCoverGenerator(EcoleInstances):
36    def __init__(self, *args, **kwargs):
37        super().__init__(ecole.instance.SetCoverGenerator(*args, **kwargs))

An Instances object is an iterator that yields pyscipopt.Model.

SetCoverGenerator(*args, **kwargs)
36    def __init__(self, *args, **kwargs):
37        super().__init__(ecole.instance.SetCoverGenerator(*args, **kwargs))