discrete_optimization.workforce.allocation package

Subpackages

Submodules

discrete_optimization.workforce.allocation.parser module

discrete_optimization.workforce.allocation.parser.parse_to_allocation_problem(json_path: str, multiobjective: bool = True) TeamAllocationProblem[source]
discrete_optimization.workforce.allocation.parser.parse_to_allocation_problem_additional_constraint(json_path: str, multiobjective: bool = True) TeamAllocationProblem[source]

discrete_optimization.workforce.allocation.problem module

class discrete_optimization.workforce.allocation.problem.AggregateOperator(value)[source]

Bases: Enum

An enumeration.

GINI = 4
MAX = 1
MAX_MINUS_MIN = 0
MEAN = 3
MIN = 2
class discrete_optimization.workforce.allocation.problem.AllocationAdditionalConstraint(same_allocation: list[set[Hashable]] | None = None, all_diff_allocation: list[set[Hashable]] | None = None, forced_allocation: dict[Hashable, Hashable] | None = None, forbidden_allocation: dict[Hashable, set[Hashable]] | None = None, allowed_allocation: dict[Hashable, set[Hashable]] | None = None, disjunction: list[list[tuple[Hashable, Hashable]]] | None = None, nb_max_teams: int | None = None, precedences: dict[Hashable, set[Hashable]] | None = None)[source]

Bases: object

Object to store potentially dynamically defined constraints. Some can be redundant

all_diff_allocation: list[set[Hashable]]
allowed_allocation: dict[Hashable, set[Hashable]]
disjunction: list[list[tuple[Hashable, Hashable]]]
forbidden_allocation: dict[Hashable, set[Hashable]]
forced_allocation: dict[Hashable, Hashable]
is_empty()[source]
nb_max_teams: int
precedences: dict[Hashable, set[Hashable]]
same_allocation: list[set[Hashable]]
class discrete_optimization.workforce.allocation.problem.GraphBipartite(nodes: list[tuple[Hashable, dict[str, Any]]], edges: list[tuple[Hashable, Hashable, dict[str, Any]]], nodes_activity: set[Hashable], nodes_team: set[Hashable], undirected: bool = True, compute_predecessors: bool = True)[source]

Bases: Graph

get_nodes_activity()[source]
get_nodes_team()[source]
get_nodes_team_list()[source]
is_bipartite() bool[source]
to_networkx() DiGraph[source]
class discrete_optimization.workforce.allocation.problem.TeamAllocationProblem(graph_activity: Graph | None = None, graph_allocation: GraphBipartite | None = None, allocation_additional_constraint: AllocationAdditionalConstraint | None = None, schedule_activity: dict[Hashable, tuple[int, int]] | None = None, calendar_team: dict[Hashable, list[tuple[int, int]]] | None = None, activities_name: list[Hashable] | None = None)[source]

Bases: Problem

add_additional_constraint(allocation_additional_constraint: AllocationAdditionalConstraint)[source]
compute_allowed_team_for_task(task: Hashable) list[Hashable][source]
compute_allowed_team_index_all_task() list[list[int]][source]
compute_allowed_team_index_for_task(task: Hashable) list[int][source]
compute_forbidden_team_index_all_task() list[list[int]][source]
compute_forbidden_team_index_for_task(task: Hashable) list[int][source]
compute_pair_overlap_index_task() list[tuple[int, int]][source]
computed_forbidden_team_for_task(task: Hashable) list[Hashable][source]
count_allowed_assignment_violations(variable: TeamAllocationSolution) int[source]
count_color_constraints_violations(variable: TeamAllocationSolution) int[source]
property do_add_cons
evaluate(variable: TeamAllocationSolution) dict[str, float][source]

Evaluation implementation for TeamAllocationProblem.

Compute number of allocated teams and violation of the current solution.

evaluate_from_encoding(int_vector: list[int], encoding_name: str) dict[str, float][source]

Can be used in GA algorithm to build an object solution and evaluate from a int_vector representation.

Parameters:
  • int_vector – representing the colors vector of our problem

  • encoding_name – name of the attribute in TeamAllocationSolution corresponding to the int_vector given. In our case, will only work for encoding_name=”allocation”

Returns: the evaluation of the (int_vector, encoding) object on the team allocation problem.

get_attribute_register() EncodingRegister[source]

Attribute documentation for TeamAllocation object.

Returns: an EncodingRegister specifying the colors attribute.

get_dummy_solution() TeamAllocationSolution[source]

Returns a dummy solution.

A dummy feasible solution consists in giving one different color per vertices. Returns: A feasible and dummiest ColoringSolution

get_max_teams() int[source]
get_natural_explanation_unsat_allowed_assignment(variable: TeamAllocationSolution) list[str][source]
get_natural_explanation_unsat_colors(variable: TeamAllocationSolution) list[str][source]

