Compare commits

..

No commits in common. '596f41c47742ef5988c1d7453a8acf48b633faaf' and 'daa801b5e9a21455a81852c9e1d3bd75876aa798' have entirely different histories.

@ -33,7 +33,6 @@ class BasicCollector:
try: try:
h5_filename = _to_h5_filename(data_filename) h5_filename = _to_h5_filename(data_filename)
mps_filename = h5_filename.replace(".h5", ".mps") mps_filename = h5_filename.replace(".h5", ".mps")
log_filename = h5_filename.replace(".h5", ".h5.log")
if exists(h5_filename): if exists(h5_filename):
# Try to read optimal solution # Try to read optimal solution
@ -51,7 +50,6 @@ class BasicCollector:
return return
with H5File(h5_filename, "w") as h5: with H5File(h5_filename, "w") as h5:
h5.put_scalar("data_filename", data_filename)
streams: List[Any] = [StringIO()] streams: List[Any] = [StringIO()]
if verbose: if verbose:
streams += [sys.stdout] streams += [sys.stdout]
@ -78,10 +76,7 @@ class BasicCollector:
model.write(mps_filename) model.write(mps_filename)
gzip(mps_filename) gzip(mps_filename)
log = streams[0].getvalue() h5.put_scalar("mip_log", streams[0].getvalue())
h5.put_scalar("mip_log", log)
with open(log_filename, "w") as log_file:
log_file.write(log)
except: except:
print(f"Error processing: data_filename") print(f"Error processing: data_filename")
traceback.print_exc() traceback.print_exc()

@ -28,21 +28,21 @@ class MaxCutGenerator:
""" """
Random instance generator for the Maximum Cut Problem. Random instance generator for the Maximum Cut Problem.
The generator operates in two modes. When `fix_graph=True`, a single random Erdős-Rényi graph $G_{n, The generator operates in two modes. When `fix_graph=True`, a single random
p}$ is generated during initialization, with parameters $n$ and $p$ drawn from their respective probability Erdős-Rényi graph $G_{n,p}$ is generated during initialization, with parameters $n$
distributions, and each edge is assigned a random weight drawn from the set {-1, 1}, with equal probability. To and $p$ drawn from their respective probability distributions. For each instance,
generate each instance variation, the generator randomly flips the sign of each edge weight with probability only edge weights are randomly sampled from the set {1, -1}, while the graph
`w_jitter`. The graph remains the same across all variations. structure remains fixed.
When `fix_graph=False`, a new random graph is generated for each instance, with random {-1,1} edge weights. When `fix_graph=False`, both the graph structure and edge weights are randomly
generated for each instance.
""" """
def __init__( def __init__(
self, self,
n: rv_frozen, n: rv_frozen,
p: rv_frozen, p: rv_frozen,
w_jitter: float = 0.0, fix_graph: bool,
fix_graph: bool = False,
): ):
""" """
Initialize the problem generator. Initialize the problem generator.
@ -53,8 +53,6 @@ class MaxCutGenerator:
Probability distribution for the number of nodes. Probability distribution for the number of nodes.
p: rv_continuous p: rv_continuous
Probability distribution for the graph density. Probability distribution for the graph density.
w_jitter: float
Probability that each edge weight flips from -1 to 1. Only applicable if fix_graph is True.
fix_graph: bool fix_graph: bool
Controls graph generation for instances. If false, a new random graph is Controls graph generation for instances. If false, a new random graph is
generated for each instance. If true, the same graph is reused across instances. generated for each instance. If true, the same graph is reused across instances.
@ -63,24 +61,19 @@ class MaxCutGenerator:
assert isinstance(p, rv_frozen), "p should be a SciPy probability distribution" assert isinstance(p, rv_frozen), "p should be a SciPy probability distribution"
self.n = n self.n = n
self.p = p self.p = p
self.w_jitter = w_jitter
self.fix_graph = fix_graph self.fix_graph = fix_graph
self.graph = None self.graph = None
self.weights = None
if fix_graph: if fix_graph:
self.graph = self._generate_graph() self.graph = self._generate_graph()
self.weights = self._generate_weights(self.graph)
def generate(self, n_samples: int) -> List[MaxCutData]: def generate(self, n_samples: int) -> List[MaxCutData]:
def _sample() -> MaxCutData: def _sample() -> MaxCutData:
if self.graph is not None: if self.graph is not None:
graph = self.graph graph = self.graph
weights = self.weights
jitter = self._generate_jitter(graph)
weights = weights * jitter
else: else:
graph = self._generate_graph() graph = self._generate_graph()
weights = self._generate_weights(graph) m = graph.number_of_edges()
weights = np.random.randint(2, size=(m,)) * 2 - 1
return MaxCutData(graph, weights) return MaxCutData(graph, weights)
return [_sample() for _ in range(n_samples)] return [_sample() for _ in range(n_samples)]
@ -88,15 +81,6 @@ class MaxCutGenerator:
def _generate_graph(self) -> Graph: def _generate_graph(self) -> Graph:
return nx.generators.random_graphs.binomial_graph(self.n.rvs(), self.p.rvs()) return nx.generators.random_graphs.binomial_graph(self.n.rvs(), self.p.rvs())
@staticmethod
def _generate_weights(graph: Graph) -> np.ndarray:
m = graph.number_of_edges()
return np.random.randint(2, size=(m,)) * 2 - 1
def _generate_jitter(self, graph: Graph) -> np.ndarray:
m = graph.number_of_edges()
return (np.random.rand(m) >= self.w_jitter).astype(int) * 2 - 1
def build_maxcut_model_gurobipy( def build_maxcut_model_gurobipy(
data: Union[str, MaxCutData], data: Union[str, MaxCutData],

@ -52,13 +52,21 @@ def test_maxcut_generator_fixed() -> None:
n=randint(low=5, high=6), n=randint(low=5, high=6),
p=uniform(loc=0.5, scale=0.0), p=uniform(loc=0.5, scale=0.0),
fix_graph=True, fix_graph=True,
w_jitter=0.25,
) )
data = gen.generate(3) data = gen.generate(3)
assert len(data) == 3 assert len(data) == 3
for i in range(3): assert list(data[0].graph.nodes()) == [0, 1, 2, 3, 4]
assert list(data[i].graph.nodes()) == [0, 1, 2, 3, 4] assert list(data[0].graph.edges()) == [
assert list(data[i].graph.edges()) == [ (0, 2),
(0, 3),
(0, 4),
(2, 3),
(2, 4),
(3, 4),
]
assert data[0].weights.tolist() == [-1, 1, -1, -1, -1, 1]
assert list(data[1].graph.nodes()) == [0, 1, 2, 3, 4]
assert list(data[1].graph.edges()) == [
(0, 2), (0, 2),
(0, 3), (0, 3),
(0, 4), (0, 4),
@ -66,9 +74,7 @@ def test_maxcut_generator_fixed() -> None:
(2, 4), (2, 4),
(3, 4), (3, 4),
] ]
assert data[0].weights.tolist() == [-1, -1, 1, 1, -1, 1] assert data[1].weights.tolist() == [-1, -1, -1, 1, -1, -1]
assert data[1].weights.tolist() == [-1, -1, -1, -1, 1, -1]
assert data[2].weights.tolist() == [1, 1, -1, -1, -1, 1]
def test_maxcut_model(): def test_maxcut_model():

Loading…
Cancel
Save