mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-09 02:48:52 -06:00
problems: Allow correlated arguments in random problem generators
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, Optional, Union, Callable
|
||||
|
||||
import gurobipy as gp
|
||||
import numpy as np
|
||||
@@ -47,8 +47,10 @@ class MultiKnapsackGenerator:
|
||||
----------
|
||||
n: rv_discrete
|
||||
Probability distribution for the number of items (or variables).
|
||||
m: rv_discrete
|
||||
Probability distribution for the number of knapsacks (or constraints).
|
||||
m: rv_discrete or callable
|
||||
Probability distribution for the number of knapsacks (or constraints), or a
|
||||
callable that takes the numer of items and returns the number of knapsacks
|
||||
(e.g., lambda n: n//3).
|
||||
w: rv_continuous
|
||||
Probability distribution for the item weights.
|
||||
K: rv_continuous
|
||||
@@ -65,7 +67,7 @@ class MultiKnapsackGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n: rv_frozen = randint(low=100, high=101),
|
||||
m: rv_frozen = randint(low=30, high=31),
|
||||
m: Union[rv_frozen, Callable] = randint(low=30, high=31),
|
||||
w: rv_frozen = randint(low=0, high=1000),
|
||||
K: rv_frozen = randint(low=500, high=501),
|
||||
u: rv_frozen = uniform(loc=0.0, scale=1.0),
|
||||
@@ -73,7 +75,9 @@ class MultiKnapsackGenerator:
|
||||
round: bool = True,
|
||||
):
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(m, rv_frozen), "m should be a SciPy probability distribution"
|
||||
assert isinstance(m, rv_frozen) or callable(
|
||||
m
|
||||
), "m should be a SciPy probability distribution or callable"
|
||||
assert isinstance(w, rv_frozen), "w should be a SciPy probability distribution"
|
||||
assert isinstance(K, rv_frozen), "K should be a SciPy probability distribution"
|
||||
assert isinstance(u, rv_frozen), "u should be a SciPy probability distribution"
|
||||
@@ -92,7 +96,10 @@ class MultiKnapsackGenerator:
|
||||
def generate(self, n_samples: int) -> List[MultiKnapsackData]:
|
||||
def _sample() -> MultiKnapsackData:
|
||||
n = self.n.rvs()
|
||||
m = self.m.rvs()
|
||||
if callable(self.m):
|
||||
m = self.m(n)
|
||||
else:
|
||||
m = self.m.rvs()
|
||||
w = np.array([self.w.rvs(n) for _ in range(m)])
|
||||
u = self.u.rvs(n)
|
||||
K = self.K.rvs()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, Optional, Union, Callable
|
||||
|
||||
import gurobipy as gp
|
||||
import numpy as np
|
||||
@@ -58,7 +58,8 @@ class PMedianGenerator:
|
||||
n
|
||||
Probability distribution for the number of customer.
|
||||
p
|
||||
Probability distribution for the number of medians.
|
||||
Probability distribution for the number of medians, or a callable that takes
|
||||
the number of customers and returns the number of medians (e.g., lambda n: n//10).
|
||||
demands
|
||||
Probability distribution for the customer demands.
|
||||
capacities
|
||||
@@ -70,10 +71,23 @@ class PMedianGenerator:
|
||||
x: rv_frozen = uniform(loc=0.0, scale=100.0),
|
||||
y: rv_frozen = uniform(loc=0.0, scale=100.0),
|
||||
n: rv_frozen = randint(low=100, high=101),
|
||||
p: rv_frozen = randint(low=10, high=11),
|
||||
p: Union[rv_frozen, Callable] = randint(low=10, high=11),
|
||||
demands: rv_frozen = uniform(loc=0, scale=20),
|
||||
capacities: rv_frozen = uniform(loc=0, scale=100),
|
||||
):
|
||||
assert isinstance(x, rv_frozen), "x should be a SciPy probability distribution"
|
||||
assert isinstance(y, rv_frozen), "y should be a SciPy probability distribution"
|
||||
assert isinstance(n, rv_frozen), "n should be a SciPy probability distribution"
|
||||
assert isinstance(p, rv_frozen) or callable(
|
||||
p
|
||||
), "p should be a SciPy probability distribution or callable"
|
||||
assert isinstance(
|
||||
demands, rv_frozen
|
||||
), "demands should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
capacities, rv_frozen
|
||||
), "capacities should be a SciPy probability distribution"
|
||||
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.n = n
|
||||
@@ -84,7 +98,10 @@ class PMedianGenerator:
|
||||
def generate(self, n_samples: int) -> List[PMedianData]:
|
||||
def _sample() -> PMedianData:
|
||||
n = self.n.rvs()
|
||||
p = self.p.rvs()
|
||||
if callable(self.p):
|
||||
p = self.p(n)
|
||||
else:
|
||||
p = self.p.rvs()
|
||||
loc = np.array([(self.x.rvs(), self.y.rvs()) for _ in range(n)])
|
||||
distances = squareform(pdist(loc))
|
||||
demands = self.demands.rvs(n)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Union
|
||||
from typing import List, Union, Callable
|
||||
|
||||
import gurobipy as gp
|
||||
import numpy as np
|
||||
@@ -34,7 +34,7 @@ class SetCoverGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n_elements: rv_frozen = randint(low=50, high=51),
|
||||
n_sets: rv_frozen = randint(low=100, high=101),
|
||||
n_sets: Union[rv_frozen, Callable] = randint(low=100, high=101),
|
||||
costs: rv_frozen = uniform(loc=0.0, scale=100.0),
|
||||
K: rv_frozen = uniform(loc=25.0, scale=0.0),
|
||||
density: rv_frozen = uniform(loc=0.02, scale=0.00),
|
||||
@@ -45,8 +45,9 @@ class SetCoverGenerator:
|
||||
----------
|
||||
n_elements: rv_discrete
|
||||
Probability distribution for number of elements.
|
||||
n_sets: rv_discrete
|
||||
Probability distribution for number of sets.
|
||||
n_sets: rv_discrete or callable
|
||||
Probability distribution for number of sets, or a callable that takes
|
||||
the number of elements and returns the number of sets.
|
||||
costs: rv_continuous
|
||||
Probability distribution for base set costs.
|
||||
K: rv_continuous
|
||||
@@ -57,9 +58,9 @@ class SetCoverGenerator:
|
||||
assert isinstance(
|
||||
n_elements, rv_frozen
|
||||
), "n_elements should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
n_sets, rv_frozen
|
||||
), "n_sets should be a SciPy probability distribution"
|
||||
assert isinstance(n_sets, rv_frozen) or callable(
|
||||
n_sets
|
||||
), "n_sets should be a SciPy probability distribution or callable"
|
||||
assert isinstance(
|
||||
costs, rv_frozen
|
||||
), "costs should be a SciPy probability distribution"
|
||||
@@ -75,8 +76,11 @@ class SetCoverGenerator:
|
||||
|
||||
def generate(self, n_samples: int) -> List[SetCoverData]:
|
||||
def _sample() -> SetCoverData:
|
||||
n_sets = self.n_sets.rvs()
|
||||
n_elements = self.n_elements.rvs()
|
||||
if callable(self.n_sets):
|
||||
n_sets = self.n_sets(n_elements)
|
||||
else:
|
||||
n_sets = self.n_sets.rvs()
|
||||
density = self.density.rvs()
|
||||
|
||||
incidence_matrix = np.random.rand(n_elements, n_sets) < density
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Union
|
||||
from typing import List, Union, Callable
|
||||
|
||||
import gurobipy as gp
|
||||
import numpy as np
|
||||
@@ -33,7 +33,7 @@ class SetPackGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n_elements: rv_frozen = randint(low=50, high=51),
|
||||
n_sets: rv_frozen = randint(low=100, high=101),
|
||||
n_sets: Union[rv_frozen, Callable] = randint(low=100, high=101),
|
||||
costs: rv_frozen = uniform(loc=0.0, scale=100.0),
|
||||
K: rv_frozen = uniform(loc=25.0, scale=0.0),
|
||||
density: rv_frozen = uniform(loc=0.02, scale=0.00),
|
||||
@@ -44,8 +44,9 @@ class SetPackGenerator:
|
||||
----------
|
||||
n_elements: rv_discrete
|
||||
Probability distribution for number of elements.
|
||||
n_sets: rv_discrete
|
||||
Probability distribution for number of sets.
|
||||
n_sets: rv_discrete or callable
|
||||
Probability distribution for number of sets, or a callable that takes
|
||||
the number of elements and returns the number of sets.
|
||||
costs: rv_continuous
|
||||
Probability distribution for base set costs.
|
||||
K: rv_continuous
|
||||
@@ -56,9 +57,9 @@ class SetPackGenerator:
|
||||
assert isinstance(
|
||||
n_elements, rv_frozen
|
||||
), "n_elements should be a SciPy probability distribution"
|
||||
assert isinstance(
|
||||
n_sets, rv_frozen
|
||||
), "n_sets should be a SciPy probability distribution"
|
||||
assert isinstance(n_sets, rv_frozen) or callable(
|
||||
n_sets
|
||||
), "n_sets should be a SciPy probability distribution or callable"
|
||||
assert isinstance(
|
||||
costs, rv_frozen
|
||||
), "costs should be a SciPy probability distribution"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from math import pi
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, Optional, Union, Callable
|
||||
|
||||
import gurobipy as gp
|
||||
import numpy as np
|
||||
@@ -39,7 +39,7 @@ class UnitCommitmentGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
n_units: rv_frozen = randint(low=1_000, high=1_001),
|
||||
n_periods: rv_frozen = randint(low=72, high=73),
|
||||
n_periods: Union[rv_frozen, Callable] = randint(low=72, high=73),
|
||||
max_power: rv_frozen = uniform(loc=50, scale=450),
|
||||
min_power: rv_frozen = uniform(loc=0.5, scale=0.25),
|
||||
cost_startup: rv_frozen = uniform(loc=0, scale=10_000),
|
||||
@@ -55,8 +55,9 @@ class UnitCommitmentGenerator:
|
||||
----------
|
||||
n_units: rv_frozen
|
||||
Probability distribution for number of units.
|
||||
n_periods: rv_frozen
|
||||
Probability distribution for number of periods.
|
||||
n_periods: rv_frozen or callable
|
||||
Probability distribution for number of periods, or a callable that takes
|
||||
the number of units and returns the number of periods.
|
||||
max_power: rv_frozen
|
||||
Probability distribution for maximum power output.
|
||||
min_power: rv_frozen
|
||||
@@ -74,6 +75,12 @@ class UnitCommitmentGenerator:
|
||||
min_downtime: rv_frozen
|
||||
Probability distribution for minimum downtime.
|
||||
"""
|
||||
assert isinstance(
|
||||
n_units, rv_frozen
|
||||
), "n_units should be a SciPy probability distribution"
|
||||
assert isinstance(n_periods, rv_frozen) or callable(
|
||||
n_periods
|
||||
), "n_periods should be a SciPy probability distribution or callable"
|
||||
self.n_units = n_units
|
||||
self.n_periods = n_periods
|
||||
self.max_power = max_power
|
||||
@@ -87,8 +94,11 @@ class UnitCommitmentGenerator:
|
||||
|
||||
def generate(self, n_samples: int) -> List[UnitCommitmentData]:
|
||||
def _sample() -> UnitCommitmentData:
|
||||
T = self.n_periods.rvs()
|
||||
G = self.n_units.rvs()
|
||||
if callable(self.n_periods):
|
||||
T = self.n_periods(G)
|
||||
else:
|
||||
T = self.n_periods.rvs()
|
||||
|
||||
# Generate unit parameteres
|
||||
max_power = self.max_power.rvs(G)
|
||||
|
||||
Reference in New Issue
Block a user