Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix synthetic generation and add comments to genetic operators with numpy #59

Merged
merged 18 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sampo/generator/pipeline/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def get_graph(mode: SyntheticGraphType | None = SyntheticGraphType.GENERAL,
masters_clusters_ind += 1
works_generated += count_works

if (0 < bottom_border <= works_generated or top_border < (count_works + works_generated)
if (0 < bottom_border <= works_generated or 0 < top_border < (count_works + works_generated)
or 0 < cluster_counts <= (len(stages) - 1)):
break

Expand Down
5 changes: 3 additions & 2 deletions sampo/generator/utils/graph_node_operations.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from sampo.schemas.graph import GraphNode
from collections import deque


def count_ancestors(first_ancestors: list[GraphNode], root: GraphNode) -> int:
Expand All @@ -9,7 +10,7 @@ def count_ancestors(first_ancestors: list[GraphNode], root: GraphNode) -> int:
:param root: The root node of the graph.
:return:
"""
q = list(first_ancestors)
q = deque(first_ancestors)
count = len(first_ancestors)
used = set()
used.add(root)
Expand All @@ -19,7 +20,7 @@ def count_ancestors(first_ancestors: list[GraphNode], root: GraphNode) -> int:
if parent in used:
continue
used.add(parent)
q.insert(0, parent)
q.appendleft(parent)
count += 1

return count
16 changes: 16 additions & 0 deletions sampo/scheduler/genetic/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,24 +430,40 @@ def mutate_scheduling_order(ind: ChromosomeType, mutpb: float, rand: random.Rand
:return: mutated individual
"""
order = ind[0]
# number of possible mutations = number of works except start and finish works
num_possible_muts = len(order) - 2
# generate mask of works to mutate based on mutation probability
mask = np.array([rand.random() < mutpb for _ in range(num_possible_muts)])
if mask.any():
# get indexes of works to mutate based on generated mask
indexes_of_works_to_mutate = np.where(mask)[0] + 1
# shuffle order of mutations
rand.shuffle(indexes_of_works_to_mutate)
# get works to mutate based on shuffled indexes
works_to_mutate = order[indexes_of_works_to_mutate]
for work in works_to_mutate:
# pop index of the current work
i, indexes_of_works_to_mutate = indexes_of_works_to_mutate[0], indexes_of_works_to_mutate[1:]
# find max index of parent of the current work
i_parent = np.max(np.where(np.isin(order[:i], list(parents[work]), assume_unique=True))[0]) + 1
# find min index of child of the current work
i_children = np.min(np.where(np.isin(order[i + 1:], list(children[work]), assume_unique=True))[0]) + i
if i_parent == i_children:
# if child and parent indexes are equal then no mutation can be done
continue
else:
# update work indexes after the current work deletion
indexes_of_works_to_mutate[indexes_of_works_to_mutate > i] -= 1
# range potential indexes to insert the current work
choices = np.concatenate((np.arange(i_parent, i), np.arange(i + 1, i_children + 1)))
# set weights to potential indexes based on their distance from the current one
weights = 1 / np.abs(choices - i)
# generate new index for the current work
new_i = rand.choices(choices, weights=weights)[0]
# delete current work from current index, insert in new generated index and update scheduling order
# in chromosome
order[:] = np.insert(np.delete(order, i), new_i, work)
# update work indexes after the current work insertion in new generated index
indexes_of_works_to_mutate[indexes_of_works_to_mutate >= new_i] += 1

return ind
Expand Down