Return a list of strings describing which coloring constraints are not fulfilled by the given solution. :param variable: solution object we want to “analyze” :type variable: TeamAllocationSolution

Returns: list[str]

get_natural_explanation_unsat_constraints(variable: TeamAllocationSolution) list[str][source]

Return a list of strings describing which constraints are not fulfilled by the given solution. :param variable: solution object we want to “analyze” :type variable: TeamAllocationSolution

Returns: list[str]

get_objective_register() ObjectiveRegister[source]

Specifies the default objective settings to be used with the evaluate function output.

get_solution_type() type[Solution][source]

Returns the class of a solution instance for ColoringProblem.

remove_additional_constraint()[source]
reorder_teams_name(new_order_teams_name: list[Hashable])[source]
satisfy(variable: TeamAllocationSolution) bool[source]

Check the constraint of the solution.

Check for each edges in the graph if the allocated team of the vertices are different. When one counterexample is found, the function directly returns False. :param variable: the solution object we want to check the feasibility :type variable: TeamAllocationSolution

Returns: boolean indicating if the solution fulfills the constraint.

satisfy_allowed_assignment(variable: TeamAllocationSolution) bool[source]
satisfy_color_constraints(variable: TeamAllocationSolution) bool[source]
class discrete_optimization.workforce.allocation.problem.TeamAllocationProblemMultiobj(graph_activity: Graph | None = None, graph_allocation: GraphBipartite | None = None, allocation_additional_constraint: AllocationAdditionalConstraint | None = None, schedule_activity: dict[Hashable, tuple[int, int]] | None = None, calendar_team: dict[Hashable, list[tuple[int, int]]] | None = None, activities_name: list[Hashable] | None = None, attributes_cumul_activities: list[str] | None = None, objective_doc_cumul_activities: dict[str, tuple[ObjectiveDoc, AggregateOperator]] | None = None)[source]

Bases: TeamAllocationProblem

aggregate_cumuls(cumuls_array, aggregate_operator: AggregateOperator) float[source]
evaluate(variable: TeamAllocationSolution) dict[str, float][source]

Evaluation implementation for TeamAllocationProblem.

Compute number of allocated teams and violation of the current solution.

evaluate_cumul_nodes(variable: TeamAllocationSolution, attribute_on_node: str)[source]
get_objective_register() ObjectiveRegister[source]

Specifies the default objective settings to be used with the evaluate function output.

update_attributes_of_activities()[source]
class discrete_optimization.workforce.allocation.problem.TeamAllocationSolution(problem: TeamAllocationProblem, allocation: list[int | None], **kwargs)[source]

Bases: Solution

change_problem(new_problem: Problem) None[source]

If relevant to the optimisation problem, change the underlying problem instance for the solution.

This method can be used to evaluate a solution for different instance of problems.

Parameters:

new_problem (Problem) – another problem instance from which the solution can be evaluated

Returns: None

copy() Solution[source]

Deep copy of the solution.

The copy() function should return a new object containing the same input as the current object, that respects the following expected behaviour: -y = x.copy() -if do some inplace change of y, the changes are not done in x.

Returns: a new object from which you can manipulate attributes without changing the original object.

lazy_copy() Solution[source]

This function should return a new object but possibly with mutable attributes from the original objects.

A typical use of lazy copy is in evolutionary algorithms or genetic algorithm where the use of local move don’t need to do a possibly costly deepcopy.

Returns (Solution): copy (possibly shallow) of the Solution

