forked from hiive/mlrose
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In progress: finish refactor of all generators; pending tests
- Loading branch information
1 parent
015f6f3
commit c3cd776
Showing
8 changed files
with
367 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,42 @@ | ||
"""Classes for defining optimization problem objects.""" | ||
"""Class defining a FlipFlop optimization problem generator.""" | ||
|
||
# Author: Andrew Rollings | ||
# Authors: Andrew Rollings (modified by Kyle Nakamura) | ||
# License: BSD 3 clause | ||
|
||
import numpy as np | ||
|
||
from mlrose_hiive import FlipFlopOpt | ||
|
||
|
||
class FlipFlopGenerator: | ||
"""A class to generate FlipFlop optimization problem instances.""" | ||
|
||
@staticmethod | ||
def generate(seed, size=20): | ||
def generate(seed: int, size: int = 20) -> FlipFlopOpt: | ||
""" | ||
Generate a FlipFlop optimization problem with a given seed and size. | ||
Parameters | ||
---------- | ||
seed : int | ||
The seed for the random number generator. | ||
size : int, optional | ||
The size of the problem (default is 20). | ||
Returns | ||
------- | ||
FlipFlopOpt | ||
An instance of FlipFlopOpt configured with the specified seed and size. | ||
Raises | ||
------ | ||
ValueError | ||
If the size is not a positive integer. | ||
""" | ||
if size <= 0: | ||
raise ValueError(f"Size must be a positive integer. Got {size}.") | ||
|
||
np.random.seed(seed) | ||
|
||
problem = FlipFlopOpt(length=size) | ||
|
||
return problem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,48 @@ | ||
"""Classes for defining optimization problem objects.""" | ||
"""Class defining a Four Peaks optimization problem generator.""" | ||
|
||
# Authors: Andrew Rollings (modified by Kyle Nakamura) | ||
# License: BSD 3 clause | ||
|
||
import numpy as np | ||
|
||
from mlrose_hiive import DiscreteOpt, FourPeaks | ||
|
||
|
||
class FourPeaksGenerator: | ||
"""Generator class for Four Peaks.""" | ||
"""A class to generate Four Peaks optimization problem instances.""" | ||
|
||
@staticmethod | ||
def generate(seed, size=20, t_pct=0.1): | ||
def generate(seed: int, size: int = 20, threshold_percentage: float = 0.1) -> DiscreteOpt: | ||
""" | ||
Generate a Four Peaks optimization problem with a given seed, size, and threshold percentage. | ||
Parameters | ||
---------- | ||
seed : int | ||
The seed for the random number generator. | ||
size : int, optional | ||
The size of the problem (default is 20). | ||
threshold_percentage : float, optional | ||
The threshold percentage for the Four Peaks problem (default is 0.1). | ||
Returns | ||
------- | ||
DiscreteOpt | ||
An instance of DiscreteOpt configured with the specified parameters. | ||
Raises | ||
------ | ||
ValueError | ||
If the size is not a positive integer or if the threshold_percentage is not between 0 and 1. | ||
""" | ||
if size <= 0: | ||
raise ValueError(f"Size must be a positive integer. Got {size}.") | ||
if not (0 <= threshold_percentage <= 1): | ||
raise ValueError(f"Threshold percentage must be between 0 and 1. Got {threshold_percentage}.") | ||
|
||
np.random.seed(seed) | ||
fitness = FourPeaks(threshold_percentage=t_pct) | ||
|
||
fitness = FourPeaks(threshold_percentage=threshold_percentage) | ||
problem = DiscreteOpt(length=size, fitness_fn=fitness) | ||
|
||
return problem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,80 @@ | ||
"""Classes for defining optimization problem objects.""" | ||
"""Class defining a Knapsack optimization problem generator.""" | ||
|
||
# Author: Genevieve Hayes | ||
# Author: Genevieve Hayes (modified by Kyle Nakamura) | ||
# License: BSD 3 clause | ||
|
||
import numpy as np | ||
|
||
import mlrose_hiive | ||
from mlrose_hiive import KnapsackOpt | ||
|
||
|
||
class KnapsackGenerator: | ||
"""A class to generate Knapsack optimization problems.""" | ||
|
||
@staticmethod | ||
def generate(seed, number_of_items_types=10, | ||
max_item_count=5, max_weight_per_item=25, | ||
max_value_per_item=10, max_weight_pct=0.6, | ||
multiply_by_max_item_count=True): | ||
def generate(seed: int, | ||
number_of_item_types: int = 10, | ||
max_item_count: int = 5, | ||
max_weight_per_item: int = 25, | ||
max_value_per_item: int = 10, | ||
max_weight_percentage: float = 0.6, | ||
multiply_by_max_item_count: bool = True) -> KnapsackOpt: | ||
""" | ||
Generate a Knapsack optimization problem instance. | ||
Parameters | ||
---------- | ||
seed : int | ||
Seed for the random number generator. | ||
number_of_item_types : int, optional, default=10 | ||
Number of different item types. | ||
max_item_count : int, optional, default=5 | ||
Maximum count for each item type. | ||
max_weight_per_item : int, optional, default=25 | ||
Maximum weight for each item type. | ||
max_value_per_item : int, optional, default=10 | ||
Maximum value for each item type. | ||
max_weight_percentage : float, optional, default=0.6 | ||
Maximum weight percentage of the knapsack. | ||
multiply_by_max_item_count : bool, optional, default=True | ||
If True, multiply weights and values by max_item_count. | ||
Returns | ||
------- | ||
KnapsackOpt | ||
An instance of KnapsackOpt configured with the specified parameters. | ||
Raises | ||
------ | ||
ValueError | ||
If any parameter is not of the expected type or value. | ||
""" | ||
if not isinstance(seed, int): | ||
raise ValueError(f"Seed must be an integer. Got {seed}") | ||
if not isinstance(number_of_item_types, int) or number_of_item_types <= 0: | ||
raise ValueError(f"Number of item types must be a positive integer. Got {number_of_item_types}") | ||
if not isinstance(max_item_count, int) or max_item_count <= 0: | ||
raise ValueError(f"Max item count must be a positive integer. Got {max_item_count}") | ||
if not isinstance(max_weight_per_item, int) or max_weight_per_item <= 0: | ||
raise ValueError(f"Max weight per item must be a positive integer. Got {max_weight_per_item}") | ||
if not isinstance(max_value_per_item, int) or max_value_per_item <= 0: | ||
raise ValueError(f"Max value per item must be a positive integer. Got {max_value_per_item}") | ||
if not isinstance(max_weight_percentage, float) or not (0 <= max_weight_percentage <= 1): | ||
raise ValueError(f"Max weight percentage must be a float between 0 and 1. Got {max_weight_percentage}") | ||
if not isinstance(multiply_by_max_item_count, bool): | ||
raise ValueError(f"multiply_by_max_item_count must be a boolean. Got {multiply_by_max_item_count}") | ||
|
||
np.random.seed(seed) | ||
weights = 1 + np.random.randint(max_weight_per_item, size=number_of_items_types) | ||
values = 1 + np.random.randint(max_value_per_item, size=number_of_items_types) | ||
problem = mlrose_hiive.KnapsackOpt(length=number_of_items_types, max_val=max_item_count, weights=weights, values=values, | ||
max_weight_pct=max_weight_pct, multiply_by_max_item_count=multiply_by_max_item_count) | ||
|
||
weights = 1 + np.random.randint(max_weight_per_item, size=number_of_item_types) | ||
values = 1 + np.random.randint(max_value_per_item, size=number_of_item_types) | ||
|
||
problem = KnapsackOpt( | ||
length=number_of_item_types, | ||
max_val=max_item_count, | ||
weights=weights, | ||
values=values, | ||
max_weight_pct=max_weight_percentage, | ||
multiply_by_max_item_count=multiply_by_max_item_count | ||
) | ||
|
||
return problem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,92 @@ | ||
from mlrose_hiive.opt_probs import MaxKColorOpt | ||
"""Class defining a Max-K Color optimization problem generator.""" | ||
|
||
import numpy as np | ||
import networkx as nx | ||
|
||
from mlrose_hiive.opt_probs import MaxKColorOpt | ||
|
||
|
||
class MaxKColorGenerator: | ||
@staticmethod | ||
def generate(seed, number_of_nodes=20, max_connections_per_node=4, max_colors=None, maximize=False): | ||
"""A class to generate Max-K Color optimization problems.""" | ||
|
||
@staticmethod | ||
def generate(seed: int, | ||
number_of_nodes: int = 20, | ||
max_connections_per_node: int = 4, | ||
max_colors: int | None = None, | ||
maximize: bool = False) -> MaxKColorOpt: | ||
""" | ||
>>> edges = [(0, 1), (0, 2), (0, 4), (1, 3), (2, 0), (2, 3), (3, 4)] | ||
>>> fitness = mlrose_hiive.MaxKColor(edges) | ||
Generate a Max-K Color optimization problem instance. | ||
Parameters | ||
---------- | ||
seed : int | ||
Seed for the random number generator. | ||
number_of_nodes : int, optional, default=20 | ||
The number of nodes in the graph. | ||
max_connections_per_node : int, optional, default=4 | ||
The maximum number of connections (edges) per node. | ||
max_colors : int or None, optional, default=None | ||
The maximum number of colors available. | ||
maximize : bool, optional, default=False | ||
Whether the optimization problem should be maximized. | ||
Returns | ||
------- | ||
MaxKColorOpt | ||
An instance of MaxKColorOpt configured with the specified parameters. | ||
Raises | ||
------ | ||
ValueError | ||
If any parameter is not of the expected type or value. | ||
Examples | ||
-------- | ||
>>> import mlrose_hiive | ||
>>> test_edges = [(0, 1), (0, 2), (0, 4), (1, 3), (2, 0), (2, 3), (3, 4)] | ||
>>> fitness = mlrose_hiive.MaxKColor(test_edges) | ||
>>> state = np.array([0, 1, 0, 1, 1]) | ||
>>> fitness.evaluate(state) | ||
3.0 | ||
""" | ||
if not isinstance(seed, int): | ||
raise ValueError(f"Seed must be an integer. Got {seed}") | ||
if not isinstance(number_of_nodes, int) or number_of_nodes <= 0: | ||
raise ValueError(f"Number of nodes must be a positive integer. Got {number_of_nodes}") | ||
if not isinstance(max_connections_per_node, int) or max_connections_per_node <= 0: | ||
raise ValueError(f"Max connections per node must be a positive integer. Got {max_connections_per_node}") | ||
if max_colors is not None and not isinstance(max_colors, int): | ||
raise ValueError(f"Max colors must be an integer or None. Got {max_colors}") | ||
if not isinstance(maximize, bool): | ||
raise ValueError(f"Maximize must be a boolean. Got {maximize}") | ||
|
||
np.random.seed(seed) | ||
# all nodes have to be connected, somehow. | ||
|
||
# Generate random connection counts for each node | ||
node_connection_counts = 1 + np.random.choice(max_connections_per_node, size=number_of_nodes) | ||
|
||
node_connections = {} | ||
nodes = range(number_of_nodes) | ||
for n in nodes: | ||
all_other_valid_nodes = [o for o in nodes if (o != n and (o not in node_connections or | ||
n not in node_connections[o]))] | ||
count = min(node_connection_counts[n], len(all_other_valid_nodes)) | ||
other_nodes = sorted(np.random.choice(all_other_valid_nodes, count, replace=False)) | ||
node_connections[n] = [(n, o) for o in other_nodes] | ||
|
||
# check connectivity | ||
g = nx.Graph() | ||
g.add_edges_from([x for y in node_connections.values() for x in y]) | ||
|
||
for n in nodes: | ||
cannot_reach = [(n, o) if n < o else (o, n) for o in nodes if o not in nx.bfs_tree(g, n).nodes()] | ||
for s, f in cannot_reach: | ||
g.add_edge(s, f) | ||
check_reach = len([(n, o) if n < o else (o, n) for o in nodes if o not in nx.bfs_tree(g, n).nodes()]) | ||
if check_reach == 0: | ||
for node in nodes: | ||
valid_other_nodes = [other for other in nodes if ( | ||
other != node and (other not in node_connections or node not in node_connections[other]))] | ||
count = min(node_connection_counts[node], len(valid_other_nodes)) | ||
connected_nodes = sorted(np.random.choice(valid_other_nodes, count, replace=False)) | ||
node_connections[node] = [(node, other) for other in connected_nodes] | ||
|
||
# Ensure graph connectivity | ||
graph = nx.Graph() | ||
graph.add_edges_from([edge for edges in node_connections.values() for edge in edges]) | ||
|
||
for node in nodes: | ||
unreachable = [(node, other) if node < other else (other, node) for other in nodes if other not in nx.bfs_tree(graph, node).nodes()] | ||
for start, end in unreachable: | ||
graph.add_edge(start, end) | ||
remaining_unreachable = len([(node, other) if node < other else (other, node) for other in nodes if other not in nx.bfs_tree(graph, node).nodes()]) | ||
if remaining_unreachable == 0: | ||
break | ||
|
||
edges = [(s, f) for (s, f) in g.edges()] | ||
problem = MaxKColorOpt(edges=edges, length=number_of_nodes, maximize=maximize, max_colors=max_colors, source_graph=g) | ||
problem = MaxKColorOpt(edges=list(graph.edges()), length=number_of_nodes, maximize=maximize, max_colors=max_colors, source_graph=graph) | ||
|
||
return problem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,43 @@ | ||
"""Classes for defining optimization problem objects.""" | ||
"""Class defining a One Max optimization problem generator.""" | ||
|
||
import numpy as np | ||
|
||
from mlrose_hiive import DiscreteOpt, OneMax | ||
|
||
|
||
class OneMaxGenerator: | ||
"""Generator class for One Max.""" | ||
"""A class to generate One Max optimization problems.""" | ||
|
||
@staticmethod | ||
def generate(seed, size=20): | ||
def generate(seed: int, size: int = 20) -> DiscreteOpt: | ||
""" | ||
Generate a One Max optimization problem instance. | ||
Parameters | ||
---------- | ||
seed : int | ||
Seed for the random number generator. | ||
size : int, optional, default=20 | ||
The size of the optimization problem (number of bits). | ||
Returns | ||
------- | ||
DiscreteOpt | ||
An instance of DiscreteOpt configured for the One Max problem. | ||
Raises | ||
------ | ||
ValueError | ||
If `size` is not a positive integer. | ||
""" | ||
if not isinstance(seed, int): | ||
raise ValueError(f"Seed must be an integer. Got {seed}") | ||
if not isinstance(size, int) or size <= 0: | ||
raise ValueError(f"Size must be a positive integer. Got {size}") | ||
|
||
np.random.seed(seed) | ||
|
||
fitness = OneMax() | ||
return DiscreteOpt(length=size, fitness_fn=fitness) | ||
problem = DiscreteOpt(length=size, fitness_fn=fitness) | ||
|
||
return problem |
Oops, something went wrong.