Skip to content

Commit 8cf4354

Browse files
committed
v0.1.2 Simulated Annealing
1 parent 3edc592 commit 8cf4354

File tree

20 files changed

+377
-114
lines changed

20 files changed

+377
-114
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ There are 2 editions of GreyJack Solver:
1414
- Python edition
1515
- [Rust edition](https://github.com/CameleoGrey/greyjack-solver-rust)
1616

17-
# Key Features of GreyJack Solver (Rust version)
17+
# Key Features of GreyJack Solver
1818

1919
- **Unmatched Comfort, Expressiveness, Flexibility and speed of developing** Designed to express almost any optimization problem with maximum comfortability and clarity.
2020
- **Universality** Supports a wide range of constraint problems, including continuous, integer, and mixed-integer challenges. Additionally, thanks to Polars, you can optimize virtually any process that can be represented as table data.
@@ -24,7 +24,7 @@ There are 2 editions of GreyJack Solver:
2424
- **Support for Population and Local Search Algorithms** GreyJack Solver supports a wide range of metaheuristics, including population-based and local search algorithms, with highly flexible settings. You can easily find, select, and configure the approach that best fits your problem, delivering optimal results.
2525
- **Easy Integration** The observer mechanism (see examples) simplifies integration, making it straightforward to incorporate GreyJack Solver into your existing workflows..
2626

27-
# Get started with GreyJack Solver in Rust
27+
# Get started with GreyJack Solver
2828

2929
```
3030
pip install greyjack
@@ -45,7 +45,6 @@ maturin develop --release
4545

4646
# RoadMap
4747

48-
- SimulatedAnnealing
4948
- API for modelling pure math problems (classic solvers like)
5049
- Modern variations (modifications) of LSHADE (Differential evolution algorithms often appear in articles as sota approaches)
5150
- CMA, probably its modern variants, adaptations for tasks with integer and categorical variables (often appears in articles as sota approach)

examples/object_oriented/nqueens/score/PlainScoreCalculatorNQueens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def all_different(self, planning_entity_dfs, problem_fact_dfs):
3939
)
4040
.with_columns((pl.col("row_conflicts_count") + pl.col("desc_conflicts_count") + pl.col("asc_conflicts_count")).alias("sum_conflicts"))
4141
.sort("sample_id")
42-
.collect()
42+
.collect() # you can use engine="gpu" on Linux or by WSL
4343
)
4444

4545
scores = same_row_id_counts["sum_conflicts"].to_list()

examples/object_oriented/nqueens/scripts/solve_nqueens.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,33 @@
1515
from greyjack.Solver import Solver
1616
from greyjack.agents.base.LoggingLevel import LoggingLevel
1717
from greyjack.agents.base.ParallelizationBackend import ParallelizationBackend
18-
from greyjack.agents.TabuSearch import TabuSearch
19-
from greyjack.agents.GeneticAlgorithm import GeneticAlgorithm
20-
from greyjack.agents.LateAcceptance import LateAcceptance
18+
from greyjack.agents import *
2119

2220
if __name__ == "__main__":
2321

2422
# build domain model
25-
domain_builder = DomainBuilderNQueens(1024, random_seed=45)
23+
domain_builder = DomainBuilderNQueens(10000, random_seed=45)
2624
cotwin_builder = CotwinBuilderNQueens(use_incremental_score_calculator=True)
2725

2826
#termination_strategy = StepsLimit(step_count_limit=1000)
29-
#termination_strategy = TimeSpentLimit(time_seconds_limit=60)
27+
termination_strategy = TimeSpentLimit(time_seconds_limit=60)
3028
#termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
31-
termination_strategy = ScoreLimit(score_to_compare=[0])
29+
#termination_strategy = ScoreLimit(score_to_compare=[0])
3230
agent = TabuSearch(neighbours_count=20, tabu_entity_rate=0.0,
3331
mutation_rate_multiplier=None, move_probas=[0, 1, 0, 0, 0, 0],
3432
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)
3533
"""agent = GeneticAlgorithm(population_size=128, crossover_probability=0.5, p_best_rate=0.05,
3634
tabu_entity_rate=0.0, mutation_rate_multiplier=1.0, move_probas=[0, 1, 0, 0, 0, 0],
3735
migration_rate=0.00001, migration_frequency=1, termination_strategy=termination_strategy)"""
38-
"""agent = LateAcceptance(late_acceptance_size=1, tabu_entity_rate=0.0,
36+
"""agent = LateAcceptance(late_acceptance_size=10, tabu_entity_rate=0.0,
3937
mutation_rate_multiplier=None, move_probas=[0, 1, 0, 0, 0, 0],
4038
termination_strategy=termination_strategy)"""
39+
"""agent = SimulatedAnnealing(initial_temperature=[1.0], cooling_rate=0.9999, tabu_entity_rate=0.0,
40+
mutation_rate_multiplier=None, move_probas=[0, 1, 0, 0, 0, 0],
41+
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)"""
4142

4243
solver = Solver(domain_builder, cotwin_builder, agent,
43-
ParallelizationBackend.Multiprocessing, LoggingLevel.Info,
44+
ParallelizationBackend.Multiprocessing, LoggingLevel.FreshOnly,
4445
n_jobs=10, score_precision=[0])
4546
solution = solver.solve()
4647
#print( "Cotwin solution looks that: " )

examples/object_oriented/tsp/score/PlainScoreCalculatorTSP.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from greyjack.score_calculation.scores.ScoreVariants import ScoreVariants
66
import polars as pl
77
from numba import jit
8+
#from numba import cuda # there is possibility to write some constraints on gpu outside Polars engine
89

910
class PlainScoreCalculatorTSP( PlainScoreCalculator ):
1011

@@ -27,12 +28,13 @@ def no_duplicating_stops_constraint(self, planning_entity_dfs, problem_fact_dfs)
2728

2829
duplicate_counts = (
2930
path_stops_df
31+
.lazy()
3032
.group_by("sample_id")
3133
.agg((pl.col("location_list_id").count() - pl.col("location_list_id").n_unique()).alias("duplicates_count"))
3234
.group_by("sample_id")
3335
.agg(pl.col("duplicates_count").sum())
3436
.sort("sample_id")
35-
37+
.collect() # you can use engine="gpu" on Linux or by WSL
3638
)
3739

3840
scores = duplicate_counts["duplicates_count"].to_list()
@@ -100,6 +102,7 @@ def minimize_distance(self, planning_entity_dfs, problem_fact_dfs):
100102
# instead rewriting on Rust (to not increase complexity of project and still take huge performance boost)
101103
@staticmethod
102104
@jit(nopython=True, cache=True)
105+
#@cuda.jit()
103106
def compute_path_distances(data_matrix, distance_matrix):
104107

105108
unique_sample_ids = np.unique(data_matrix[:, 0])

examples/object_oriented/tsp/scripts/solve_tsp.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
cotwin_builder = CotwinBuilder(use_incremental_score_calculator=True)
3838

3939
#termination_strategy = StepsLimit(step_count_limit=1000)
40-
#termination_strategy = TimeSpentLimit(time_seconds_limit=60)
41-
termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
40+
termination_strategy = TimeSpentLimit(time_seconds_limit=60)
41+
#termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
4242
#termination_strategy = ScoreLimit(score_to_compare=[0])
43-
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.2,
43+
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.5,
4444
mutation_rate_multiplier=None, move_probas=[0.0, 0.2, 0.2, 0.2, 0.2, 0.2],
4545
compare_to_global=False, migration_frequency=10, termination_strategy=termination_strategy)
4646
"""agent = GeneticAlgorithm(population_size=128, crossover_probability=0.5, p_best_rate=0.05,
@@ -49,9 +49,12 @@
4949
"""agent = LateAcceptance(late_acceptance_size=64, tabu_entity_rate=0.2,
5050
mutation_rate_multiplier=None, move_probas=[0.0, 0.2, 0.2, 0.2, 0.2, 0.2],
5151
termination_strategy=termination_strategy)"""
52+
"""agent = SimulatedAnnealing(initial_temperature=[1.0, 1.0], cooling_rate=0.9999, tabu_entity_rate=0.2,
53+
mutation_rate_multiplier=None, move_probas=[0, 0.2, 0.2, 0.2, 0.2, 0.2],
54+
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)"""
5255

5356
solver = Solver(domain_builder, cotwin_builder, agent,
54-
ParallelizationBackend.Multiprocessing, LoggingLevel.FreshOnly,
57+
ParallelizationBackend.Multiprocessing, LoggingLevel.Info,
5558
n_jobs=10, score_precision=[0, 0])
5659
solution = solver.solve()
5760

examples/object_oriented/vrp/score/PlainScoreCalculatorVRP.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from greyjack.score_calculation.scores.ScoreVariants import ScoreVariants
66
import polars as pl
77
from numba import jit
8+
#from numba import cuda # there is possibility to write some constraints on gpu outside Polars engine
89

910
class PlainScoreCalculatorVRP(PlainScoreCalculator):
1011

@@ -30,10 +31,13 @@ def build_common_df(self, planning_entity_dfs, problem_fact_dfs):
3031

3132
customers_df = customers_df.rename({"customer_vec_id": "customer_id"})
3233
common_df = (planning_stops_df
33-
.with_row_index("index", offset=None)
34-
.join(vehicle_df, on="vehicle_id", how="inner")
35-
.join(customers_df, on="customer_id", how="inner")
36-
.sort(["sample_id", "vehicle_id", "index"], descending=[False, False, False]))
34+
.lazy()
35+
.with_row_index("index", offset=None)
36+
.join(vehicle_df.lazy(), on="vehicle_id", how="inner")
37+
.join(customers_df.lazy(), on="customer_id", how="inner")
38+
.sort(["sample_id", "vehicle_id", "index"], descending=[False, False, False])
39+
.collect() # you can use engine="gpu" on Linux or by WSL
40+
)
3741

3842
self.utility_objects["common_df"] = common_df
3943

@@ -45,11 +49,13 @@ def no_duplicating_stops_constraint(self, planning_entity_dfs, problem_fact_dfs)
4549

4650
duplicate_counts = (
4751
path_stops_df
52+
.lazy()
4853
.group_by("sample_id")
4954
.agg((pl.col("customer_id").count() - pl.col("customer_id").n_unique()).alias("duplicates_count"))
5055
.group_by("sample_id")
5156
.agg(pl.col("duplicates_count").sum())
5257
.sort("sample_id")
58+
.collect() # you can use engine="gpu" on Linux or by WSL
5359
)
5460

5561
scores = duplicate_counts["duplicates_count"].to_numpy()
@@ -64,13 +70,15 @@ def capacity_constraint(self, planning_entity_dfs, problem_fact_dfs):
6470

6571
capacity_penalties = (
6672
common_df
73+
.lazy()
6774
.group_by(["sample_id", "vehicle_id"])
6875
.agg(pl.col("demand").sum().alias("sum_trip_demand"))
69-
.join(vehicle_df, on="vehicle_id", how="inner")
76+
.join(vehicle_df.lazy(), on="vehicle_id", how="inner")
7077
.with_columns((pl.col("capacity") - pl.col("sum_trip_demand")).alias("capacity_difference"))
7178
.filter(pl.col("capacity_difference") < 0)
7279
.group_by("sample_id")
7380
.agg(pl.col("capacity_difference").abs().sum().alias("capacity_constraint_penalty"))
81+
.collect() # you can use engine="gpu" on Linux or by WSL
7482
)
7583

7684
bad_sample_ids = capacity_penalties["sample_id"].to_list()

examples/object_oriented/vrp/scripts/solve_vrp.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,21 @@
4141
cotwin_builder = CotwinBuilder(use_incremental_score_calculator=True, use_greed_init=True)
4242

4343
#termination_strategy = StepsLimit(step_count_limit=1000)
44-
#termination_strategy = TimeSpentLimit(time_seconds_limit=60)
45-
termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
44+
termination_strategy = TimeSpentLimit(time_seconds_limit=60)
45+
#termination_strategy = ScoreNoImprovement(time_seconds_limit=15)
4646
#termination_strategy = ScoreLimit(score_to_compare=[0])
47-
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.0,
47+
agent = TabuSearch(neighbours_count=128, tabu_entity_rate=0.8,
4848
mutation_rate_multiplier=None, move_probas=[0.5, 0.5, 0.0, 0.0, 0.0, 0.0],
49-
compare_to_global=False, migration_frequency=10, termination_strategy=termination_strategy)
49+
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)
5050
"""agent = GeneticAlgorithm(population_size=512, crossover_probability=0.5, p_best_rate=0.2,
5151
tabu_entity_rate=0.0, mutation_rate_multiplier=None, move_probas=[0.5, 0.5, 0.0, 0.0, 0.0, 0.0],
5252
migration_rate=0.00001, migration_frequency=10, termination_strategy=termination_strategy)"""
53-
"""agent = LateAcceptance(late_acceptance_size=64, tabu_entity_rate=0.05,
53+
"""agent = LateAcceptance(late_acceptance_size=32, tabu_entity_rate=0.8,
5454
mutation_rate_multiplier=None, move_probas=[0.5, 0.5, 0.0, 0.0, 0.0, 0.0],
5555
termination_strategy=termination_strategy)"""
56+
"""agent = SimulatedAnnealing(initial_temperature=[1.0, 1.0, 1.0], cooling_rate=0.9999, tabu_entity_rate=0.0,
57+
mutation_rate_multiplier=None, move_probas=[0.5, 0.5, 0.0, 0.0, 0.0, 0.0],
58+
compare_to_global=True, migration_frequency=10, termination_strategy=termination_strategy)"""
5659

5760
solver = Solver(domain_builder, cotwin_builder, agent,
5861
ParallelizationBackend.Multiprocessing, LoggingLevel.FreshOnly,

greyjack/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

greyjack/Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "greyjack"
3-
version = "0.1.1"
4-
edition = "2021"
3+
version = "0.1.2"
4+
edition = "2024"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77
[lib]
@@ -22,8 +22,8 @@ polars = { version = "0.46.0", features = ["lazy", "ndarray", "serde", "abs"] }
2222
# if you build lib from source code
2323
# uncomment to gain max performance (increases calculation speed about 5-10%,
2424
# but also increases build time ~20x times)
25-
[profile.release]
26-
lto = true
27-
codegen-units = 1
28-
debug = true
29-
opt-level = 3
25+
#[profile.release]
26+
#lto = true
27+
#codegen-units = 1
28+
#debug = true
29+
#opt-level = 3

greyjack/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ There are 2 editions of GreyJack Solver:
1414
- Python edition
1515
- [Rust edition](https://github.com/CameleoGrey/greyjack-solver-rust)
1616

17-
# Key Features of GreyJack Solver (Rust version)
17+
# Key Features of GreyJack Solver
1818

1919
- **Unmatched Comfort, Expressiveness, Flexibility and speed of developing** Designed to express almost any optimization problem with maximum comfortability and clarity.
2020
- **Universality** Supports a wide range of constraint problems, including continuous, integer, and mixed-integer challenges. Additionally, thanks to Polars, you can optimize virtually any process that can be represented as table data.
@@ -24,7 +24,7 @@ There are 2 editions of GreyJack Solver:
2424
- **Support for Population and Local Search Algorithms** GreyJack Solver supports a wide range of metaheuristics, including population-based and local search algorithms, with highly flexible settings. You can easily find, select, and configure the approach that best fits your problem, delivering optimal results.
2525
- **Easy Integration** The observer mechanism (see examples) simplifies integration, making it straightforward to incorporate GreyJack Solver into your existing workflows..
2626

27-
# Get started with GreyJack Solver in Rust
27+
# Get started with GreyJack Solver
2828

2929
```
3030
pip install greyjack
@@ -45,7 +45,6 @@ maturin develop --release
4545

4646
# RoadMap
4747

48-
- SimulatedAnnealing
4948
- API for modelling pure math problems (classic solvers like)
5049
- Modern variations (modifications) of LSHADE (Differential evolution algorithms often appear in articles as sota approaches)
5150
- CMA, probably its modern variants, adaptations for tasks with integer and categorical variables (often appears in articles as sota approach)

0 commit comments

Comments
 (0)