Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
khoint5304 committed Dec 4, 2023
2 parents 3d1eedb + 8d603a2 commit cb08b06
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 20 deletions.
28 changes: 21 additions & 7 deletions .github/workflows/d2d-compare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
"utf-8",
function(error, data) {
if (error) throw error;
github.rest.issues.createComment({
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.issue.number }},
Expand All @@ -57,7 +57,7 @@ jobs:
with:
retries: 3
script: |
github.rest.reactions.createForIssueComment({
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: ${{ github.event.comment.id }},
Expand All @@ -73,8 +73,26 @@ jobs:
counter: [1, 2]

steps:
- name: Get PR branch name
id: get-branch
uses: actions/github-script@v7
with:
script: |
try {
var result = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.issue.number }},
});
return result.data;
} catch (e) {
core.setFailed(`Failed to get branch name of PR#${{ github.event.issue.number }}: ${e}`);
}
- name: Checkout PR branch
uses: actions/checkout@v3
with:
ref: ${{ fromJSON(steps.get-branch.outputs.result).head.ref }}

- name: Setup Python
uses: actions/setup-python@v4
Expand All @@ -91,9 +109,7 @@ jobs:
run: |
problem=$(cat input.txt)
python d2d.py "$problem" \
--iterations 2000 \
--drone-config-mapping 3 3 3 3 \
--propagation-priority min-distance \
--pool-size 8 \
--dump PR#${{ github.event.issue.number }}-run#${{ matrix.counter }}.json
Expand Down Expand Up @@ -132,9 +148,7 @@ jobs:
run: |
problem=$(cat input.txt)
python d2d.py "$problem" \
--iterations 2000 \
--drone-config-mapping 3 3 3 3 \
--propagation-priority min-distance \
--pool-size 8 \
--dump main-run#${{ matrix.counter }}.json
Expand Down Expand Up @@ -194,7 +208,7 @@ jobs:
if (error) throw error;
await fs.readFile("url.txt", "utf-8", async function (error, url) {
if (error) throw error;
github.rest.issues.createComment({
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.issue.number }},
Expand Down
34 changes: 26 additions & 8 deletions d2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,52 @@ def to_json(solution: d2d.D2DPathSolution) -> Dict[str, Any]:
}


def _max_distance_key(pareto_costs: Dict[Tuple[float, ...], int], candidate: d2d.D2DPathSolution, /) -> float:
def _max_distance_key(
pareto_costs: Dict[Tuple[float, ...], int],
minimum: Tuple[float, ...],
maximum: Tuple[float, ...],
candidate: d2d.D2DPathSolution,
/
) -> float:
cost = candidate.cost()
result = 0.0
for pareto_cost, counter in pareto_costs.items():
result += counter * abs(pareto_cost[0] - cost[0]) + abs(pareto_cost[1] - cost[1])
result += counter * abs(pareto_cost[0] - cost[0]) / maximum[0] + abs(pareto_cost[1] - cost[1]) / maximum[1]

return -result


def _min_distance_key(pareto_costs: Dict[Tuple[float, ...], int], candidate: d2d.D2DPathSolution, /) -> float:
def _min_distance_key(
pareto_costs: Dict[Tuple[float, ...], int],
minimum: Tuple[float, ...],
maximum: Tuple[float, ...],
candidate: d2d.D2DPathSolution,
/
) -> float:
cost = candidate.cost()
result = 0.0
for pareto_cost, counter in pareto_costs.items():
result += counter * abs(pareto_cost[0] - cost[0]) + abs(pareto_cost[1] - cost[1])
result += counter * abs(pareto_cost[0] - cost[0]) / maximum[0] + abs(pareto_cost[1] - cost[1]) / maximum[1]

return result


def _ideal_distance_key(pareto_costs: Dict[Tuple[float, ...], int], candidate: d2d.D2DPathSolution, /) -> float:
def _ideal_distance_key(
pareto_costs: Dict[Tuple[float, ...], int],
minimum: Tuple[float, ...],
maximum: Tuple[float, ...],
candidate: d2d.D2DPathSolution,
/
) -> float:
ideal = (min(cost[0] for cost in pareto_costs.keys()), min(cost[1] for cost in pareto_costs.keys()))
cost = candidate.cost()
return abs(ideal[0] - cost[0]) + abs(ideal[1] - cost[1])
return abs(ideal[0] - cost[0]) / maximum[0] + abs(ideal[1] - cost[1]) / maximum[1]


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Tabu search algorithm for D2D problems")
parser.add_argument("problem", type=str, help="the problem name (e.g. \"6.5.1\", \"200.10.1\", ...)")
parser.add_argument("-i", "--iterations", default=500, type=int, help="the number of iterations to run the tabu search for (default: 500)")
parser.add_argument("-i", "--iterations", default=2000, type=int, help="the number of iterations to run the tabu search for (default: 2000)")
parser.add_argument("-t", "--tabu-size", default=10, type=int, help="the tabu size for every neighborhood (default: 10)")
parser.add_argument("-c", "--drone-config-mapping", nargs="+", default=[3, 3, 3, 3], type=int, help="the energy configuration index for each drone (default: \"0 0 0 0\")")
parser.add_argument("-e", "--energy-mode", default=LINEAR, choices=[LINEAR, NON_LINEAR], help="the energy consumption mode to use (default: linear)")
Expand Down Expand Up @@ -105,7 +123,7 @@ def _ideal_distance_key(pareto_costs: Dict[Tuple[float, ...], int], candidate: d
with d2d.D2DPathSolution.share_distances():
d2d.Swap.reset_tabu(maxlen=namespace.tabu_size)

propagation_priority_key: Optional[Callable[[Dict[Tuple[float, ...], int], d2d.D2DPathSolution], float]] = None
propagation_priority_key: Optional[Callable[[Dict[Tuple[float, ...], int], Tuple[float, ...], Tuple[float, ...], d2d.D2DPathSolution], float]] = None
if namespace.propagation_priority == MIN_DISTANCE:
propagation_priority_key = _min_distance_key
elif namespace.propagation_priority == MAX_DISTANCE:
Expand Down
3 changes: 3 additions & 0 deletions ts/abc/multi_ob/costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ def __init__(self, initial: Optional[Iterable[_ST]] = None, /) -> None:
for s in initial:
self.add(s)

def keys(self) -> Iterable[Tuple[float, ...]]:
return self.__cost_to_solutions.keys()

def counter(self) -> Dict[Tuple[float, ...], int]:
"""Return a counter of the costs of the solutions in this set"""
return {k: len(v) for k, v in self.__cost_to_solutions.items()}
Expand Down
17 changes: 12 additions & 5 deletions ts/abc/multi_ob/solutions.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def tabu_search(
pool_size: int,
iterations_count: int,
use_tqdm: bool,
propagation_priority_key: Optional[Callable[[Dict[Tuple[float, ...], int], Self], float]] = None,
propagation_priority_key: Optional[Callable[[Dict[Tuple[float, ...], int], Tuple[float, ...], Tuple[float, ...], Self], float]] = None,
max_propagation: int,
plot_pareto_front: bool = False,
logger: Optional[Callable[[str], Any]] = None,
Expand All @@ -65,8 +65,12 @@ def tabu_search(
use_tqdm:
Whether to display the progress bar
propagation_priority_key:
A function taking 2 arguments: The first one is the counter of costs of current Pareto-optimal solutions, the second one is
the solution S. The less the returned value, the more likely the solution S will be added to the propagation tree.
A function taking 4 arguments:
- The counter of costs of current Pareto-optimal solutions
- The minimum value for each dimension of the Pareto front
- The maximum value for each dimension of the Pareto front
- The solution S
The less the returned value, the more likely the solution S will be added to the propagation tree.
max_propagation:
An integer or a function that takes the current Pareto front as a single parameter and return the maximum number of
propagating solutions at a time
Expand Down Expand Up @@ -95,7 +99,8 @@ def tabu_search(

current = [initial]
candidate_costs = {initial.cost()} if plot_pareto_front else None
if len(initial.cost()) != 2:
dimensions = len(initial.cost())
if dimensions != 2:
message = "Cannot plot the Pareto front when the number of objectives is not 2"
raise ValueError(message)

Expand Down Expand Up @@ -152,7 +157,9 @@ def process_solution(solution: Self) -> bool:
propagate = [solution.shuffle(use_tqdm=use_tqdm, logger=logger) for solution in current]

if propagation_priority_key is not None:
propagate.sort(key=partial(propagation_priority_key, results.counter()))
minimum = tuple(min(cost[i] for cost in results.keys()) for i in range(dimensions))
maximum = tuple(max(cost[i] for cost in results.keys()) for i in range(dimensions))
propagate.sort(key=partial(propagation_priority_key, results.counter(), minimum, maximum))

else:
random.shuffle(propagate)
Expand Down

0 comments on commit cb08b06

Please sign in to comment.