discrete_optimization.workforce.allocation.problem.build_graph_allocation_from_calendar_and_schedule(starts: ndarray, ends: ndarray, calendar_team: dict[Hashable, list[tuple[int, int]]], horizon: int, tasks_name: list[Hashable], teams_name: list[Hashable])[source]
discrete_optimization.workforce.allocation.problem.compute_available_teams_per_activities(starts: ndarray, ends: ndarray, activities_name: list[Hashable], calendars_team: dict[Hashable, ndarray])[source]
discrete_optimization.workforce.allocation.problem.compute_graph_coloring(starts: ndarray, ends: ndarray, task_names: list)[source]
discrete_optimization.workforce.allocation.problem.satisfy_additional_constraint(problem: TeamAllocationProblem, solution: TeamAllocationSolution, additional_constraint: AllocationAdditionalConstraint, partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_all_diff(problem: TeamAllocationProblem, solution: TeamAllocationSolution, all_diffs: list[set[Hashable]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_allowed_allocation(problem: TeamAllocationProblem, solution: TeamAllocationSolution, allowed_allocation: dict[Hashable, set[Hashable]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_disjunction(problem: TeamAllocationProblem, solution: TeamAllocationSolution, one_disjunction: list[tuple[Hashable, Hashable]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_disjunctions(problem: TeamAllocationProblem, solution: TeamAllocationSolution, disjunction: list[list[tuple[Hashable, Hashable]]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_forbidden_allocation(problem: TeamAllocationProblem, solution: TeamAllocationSolution, forbidden_allocation: dict[Hashable, set[Hashable]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_forced_allocation(problem: TeamAllocationProblem, solution: TeamAllocationSolution, forced_allocation: dict[Hashable, Hashable], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_nb_teams(problem: TeamAllocationProblem, solution: TeamAllocationSolution, nb_teams_max: int, partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.satisfy_same_allocation(problem: TeamAllocationProblem, solution: TeamAllocationSolution, same_allocation: list[set[Hashable]], partial_solution: bool = False)[source]
discrete_optimization.workforce.allocation.problem.transform_to_coloring_problem(team_allocation_problem: TeamAllocationProblem, add_clique_team_nodes: bool = True, add_constraint_color: bool = False) ColoringProblem[source]

Transform the list-coloring/team_allocation_problem into a classical coloring problem. 1) We create a node for each team, linking to other original nodes this team can’t be allocated to. 2) We create a clique of nodes that are the “teams” node. :param team_allocation_problem: original problem to be transformed. :param add_constraint_color: use special structure in ColoringProblem to force the value of color of given nodes :param add_clique_team_nodes: use the transformation of list-coloring to classical graph coloring by adding artificial nodes for team and creating a clique from them. :return: ColoringProblem representing the same problem.

discrete_optimization.workforce.allocation.utils module

discrete_optimization.workforce.allocation.utils.additional_constraint_subset_teams(allocation_additional_constraint: AllocationAdditionalConstraint, subset_teams_keep: set[Hashable])[source]
discrete_optimization.workforce.allocation.utils.allocation_additional_constraint_subset_tasks(allocation_additional_constraint: AllocationAdditionalConstraint, subset_tasks: set[Hashable])[source]
discrete_optimization.workforce.allocation.utils.compute_active_activities_on_time(team_allocation_problem: TeamAllocationProblem, time: int | Timestamp, side='left') list[Hashable][source]
discrete_optimization.workforce.allocation.utils.compute_all_overlapping(team_allocation_problem: TeamAllocationProblem) set[frozenset][source]
discrete_optimization.workforce.allocation.utils.compute_changes_between_solution_alloc(solution_a: TeamAllocationSolution, solution_b: TeamAllocationSolution, problem_a: TeamAllocationProblem | None = None, problem_b: TeamAllocationProblem | None = None)[source]
discrete_optimization.workforce.allocation.utils.compute_equivalent_teams(team_allocation_problem: TeamAllocationProblem) list[list[int]][source]

Return a list of disjoint set of teams index, that can be considered as indistinguishable from a solution point of view. Example : in the pure coloring problem all the colors/team are equivalent In the team allocation problem, due to restricted compatible teams to task, the equivalent class are different Adaptation from the notebook/test_models.ipynb

discrete_optimization.workforce.allocation.utils.compute_overlapping_activities_on_end_time(team_allocation_problem: TeamAllocationProblem, activity: Hashable) list[Hashable][source]

Look at overlapping task at starting time of task

discrete_optimization.workforce.allocation.utils.compute_overlapping_activities_on_start_time(team_allocation_problem: TeamAllocationProblem, activity: Hashable) list[Hashable][source]

Look at overlapping task at starting time of task

discrete_optimization.workforce.allocation.utils.create_subproblem_allocation(problem: TeamAllocationProblem, subset_tasks: set[Hashable])[source]
discrete_optimization.workforce.allocation.utils.cut_number_of_team(team_allocation: TeamAllocationProblem, nb_teams_keep: int = 3, subset_teams_keep: set[Hashable] | None = None)[source]
discrete_optimization.workforce.allocation.utils.modify_graph(fig)[source]
discrete_optimization.workforce.allocation.utils.plot_allocation_solution(problem: TeamAllocationProblem, sol: TeamAllocationSolution, index_team_to_other_index: dict[int, int] | None = None, use_color_map: bool = False, category: bool = True, display: bool = True, plot_breaks: bool = False, color_break: str | None = None, ignore_unallocated: bool = False, name_unallocated: str = 'Unset', text: str | None = None, title: str | None = None, ref_date: Timestamp | None = None, showlegend=True)[source]
discrete_optimization.workforce.allocation.utils.subgraph_activities(graph: Graph, subset_tasks: set[Hashable]) Graph[source]
discrete_optimization.workforce.allocation.utils.subgraph_bipartite_activities(graph_allocation: GraphBipartite, subset_tasks: set[Hashable]) Graph[source]
discrete_optimization.workforce.allocation.utils.subgraph_teams(graph_allocation: GraphBipartite, nb_teams_keep: int = 3, subset_teams_keep: set[Hashable] | None = None) GraphBipartite[source]

Module contents