Контекст: я пытаюсь решить проблему планирования турниров.
Я хочу проанализировать решение, сгенерированное алгоритмом Timefold, но столкнулся с проблемой. проблема с сериализацией:
ScoreSerializer = PlainSerializer(lambda score: str(score) if score is not None else None,
return_type=str | None)
def validate_score(v: Any, info: ValidationInfo) -> Any:
logger.info(f"Validating score: type={type(v)}, value={v}")
if isinstance(v, HardMediumSoftDecimalScore) or v is None:
return v
if isinstance(v, str):
return HardMediumSoftDecimalScore.parse(v)
raise ValueError('"score" should be a string')
ScoreValidator = BeforeValidator(validate_score)
class JsonDomainBase(BaseModel):
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
from_attributes=True,
)
Как я могу решить эту проблему? Обновление:
Я пробовал реализовать CustomConstraintJustification для переопределения DefaultConstraintJustification, который вызывается по умолчанию следующим образом:
constraint.py:
INFO: @ uvicorn.access : 127.0.0.1:64450 - "PUT /schedules/analyze HTTP/1.1" 500
ERROR: @ uvicorn.error : Exception in ASGI application
Traceback (most recent call last):
File "SolutionManager.java", line 114, in ai.timefold.solver.core.api.solver.SolutionManager.analyze
ai.timefold.jpyinterpreter.types.errors.ai.timefold.jpyinterpreter.types.errors.AttributeError: ai.timefold.jpyinterpreter.types.errors.AttributeError: object '0' does not have attribute 'toPlainString'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "SolutionManager.java", line 114, in ai.timefold.solver.core.api.solver.SolutionManager.analyze
Exception: Java Exception
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 399, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[...]
File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/fastapi/routing.py", line 191, in run_endpoint_function
return await dependant.call(**values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/src/tournament_scheduling/rest_api.py", line 95, in analyze_timetable
analysis_result = solution_manager.analyze(tournament_schedule)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/timefold/solver/_solution_manager.py", line 89, in analyze
return ScoreAnalysis(self._delegate.analyze(convert_to_java_python_like_object(solution)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
java.lang.java.lang.IllegalStateException: java.lang.IllegalStateException: Consequence of a constraint (org.jpyinterpreter.user.tournament_scheduling.domain/evenlyConfrontationCount) threw an exception creating constraint justification from a tuple ({ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl@ebbd6d8}).
Я неправильно реализовал/применил пользовательскую ConstraintJustification? Или я что-то упускаю?
[b]Контекст[/b]: я пытаюсь решить проблему планирования турниров. Я хочу проанализировать решение, сгенерированное алгоритмом Timefold, но столкнулся с проблемой. проблема с сериализацией: [code]INFO: @ timefold_solver : Validating score: type=, value=0hard/-1.195230medium/-2.563480soft INFO: @ timefold_solver : Analysis result: Explanation of score (0hard/-1.19523medium/-2.56348soft): Constraint matches: -1.19523medium: constraint (fairAssignmentCountPerTeam) has 1 matches: -1.19523medium: justified with ([ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl@34afdb84]) -2.56348soft: constraint (evenlyConfrontationCount) has 1 matches: -2.56348soft: justified with ([ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl@3192c24f]) 0: constraint (oneAssignmentPerDatePerTeam) has no matches. 0: constraint (unavailabilityPenalty) has no matches.
[/code] Ниже приведен мой код (фрагмент кода, относящийся к этой проблеме): rest_api.py [code]async def setup_context(request: Request) -> TournamentSchedule: json = await request.json() return TournamentSchedule.model_validate(json, context={ 'teams': { team['id']: Team.model_validate(team) for team in json.get('teams', []) }, 'days': { day['dateIndex']: Day.model_validate(day) for day in json.get('days', []) } })
@app.put("/schedules/analyze") async def analyze_timetable(tournament_schedule: Annotated[TournamentSchedule, Depends(setup_context)]) -> dict: # Call the analyze method and log its raw output analysis_result = solution_manager.analyze(tournament_schedule) logger.info(f"Analysis result: {analysis_result}")
# Log detailed constraint analyses for constraint in analysis_result.constraint_analyses: logger.info( f"Constraint Analysis: {constraint.constraint_name}, Weight: {constraint.weight}, Score: {constraint.score}") for match in constraint.matches: logger.info( f" Match Analysis: {match.constraint_ref.constraint_name}, Score: {match.score}, Justification: {match.justification}")
return {'constraints': [ConstraintAnalysisDTO( name=constraint.constraint_name, weight=constraint.weight, score=constraint.score, matches=[ MatchAnalysisDTO( name=match.constraint_ref.constraint_name, score=match.score, justification=match.justification ) for match in constraint.matches ] ) for constraint in solution_manager.analyze(tournament_schedule).constraint_analyses]} [/code] json_serialization.py [code]ScoreSerializer = PlainSerializer(lambda score: str(score) if score is not None else None, return_type=str | None)
def validate_score(v: Any, info: ValidationInfo) -> Any: logger.info(f"Validating score: type={type(v)}, value={v}") if isinstance(v, HardMediumSoftDecimalScore) or v is None: return v if isinstance(v, str): return HardMediumSoftDecimalScore.parse(v) raise ValueError('"score" should be a string')
ScoreValidator = BeforeValidator(validate_score)
class JsonDomainBase(BaseModel): model_config = ConfigDict( alias_generator=to_camel, populate_by_name=True, from_attributes=True, ) [/code] domain.py [code]class Day(JsonDomainBase): date_index: int
class Team(JsonDomainBase): id: Annotated[int, PlanningId] name: Annotated[str, Field(default=None)]
class ConstraintAnalysisDTO(JsonDomainBase): name: str weight: Annotated[HardMediumSoftDecimalScore, ScoreSerializer] matches: list[MatchAnalysisDTO] score: Annotated[HardMediumSoftDecimalScore, ScoreSerializer] [/code] Как я могу решить эту проблему? [b]Обновление[/b]: Я пробовал реализовать CustomConstraintJustification для переопределения DefaultConstraintJustification, который вызывается по умолчанию следующим образом: constraint.py: [code]def fair_assignment_count_per_team(constraint_factory: ConstraintFactory) -> Constraint: return (constraint_factory .for_each(TeamAssignment) .group_by(ConstraintCollectors.load_balance(lambda team_assignment: team_assignment.team)) .penalize_decimal(HardMediumSoftDecimalScore.ONE_MEDIUM, lambda balance: balance.unfairness()) .justify_with(lambda balance, solution_score: CustomConstraintJustification(facts=("unfairness",), impact=solution_score)) .as_constraint("fairAssignmentCountPerTeam")) [/code] score_anaанализ.py: [code]from _jpyinterpreter import add_java_interface from timefold.solver.score import ConstraintJustification
@add_java_interface('ai.timefold.solver.core.api.score.stream.ConstraintJustification') class CustomConstraintJustification(ConstraintJustification): facts: tuple[Any, ...] impact: HardMediumSoftDecimalScore
class MatchAnalysisDTO(JsonDomainBase): name: str score: Annotated[HardMediumSoftDecimalScore, ScoreSerializer] justification: object
class ConstraintAnalysisDTO(JsonDomainBase): name: str weight: Annotated[HardMediumSoftDecimalScore, ScoreSerializer] matches: list[MatchAnalysisDTO] score: Annotated[HardMediumSoftDecimalScore, ScoreSerializer] [/code] Но сейчас я получил эту ошибку: [code]INFO: @ uvicorn.access : 127.0.0.1:64450 - "PUT /schedules/analyze HTTP/1.1" 500 ERROR: @ uvicorn.error : Exception in ASGI application Traceback (most recent call last): File "SolutionManager.java", line 114, in ai.timefold.solver.core.api.solver.SolutionManager.analyze ai.timefold.jpyinterpreter.types.errors.ai.timefold.jpyinterpreter.types.errors.AttributeError: ai.timefold.jpyinterpreter.types.errors.AttributeError: object '0' does not have attribute 'toPlainString'
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "SolutionManager.java", line 114, in ai.timefold.solver.core.api.solver.SolutionManager.analyze Exception: Java Exception
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 399, in run_asgi result = await app( # type: ignore[func-returns-value] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__ return await self.app(scope, receive, send) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [...] File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/fastapi/routing.py", line 191, in run_endpoint_function return await dependant.call(**values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/src/tournament_scheduling/rest_api.py", line 95, in analyze_timetable analysis_result = solution_manager.analyze(tournament_schedule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/user/Desktop/workspace/timefold-quickstarts/python/tournament-scheduling/.venv/lib/python3.11/site-packages/timefold/solver/_solution_manager.py", line 89, in analyze return ScoreAnalysis(self._delegate.analyze(convert_to_java_python_like_object(solution))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ java.lang.java.lang.IllegalStateException: java.lang.IllegalStateException: Consequence of a constraint (org.jpyinterpreter.user.tournament_scheduling.domain/evenlyConfrontationCount) threw an exception creating constraint justification from a tuple ({ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl@ebbd6d8}). [/code] Я неправильно реализовал/применил пользовательскую ConstraintJustification? Или я что-то упускаю?
Контекст : я пытаюсь решить проблему планирования турниров.
Я хочу проанализировать решение, сгенерированное алгоритмом Timefold, но столкнулся с проблемой. проблема с сериализацией:
INFO: @ timefold_solver : Validating score: type=,...
Контекст : я пытаюсь решить проблему планирования турниров.
Я хочу проанализировать решение, сгенерированное алгоритмом Timefold, но столкнулся с проблемой. проблема с сериализацией:
INFO: @ timefold_solver : Validating score: type=,...
Поскольку он не указан в качестве опции по адресу я предполагаю, что это не поддерживается. Некоторый код тестов заставил меня задуматься, поддерживается ли он?
Я работаю со сложными структурами данных с участием пользовательских классов, которые ссылаются друг на друга. В деструкторах или используйте SleedRef , чтобы избежать утечек памяти?
Для моего последнего магистерского проекта я пытаюсь выполнить дополнение данных в наборе данных тепловых изображений ( черно-белые ) для обнаружения рака молочной железы. Этот набор данных содержит только 280 изображений, которые можно...