Skip to content

Conversation

@thomaswmorris
Copy link
Contributor

And remove outdated TSP dependencies

Copy link
Contributor

@thopkins32 thopkins32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far. I made a few comments/suggestions.

Also needed before merge:

  • Unit tests
    • Discrete suggestions
    • Validate "_id" keys are consistent after the reordering
  • API reference docs

Comment on lines +109 to +110
if route and n_points > 1:
suggestions = route_suggestions(suggestions)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can read the current positions, we can include that in the graph for the optimal routing, otherwise, we can fallback to routing the rest.

Suggested change
if route and n_points > 1:
suggestions = route_suggestions(suggestions)
if route and n_points > 1:
if all(isinstance(actuator, Readable) for actuator in actuators):
current_pos = yield from read(cast(Sequence[Readable], actuators))
else:
current_pos = None
suggestions = route_suggestions(suggestions, starting_point=current_pos)

for j, j_point in enumerate(points):
if i >= j:
continue
G.add_weighted_edges_from([(i, j, np.sqrt(np.sum(np.square(i_point - j_point))))])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part assumes all suggestions are floats when they can also be discrete choices (like strings). Need to add filtering so we only route based on distances we can compute, along with unit test coverage for the variety of cases.

Comment on lines +15 to +18
return np.array(nx.approximation.traveling_salesman_problem(G, cycle=cycle))


def route_suggestions(suggestions: list[dict], cycle: bool = False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we will ever need to return to the first point.

Suggested change
return np.array(nx.approximation.traveling_salesman_problem(G, cycle=cycle))
def route_suggestions(suggestions: list[dict], cycle: bool = False):
return np.array(nx.approximation.traveling_salesman_problem(G, cycle=False))
def route_suggestions(suggestions: list[dict]):

if route and n_points > 1:
suggestions = route_suggestions(suggestions)

uid = yield from acquisition_plan(suggestions, actuators, optimization_problem.sensors, *args, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to have this in default_acquire rather than optimize_step.

I know that in the future when sending plans to the queueserver, you will have to use default_acquire over optimize_step, since the optimizer class is not serializable. We will want the routing available in the queueserver.

It also makes it really easy to opt-out of any routing by bringing your own custom acquisition plan.



def route_suggestions(suggestions: list[dict], cycle: bool = False):
dims = [dim for dim in suggestions[0] if dim != "_id"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can import the ID_KEY and use it here

Suggested change
dims = [dim for dim in suggestions[0] if dim != "_id"]
dims = [dim for dim in suggestions[0] if dim != ID_KEY]

@thopkins32 thopkins32 mentioned this pull request Dec 21, 2025
16 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants