agentevolve-optimizer 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_evolve/__init__.py +722 -0
- agent_evolve/agentic.py +2800 -0
- agent_evolve/api.py +767 -0
- agent_evolve/application/__init__.py +1580 -0
- agent_evolve/application/action_allocation.py +744 -0
- agent_evolve/application/action_allocation_frame.py +347 -0
- agent_evolve/application/action_allocation_frame_commit.py +185 -0
- agent_evolve/application/action_allocation_frame_commit_v3.py +184 -0
- agent_evolve/application/action_allocation_frame_v3.py +338 -0
- agent_evolve/application/action_archive_value.py +497 -0
- agent_evolve/application/action_evidence_consistency.py +455 -0
- agent_evolve/application/action_forecast_partitioning.py +1471 -0
- agent_evolve/application/action_metric_projection.py +211 -0
- agent_evolve/application/action_role_value.py +680 -0
- agent_evolve/application/action_score_authorities.py +363 -0
- agent_evolve/application/action_structural_signature.py +116 -0
- agent_evolve/application/action_target_realization.py +402 -0
- agent_evolve/application/agentic_evolution.py +7734 -0
- agent_evolve/application/agentic_portfolio_residual_expert.py +835 -0
- agent_evolve/application/anchor_residual_identification.py +463 -0
- agent_evolve/application/archive_conditioned_action_target.py +208 -0
- agent_evolve/application/artifact_journal.py +246 -0
- agent_evolve/application/artifact_replay.py +347 -0
- agent_evolve/application/budgeted_optimizer.py +1828 -0
- agent_evolve/application/calibrated_campaign.py +485 -0
- agent_evolve/application/calibrated_current_prefix_forecast_opportunity.py +322 -0
- agent_evolve/application/calibrated_positive_gain_opportunity.py +1581 -0
- agent_evolve/application/campaign_capacity_recourse.py +254 -0
- agent_evolve/application/campaign_contextual_outcomes.py +119 -0
- agent_evolve/application/campaign_diagnostic_blocks.py +930 -0
- agent_evolve/application/campaign_evidence_registry.py +262 -0
- agent_evolve/application/campaign_execution.py +2537 -0
- agent_evolve/application/campaign_generation_audit.py +942 -0
- agent_evolve/application/campaign_learning.py +1812 -0
- agent_evolve/application/campaign_learning_runtime.py +1977 -0
- agent_evolve/application/campaign_search_phase.py +227 -0
- agent_evolve/application/campaign_selector_context_extension.py +220 -0
- agent_evolve/application/campaign_variation_envelope.py +649 -0
- agent_evolve/application/campaign_variation_trace.py +451 -0
- agent_evolve/application/candidate_archive_consequence.py +128 -0
- agent_evolve/application/causal_opportunity_portfolio_gate.py +385 -0
- agent_evolve/application/composite_outcome_updater.py +145 -0
- agent_evolve/application/composition_portfolio_selection.py +363 -0
- agent_evolve/application/concurrent_stage.py +144 -0
- agent_evolve/application/contextual_action_allocation.py +181 -0
- agent_evolve/application/contextual_campaign_outcomes.py +267 -0
- agent_evolve/application/contextual_campaign_planning.py +1366 -0
- agent_evolve/application/contextual_delayed_credit.py +651 -0
- agent_evolve/application/contextual_search_controller.py +2374 -0
- agent_evolve/application/current_prefix_forecast_opportunity.py +714 -0
- agent_evolve/application/decision_metric_projection.py +112 -0
- agent_evolve/application/derived_action_semantics.py +129 -0
- agent_evolve/application/detailed_evaluation.py +449 -0
- agent_evolve/application/earned_lineage.py +1011 -0
- agent_evolve/application/effective_choice_audit.py +484 -0
- agent_evolve/application/empirical_consequence_calibration.py +908 -0
- agent_evolve/application/evaluation_accounting.py +325 -0
- agent_evolve/application/evaluation_cache.py +199 -0
- agent_evolve/application/evaluation_escrow.py +547 -0
- agent_evolve/application/evaluation_recourse.py +253 -0
- agent_evolve/application/event_recorder.py +151 -0
- agent_evolve/application/evolution_campaign.py +1840 -0
- agent_evolve/application/executable_hypothesis.py +323 -0
- agent_evolve/application/factorial_branch_pilot.py +772 -0
- agent_evolve/application/finite_acquisition_capacity_recourse.py +672 -0
- agent_evolve/application/finite_acquisition_residual_expert.py +373 -0
- agent_evolve/application/finite_acquisition_variation_envelope.py +802 -0
- agent_evolve/application/finite_action_hypothesis_semantics.py +446 -0
- agent_evolve/application/finite_action_selection.py +188 -0
- agent_evolve/application/finite_action_set.py +306 -0
- agent_evolve/application/finite_action_transition.py +537 -0
- agent_evolve/application/finite_variation_eligibility.py +296 -0
- agent_evolve/application/forecast_geometry_portfolio.py +799 -0
- agent_evolve/application/forecast_opportunity_shadow_calibration.py +316 -0
- agent_evolve/application/front_proximity_admission.py +311 -0
- agent_evolve/application/front_proximity_parent_basis.py +458 -0
- agent_evolve/application/frozen_hurdle_score.py +659 -0
- agent_evolve/application/g3_causal_screen.py +2257 -0
- agent_evolve/application/g3_causal_validation.py +1046 -0
- agent_evolve/application/g3_postseal_curation.py +818 -0
- agent_evolve/application/gated_agentic_generator.py +205 -0
- agent_evolve/application/generation_feedback.py +293 -0
- agent_evolve/application/generative_proposal_journal.py +185 -0
- agent_evolve/application/geometry_conditional_elasticity.py +453 -0
- agent_evolve/application/global_wave_action_allocation.py +1151 -0
- agent_evolve/application/head_mass_conditional_seat.py +268 -0
- agent_evolve/application/identifiable_reflection_evidence.py +1147 -0
- agent_evolve/application/identifiable_reflection_learning.py +395 -0
- agent_evolve/application/identifiable_reflection_request.py +364 -0
- agent_evolve/application/in_memory_residual_archive.py +341 -0
- agent_evolve/application/insight_memory.py +1804 -0
- agent_evolve/application/live_runtime_manifest.py +758 -0
- agent_evolve/application/llm_task_queue.py +769 -0
- agent_evolve/application/matched_finite_action_block.py +409 -0
- agent_evolve/application/materialized_action_broker.py +2328 -0
- agent_evolve/application/materialized_action_constraints.py +83 -0
- agent_evolve/application/materialized_variation.py +211 -0
- agent_evolve/application/multi_option_evolution.py +1536 -0
- agent_evolve/application/outcome_adaptive_action_racing.py +2827 -0
- agent_evolve/application/outcome_adaptive_residual_campaign_runtime.py +580 -0
- agent_evolve/application/outcome_adaptive_residual_portfolio_evolution.py +3671 -0
- agent_evolve/application/outcome_conditioned_portfolio_selection.py +1374 -0
- agent_evolve/application/outcome_relation.py +193 -0
- agent_evolve/application/paired_allocation_comparison.py +241 -0
- agent_evolve/application/paired_block_schedule.py +127 -0
- agent_evolve/application/parent_measurement.py +226 -0
- agent_evolve/application/pareto_archive.py +811 -0
- agent_evolve/application/portfolio_campaign_runtime.py +4739 -0
- agent_evolve/application/portfolio_evolution.py +2950 -0
- agent_evolve/application/portfolio_hypothesis_observations.py +814 -0
- agent_evolve/application/portfolio_memory_attribution.py +581 -0
- agent_evolve/application/portfolio_memory_dose.py +788 -0
- agent_evolve/application/portfolio_memory_matched_control.py +938 -0
- agent_evolve/application/portfolio_memory_transfer.py +297 -0
- agent_evolve/application/portfolio_optimization_memory.py +363 -0
- agent_evolve/application/portfolio_outcome_feedback.py +1613 -0
- agent_evolve/application/portfolio_projection.py +335 -0
- agent_evolve/application/portfolio_recombination.py +2032 -0
- agent_evolve/application/post_evolution_reflection.py +834 -0
- agent_evolve/application/postcommit_rank_authority.py +245 -0
- agent_evolve/application/precommitted_portfolio_racing.py +2762 -0
- agent_evolve/application/prequential_archive_opportunity_calibration.py +1154 -0
- agent_evolve/application/prequential_residual_exploration.py +343 -0
- agent_evolve/application/prequential_score_portfolio.py +954 -0
- agent_evolve/application/projections.py +292 -0
- agent_evolve/application/protected_action_committee.py +1027 -0
- agent_evolve/application/protected_branch_pilot.py +376 -0
- agent_evolve/application/protected_current_prefix_forecast_opportunity.py +552 -0
- agent_evolve/application/provider_replay.py +910 -0
- agent_evolve/application/rank_balanced_causal_pilot.py +1372 -0
- agent_evolve/application/recombination_residual_expert.py +403 -0
- agent_evolve/application/reflection_workflow.py +571 -0
- agent_evolve/application/region_conditional_credit.py +911 -0
- agent_evolve/application/residual_campaign_runtime.py +531 -0
- agent_evolve/application/residual_headroom_campaign_runtime.py +459 -0
- agent_evolve/application/residual_headroom_ledger.py +1544 -0
- agent_evolve/application/residual_learning_transaction.py +396 -0
- agent_evolve/application/residual_portfolio_evolution.py +1228 -0
- agent_evolve/application/residual_reachability.py +749 -0
- agent_evolve/application/residual_stage_credit.py +499 -0
- agent_evolve/application/same_prefix_paired_audit.py +1580 -0
- agent_evolve/application/semantic_coverage_score_portfolio.py +838 -0
- agent_evolve/application/sequential_lineage_allocation.py +1017 -0
- agent_evolve/application/sequential_market_replay.py +1395 -0
- agent_evolve/application/sequential_residual_campaign_runtime.py +305 -0
- agent_evolve/application/sequential_residual_portfolio_evolution.py +940 -0
- agent_evolve/application/single_score_action_allocation.py +299 -0
- agent_evolve/application/source_exposure_allocation.py +906 -0
- agent_evolve/application/staged_memory.py +210 -0
- agent_evolve/application/stratified_cold_start_allocation.py +732 -0
- agent_evolve/application/support_guarded_hurdle_score.py +549 -0
- agent_evolve/application/target_conditioned_action_forecast.py +595 -0
- agent_evolve/application/target_conditioned_campaign.py +566 -0
- agent_evolve/application/treatment_assignment.py +201 -0
- agent_evolve/application/trusted_objective_evidence.py +217 -0
- agent_evolve/application/two_stage_action_evolution.py +1131 -0
- agent_evolve/application/v8lite_allocation_policy.py +1083 -0
- agent_evolve/application/v9_candidate_policy.py +1303 -0
- agent_evolve/bootstrap.py +108 -0
- agent_evolve/campaign_presets.py +517 -0
- agent_evolve/campaign_profiles.py +452 -0
- agent_evolve/campaign_variation_topology.py +288 -0
- agent_evolve/campaign_workload.py +950 -0
- agent_evolve/cli.py +797 -0
- agent_evolve/contract.py +241 -0
- agent_evolve/core/__init__.py +91 -0
- agent_evolve/core/action_semantics.py +411 -0
- agent_evolve/core/authored.py +105 -0
- agent_evolve/core/formatting.py +286 -0
- agent_evolve/core/optimization_semantics.py +324 -0
- agent_evolve/core/problem.py +167 -0
- agent_evolve/core/results.py +323 -0
- agent_evolve/core/stats.py +70 -0
- agent_evolve/core/telemetry.py +100 -0
- agent_evolve/domain/__init__.py +89 -0
- agent_evolve/domain/artifact.py +162 -0
- agent_evolve/domain/durable_text.py +68 -0
- agent_evolve/domain/event.py +1454 -0
- agent_evolve/domain/finite_action_set.py +426 -0
- agent_evolve/domain/finite_variation.py +526 -0
- agent_evolve/domain/generative_emission.py +559 -0
- agent_evolve/domain/ids.py +163 -0
- agent_evolve/domain/inline_text.py +106 -0
- agent_evolve/domain/insight.py +27 -0
- agent_evolve/domain/lineage.py +737 -0
- agent_evolve/domain/llm_task_queue.py +960 -0
- agent_evolve/domain/outcome.py +96 -0
- agent_evolve/domain/patch.py +854 -0
- agent_evolve/domain/typed_json.py +542 -0
- agent_evolve/domain/variation_space.py +158 -0
- agent_evolve/driver.py +1014 -0
- agent_evolve/harness/__init__.py +29 -0
- agent_evolve/harness/base.py +242 -0
- agent_evolve/harness/directives.py +163 -0
- agent_evolve/harness/generative_seal.py +479 -0
- agent_evolve/harness/registry.py +41 -0
- agent_evolve/infrastructure/__init__.py +39 -0
- agent_evolve/infrastructure/artifacts/__init__.py +6 -0
- agent_evolve/infrastructure/artifacts/_verification.py +67 -0
- agent_evolve/infrastructure/artifacts/filesystem.py +343 -0
- agent_evolve/infrastructure/artifacts/in_memory.py +73 -0
- agent_evolve/infrastructure/asyncio_runtime.py +109 -0
- agent_evolve/infrastructure/authored_runtime.py +188 -0
- agent_evolve/infrastructure/authored_worker.py +171 -0
- agent_evolve/infrastructure/clock.py +53 -0
- agent_evolve/infrastructure/events/__init__.py +6 -0
- agent_evolve/infrastructure/events/_validation.py +89 -0
- agent_evolve/infrastructure/events/in_memory.py +56 -0
- agent_evolve/infrastructure/events/jsonl.py +193 -0
- agent_evolve/infrastructure/exception_provenance.py +215 -0
- agent_evolve/infrastructure/ids.py +118 -0
- agent_evolve/infrastructure/lineage_codec.py +1836 -0
- agent_evolve/infrastructure/outcome_adaptive_phase_journal.py +170 -0
- agent_evolve/infrastructure/residual_headroom_journal.py +221 -0
- agent_evolve/infrastructure/resource_lease.py +370 -0
- agent_evolve/infrastructure/sanitization/__init__.py +8 -0
- agent_evolve/infrastructure/sanitization/strict_json.py +484 -0
- agent_evolve/infrastructure/sequential_phase_journal.py +170 -0
- agent_evolve/infrastructure/stream_liveness.py +383 -0
- agent_evolve/infrastructure/subprocess_boundary.py +136 -0
- agent_evolve/integrations/__init__.py +1 -0
- agent_evolve/integrations/botorch/__init__.py +28 -0
- agent_evolve/integrations/botorch/finite_qlognehvi.py +190 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch.py +155 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch_identity.py +20 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch_worker.py +55 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_identity.py +22 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_worker.py +55 -0
- agent_evolve/integrations/botorch/subprocess_qlognehvi.py +261 -0
- agent_evolve/integrations/botorch/subprocess_qlognehvi_batch.py +273 -0
- agent_evolve/integrations/completion.py +242 -0
- agent_evolve/integrations/pydantic_ai/__init__.py +441 -0
- agent_evolve/integrations/pydantic_ai/action_forecast.py +1068 -0
- agent_evolve/integrations/pydantic_ai/agentic_generator.py +2308 -0
- agent_evolve/integrations/pydantic_ai/async_generator.py +1604 -0
- agent_evolve/integrations/pydantic_ai/boundary_codec.py +1526 -0
- agent_evolve/integrations/pydantic_ai/calibrated_portfolio_campaign.py +756 -0
- agent_evolve/integrations/pydantic_ai/calibrated_portfolio_selection.py +7537 -0
- agent_evolve/integrations/pydantic_ai/campaign_acquisition.py +609 -0
- agent_evolve/integrations/pydantic_ai/execution_binding.py +138 -0
- agent_evolve/integrations/pydantic_ai/forecast_geometry_action_committee.py +217 -0
- agent_evolve/integrations/pydantic_ai/harness.py +159 -0
- agent_evolve/integrations/pydantic_ai/heterogeneous_model_execution.py +306 -0
- agent_evolve/integrations/pydantic_ai/hierarchical_residual_adaptive_semantic_view.py +179 -0
- agent_evolve/integrations/pydantic_ai/json_schema_dialect.py +108 -0
- agent_evolve/integrations/pydantic_ai/materialized_hierarchical_residual_expert.py +952 -0
- agent_evolve/integrations/pydantic_ai/materialized_portfolio_judge.py +520 -0
- agent_evolve/integrations/pydantic_ai/model_execution_profile.py +659 -0
- agent_evolve/integrations/pydantic_ai/outbound_request_manifest.py +1170 -0
- agent_evolve/integrations/pydantic_ai/portable_residual_consequence_features.py +575 -0
- agent_evolve/integrations/pydantic_ai/portfolio_selection.py +422 -0
- agent_evolve/integrations/pydantic_ai/progress_aware_openrouter.py +416 -0
- agent_evolve/integrations/pydantic_ai/provider_attempt_join.py +1523 -0
- agent_evolve/integrations/pydantic_ai/provider_free_calibrated_runner.py +607 -0
- agent_evolve/integrations/pydantic_ai/queued_runner.py +2634 -0
- agent_evolve/integrations/pydantic_ai/reconciled_residual_reachability.py +1417 -0
- agent_evolve/integrations/pydantic_ai/residual_forecast_geometry.py +445 -0
- agent_evolve/integrations/pydantic_ai/residual_reachability.py +674 -0
- agent_evolve/integrations/pydantic_ai/residual_semantic_cells.py +239 -0
- agent_evolve/integrations/pydantic_ai/sealed_output_replay.py +1068 -0
- agent_evolve/integrations/pydantic_ai/semantic_coverage_residual_portfolio.py +770 -0
- agent_evolve/integrations/pydantic_ai/semantic_decision_replay.py +383 -0
- agent_evolve/integrations/pydantic_ai/support_adaptive_residual_portfolio.py +135 -0
- agent_evolve/integrations/pydantic_ai/trusted_residual_prompt_context.py +143 -0
- agent_evolve/integrations/pydantic_ai/validated_openrouter_model.py +107 -0
- agent_evolve/integrations/pymoo_adapter.py +242 -0
- agent_evolve/policies/__init__.py +17 -0
- agent_evolve/policies/check.py +469 -0
- agent_evolve/policies/emit_scaffold.py +451 -0
- agent_evolve/policies/feedback/__init__.py +37 -0
- agent_evolve/policies/feedback/held_out_asn.py +1325 -0
- agent_evolve/policies/genetic.py +607 -0
- agent_evolve/policies/llm_backoff.py +183 -0
- agent_evolve/policies/llm_chooser.py +226 -0
- agent_evolve/policies/llm_generator.py +1760 -0
- agent_evolve/policies/llm_init.py +267 -0
- agent_evolve/policies/llm_operator.py +109 -0
- agent_evolve/policies/llm_prior.py +194 -0
- agent_evolve/policies/llm_surrogate.py +334 -0
- agent_evolve/policies/measurement_evidence.py +704 -0
- agent_evolve/policies/memory/__init__.py +223 -0
- agent_evolve/policies/memory/balanced_subset_blocks.py +707 -0
- agent_evolve/policies/memory/compatibility_matching.py +593 -0
- agent_evolve/policies/memory/global_falsification.py +1841 -0
- agent_evolve/policies/memory/prompt_shape.py +503 -0
- agent_evolve/policies/memory/randomized_subset.py +714 -0
- agent_evolve/policies/memory/staged_causal.py +1270 -0
- agent_evolve/policies/memory/treatment_compliance.py +759 -0
- agent_evolve/policies/objective_resolution/__init__.py +17 -0
- agent_evolve/policies/objective_resolution/fixed_grid.py +364 -0
- agent_evolve/policies/operator_portfolio.py +407 -0
- agent_evolve/policies/reguidance.py +1133 -0
- agent_evolve/policies/reward/__init__.py +83 -0
- agent_evolve/policies/reward/affine_candidate_consequence.py +156 -0
- agent_evolve/policies/reward/affine_candidate_consequence_3d.py +159 -0
- agent_evolve/policies/reward/affine_hypervolume.py +490 -0
- agent_evolve/policies/reward/affine_hypervolume_3d.py +567 -0
- agent_evolve/policies/reward/contextual_marginal_utility.py +318 -0
- agent_evolve/policies/reward/frozen_archive.py +360 -0
- agent_evolve/policies/reward/frozen_wave_archive.py +368 -0
- agent_evolve/policies/search_state.py +208 -0
- agent_evolve/policies/selection/__init__.py +345 -0
- agent_evolve/policies/selection/acquisition_certified_slate.py +684 -0
- agent_evolve/policies/selection/affine_frontier_context.py +330 -0
- agent_evolve/policies/selection/affine_frontier_target.py +473 -0
- agent_evolve/policies/selection/archive_elite.py +1346 -0
- agent_evolve/policies/selection/calibrated_portfolio_binding.py +640 -0
- agent_evolve/policies/selection/calibrated_slate.py +1394 -0
- agent_evolve/policies/selection/calibrated_slate_codec.py +579 -0
- agent_evolve/policies/selection/common_candidate_pool.py +685 -0
- agent_evolve/policies/selection/diagnostic_sampling.py +319 -0
- agent_evolve/policies/selection/disjoint_pairs.py +479 -0
- agent_evolve/policies/selection/elite_explorer.py +719 -0
- agent_evolve/policies/selection/finite_action.py +187 -0
- agent_evolve/policies/selection/finite_option_prompt_projection.py +377 -0
- agent_evolve/policies/selection/finite_palette_evidence.py +247 -0
- agent_evolve/policies/selection/forecast_calibration.py +922 -0
- agent_evolve/policies/selection/frontier_probe_slate.py +814 -0
- agent_evolve/policies/selection/frozen_archive_pairs.py +762 -0
- agent_evolve/policies/selection/full_support_slate.py +91 -0
- agent_evolve/policies/selection/meaningful_direction.py +240 -0
- agent_evolve/policies/selection/memory_dose_feasibility.py +259 -0
- agent_evolve/policies/selection/model_anchored_slate.py +826 -0
- agent_evolve/policies/selection/phenotype_recourse.py +979 -0
- agent_evolve/policies/selection/proposal_support.py +368 -0
- agent_evolve/policies/selection/random_portfolio.py +254 -0
- agent_evolve/policies/selection/regret_bounded_slate.py +1084 -0
- agent_evolve/policies/selection/residual_frontier.py +463 -0
- agent_evolve/policies/selection/residual_frontier_target.py +605 -0
- agent_evolve/policies/selection/structural_posterior_slate.py +1571 -0
- agent_evolve/policies/selection/target_conditioned_allocator.py +648 -0
- agent_evolve/policies/selection/target_conditioned_features.py +812 -0
- agent_evolve/policies/selection/target_conditioned_prequential.py +1527 -0
- agent_evolve/policies/selection/task_keyed_palette.py +906 -0
- agent_evolve/policies/semantics.py +147 -0
- agent_evolve/policies/structure.py +362 -0
- agent_evolve/policies/structured_output_budget.py +62 -0
- agent_evolve/policies/surrogate.py +696 -0
- agent_evolve/policies/variation/__init__.py +1 -0
- agent_evolve/policies/variation/compositional_finite_catalog.py +426 -0
- agent_evolve/policies/variation/crossover_inheritance.py +575 -0
- agent_evolve/policies/variation/disjoint_recombination.py +611 -0
- agent_evolve/policies/variation/exact_composition_capacity.py +214 -0
- agent_evolve/policies/variation/exact_parent_crossover.py +950 -0
- agent_evolve/policies/variation/multiscale_restart_catalog.py +372 -0
- agent_evolve/policies/variation/source_union_finite_catalog.py +403 -0
- agent_evolve/policies/variation/typed_patch.py +1981 -0
- agent_evolve/policies/weighted_prior.py +394 -0
- agent_evolve/ports/__init__.py +383 -0
- agent_evolve/ports/action_allocation.py +733 -0
- agent_evolve/ports/action_allocation_frame.py +1153 -0
- agent_evolve/ports/action_allocation_frame_commit.py +294 -0
- agent_evolve/ports/action_allocation_frame_commit_v3.py +432 -0
- agent_evolve/ports/action_allocation_frame_v3.py +995 -0
- agent_evolve/ports/action_forecast.py +1568 -0
- agent_evolve/ports/action_metric_projection.py +165 -0
- agent_evolve/ports/agentic_generator.py +1561 -0
- agent_evolve/ports/archive_context.py +136 -0
- agent_evolve/ports/artifact_sanitizer.py +44 -0
- agent_evolve/ports/artifact_store.py +225 -0
- agent_evolve/ports/clock.py +13 -0
- agent_evolve/ports/contextual_search_allocation.py +827 -0
- agent_evolve/ports/decision_metric_projection.py +258 -0
- agent_evolve/ports/event_store.py +55 -0
- agent_evolve/ports/executable_hypothesis.py +557 -0
- agent_evolve/ports/finite_acquisition.py +377 -0
- agent_evolve/ports/finite_acquisition_batch.py +296 -0
- agent_evolve/ports/finite_acquisition_batch_json.py +164 -0
- agent_evolve/ports/finite_acquisition_json.py +247 -0
- agent_evolve/ports/finite_acquisition_space.py +168 -0
- agent_evolve/ports/finite_action_selection.py +348 -0
- agent_evolve/ports/finite_action_set.py +256 -0
- agent_evolve/ports/frontier_target.py +396 -0
- agent_evolve/ports/generation_failure.py +43 -0
- agent_evolve/ports/hard_feasibility.py +233 -0
- agent_evolve/ports/id_factory.py +34 -0
- agent_evolve/ports/llm_task_queue.py +93 -0
- agent_evolve/ports/objective_resolution.py +419 -0
- agent_evolve/ports/paired_allocation_comparison.py +401 -0
- agent_evolve/ports/paired_block_schedule.py +475 -0
- agent_evolve/ports/parent_measurement.py +336 -0
- agent_evolve/ports/portfolio_memory_dose.py +643 -0
- agent_evolve/ports/portfolio_selection.py +3169 -0
- agent_evolve/ports/postcommit_rank_authority.py +467 -0
- agent_evolve/ports/presented_action_evidence.py +794 -0
- agent_evolve/ports/resource_lease.py +162 -0
- agent_evolve/ports/structured_generator.py +734 -0
- agent_evolve/ports/structured_output_budget.py +120 -0
- agent_evolve/ports/subprocess_boundary.py +138 -0
- agent_evolve/ports/treatment_assignment.py +466 -0
- agent_evolve/ports/variation_catalog.py +76 -0
- agent_evolve/ports/variation_source.py +226 -0
- agent_evolve/proposal_mode.py +157 -0
- agent_evolve/proposers/__init__.py +10 -0
- agent_evolve/proposers/random_proposer.py +188 -0
- agent_evolve/provider_accounting.py +163 -0
- agent_evolve/py.typed +0 -0
- agent_evolve/reference_method.py +1570 -0
- agent_evolve/session/__init__.py +11 -0
- agent_evolve/session/authorship.py +864 -0
- agent_evolve/session/evaluate.py +236 -0
- agent_evolve/session/fidelity.py +237 -0
- agent_evolve/session/genetic_loop.py +742 -0
- agent_evolve/session/loop.py +803 -0
- agent_evolve/session/screening.py +671 -0
- agent_evolve/settings.py +376 -0
- agent_evolve/workload_kit.py +368 -0
- agent_evolve/workload_prompt.py +398 -0
- agentevolve_optimizer-0.5.0.dist-info/METADATA +599 -0
- agentevolve_optimizer-0.5.0.dist-info/RECORD +414 -0
- agentevolve_optimizer-0.5.0.dist-info/WHEEL +5 -0
- agentevolve_optimizer-0.5.0.dist-info/entry_points.txt +2 -0
- agentevolve_optimizer-0.5.0.dist-info/licenses/LICENSE +21 -0
- agentevolve_optimizer-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
"""Rank-normalized, role-factorized value for small action portfolios.
|
|
2
|
+
|
|
3
|
+
One scalar acquisition law is brittle when consequence forecasts are weak:
|
|
4
|
+
optimistic uncertain actions can monopolize exploitation, while risk aversion
|
|
5
|
+
can suppress the global probes that discover new basins. This module assigns
|
|
6
|
+
each member of a small feasible portfolio to one of three workload-neutral
|
|
7
|
+
roles: reliable archive exploitation, residual bridging, or epistemic probing.
|
|
8
|
+
|
|
9
|
+
Role scores are empirical-CDF normalized over the sealed eligible forecast
|
|
10
|
+
snapshot. This avoids workload- and objective-scale weights. Two exploit
|
|
11
|
+
slots retain joint expected-hypervolume value; bridge and probe each receive a
|
|
12
|
+
protected slot. The ordinary feasible beam allocator still owns uniqueness,
|
|
13
|
+
family coverage, and patch compatibility.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import hashlib
|
|
19
|
+
import itertools
|
|
20
|
+
import json
|
|
21
|
+
import math
|
|
22
|
+
from dataclasses import dataclass, field
|
|
23
|
+
from enum import Enum
|
|
24
|
+
from functools import lru_cache
|
|
25
|
+
|
|
26
|
+
from agent_evolve.application.action_archive_value import (
|
|
27
|
+
ReliabilityAdjustedResidualCellExpectedHypervolumeUtility,
|
|
28
|
+
)
|
|
29
|
+
from agent_evolve.application.action_target_realization import (
|
|
30
|
+
ResidualTargetClosurePortfolioUtility,
|
|
31
|
+
)
|
|
32
|
+
from agent_evolve.domain.patch import require_sha256
|
|
33
|
+
from agent_evolve.ports.action_allocation import (
|
|
34
|
+
ForecastPortfolioUtilityBinding,
|
|
35
|
+
ForecastPortfolioUtilityInput,
|
|
36
|
+
ForecastQuantile,
|
|
37
|
+
)
|
|
38
|
+
from agent_evolve.ports.action_forecast import (
|
|
39
|
+
ActionForecastRequest,
|
|
40
|
+
ResolvedActionForecast,
|
|
41
|
+
ResolvedActionForecastBatch,
|
|
42
|
+
validate_resolved_action_forecasts,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
ROLE_FACTORIZED_ACTION_UTILITY_ID = "role_factorized_action_portfolio"
|
|
47
|
+
ROLE_FACTORIZED_ACTION_UTILITY_VERSION = 2
|
|
48
|
+
ROLE_FACTORIZED_ACTION_UTILITY_DEFINITION_SHA256 = hashlib.sha256(
|
|
49
|
+
b"agent-evolve:role-factorized-action-portfolio:v2;"
|
|
50
|
+
b"roles=reliable-archive-exploit,residual-bridge,epistemic-probe;"
|
|
51
|
+
b"slots=wave-budgeted-with-default-2,1,1;"
|
|
52
|
+
b"normalization=sealed-eligible-empirical-cdf-midrank;"
|
|
53
|
+
b"exploit=joint-reliability-adjusted-fixed-reference-hypervolume;"
|
|
54
|
+
b"bridge=singleton-residual-target-closure;"
|
|
55
|
+
b"probe=one-minus-weakest-target-metric-confidence;"
|
|
56
|
+
b"assignment=maximum-weight-injective-role-assignment;"
|
|
57
|
+
b"workload-model-provider-family-option-text-branches=false;outcomes=false"
|
|
58
|
+
).hexdigest()
|
|
59
|
+
_BINDING_DOMAIN = b"agent-evolve:role-factorized-action-binding:v2\x00"
|
|
60
|
+
_ELIGIBLE_DOMAIN = b"agent-evolve:role-factorized-eligible:v1\x00"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _canonical_json(value: object) -> bytes:
|
|
64
|
+
return json.dumps(
|
|
65
|
+
value,
|
|
66
|
+
allow_nan=False,
|
|
67
|
+
ensure_ascii=True,
|
|
68
|
+
separators=(",", ":"),
|
|
69
|
+
sort_keys=True,
|
|
70
|
+
).encode("ascii")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _finite(value: object, *, name: str) -> float:
|
|
74
|
+
if type(value) is not float or not math.isfinite(value):
|
|
75
|
+
raise TypeError(f"{name} must be a finite exact float")
|
|
76
|
+
return value
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ActionAcquisitionRole(str, Enum):
|
|
80
|
+
RELIABLE_ARCHIVE_EXPLOIT = "reliable_archive_exploit"
|
|
81
|
+
RESIDUAL_BRIDGE = "residual_bridge"
|
|
82
|
+
EPISTEMIC_PROBE = "epistemic_probe"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass(frozen=True, slots=True)
|
|
86
|
+
class RoleScoreRow:
|
|
87
|
+
option_id: str
|
|
88
|
+
exploit_rank_scores: tuple[float, float, float]
|
|
89
|
+
bridge_rank_scores: tuple[float, float, float]
|
|
90
|
+
probe_rank_score: float
|
|
91
|
+
|
|
92
|
+
def __post_init__(self) -> None:
|
|
93
|
+
if type(self.option_id) is not str or not self.option_id:
|
|
94
|
+
raise ValueError("option_id must be non-empty")
|
|
95
|
+
for name in ("exploit_rank_scores", "bridge_rank_scores"):
|
|
96
|
+
values = getattr(self, name)
|
|
97
|
+
if type(values) is not tuple or len(values) != 3:
|
|
98
|
+
raise ValueError(f"{name} must contain p10, p50, and p90")
|
|
99
|
+
for value in values:
|
|
100
|
+
_finite(value, name=name)
|
|
101
|
+
if not 0.0 <= value <= 1.0:
|
|
102
|
+
raise ValueError(f"{name} must lie in [0,1]")
|
|
103
|
+
_finite(self.probe_rank_score, name="probe_rank_score")
|
|
104
|
+
if not 0.0 <= self.probe_rank_score <= 1.0:
|
|
105
|
+
raise ValueError("probe_rank_score must lie in [0,1]")
|
|
106
|
+
|
|
107
|
+
def to_record(self) -> dict[str, object]:
|
|
108
|
+
self.__post_init__()
|
|
109
|
+
return {
|
|
110
|
+
"option_id": self.option_id,
|
|
111
|
+
"exploit_rank_scores_hex": [
|
|
112
|
+
value.hex() for value in self.exploit_rank_scores
|
|
113
|
+
],
|
|
114
|
+
"bridge_rank_scores_hex": [
|
|
115
|
+
value.hex() for value in self.bridge_rank_scores
|
|
116
|
+
],
|
|
117
|
+
"probe_rank_score_hex": self.probe_rank_score.hex(),
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@dataclass(frozen=True, slots=True)
|
|
122
|
+
class RoleAssignmentMember:
|
|
123
|
+
option_id: str
|
|
124
|
+
role: ActionAcquisitionRole
|
|
125
|
+
|
|
126
|
+
def __post_init__(self) -> None:
|
|
127
|
+
if type(self.option_id) is not str or not self.option_id:
|
|
128
|
+
raise ValueError("option_id must be non-empty")
|
|
129
|
+
if type(self.role) is not ActionAcquisitionRole:
|
|
130
|
+
raise TypeError("role must be an exact ActionAcquisitionRole")
|
|
131
|
+
|
|
132
|
+
def to_record(self) -> dict[str, str]:
|
|
133
|
+
self.__post_init__()
|
|
134
|
+
return {"option_id": self.option_id, "role": self.role.value}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(frozen=True, slots=True)
|
|
138
|
+
class RoleAssignmentAudit:
|
|
139
|
+
"""Receipt-bound explanation of one complete role assignment."""
|
|
140
|
+
|
|
141
|
+
utility_definition_sha256: str
|
|
142
|
+
forecast_receipt_sha256: str
|
|
143
|
+
quantile: ForecastQuantile
|
|
144
|
+
assignments: tuple[RoleAssignmentMember, ...]
|
|
145
|
+
utility_value: float
|
|
146
|
+
|
|
147
|
+
def __post_init__(self) -> None:
|
|
148
|
+
require_sha256(
|
|
149
|
+
self.utility_definition_sha256,
|
|
150
|
+
"utility_definition_sha256",
|
|
151
|
+
)
|
|
152
|
+
require_sha256(self.forecast_receipt_sha256, "forecast_receipt_sha256")
|
|
153
|
+
if type(self.quantile) is not ForecastQuantile:
|
|
154
|
+
raise TypeError("quantile must be an exact ForecastQuantile")
|
|
155
|
+
if type(self.assignments) is not tuple or not self.assignments:
|
|
156
|
+
raise ValueError("assignments must be a non-empty exact tuple")
|
|
157
|
+
for value in self.assignments:
|
|
158
|
+
if type(value) is not RoleAssignmentMember:
|
|
159
|
+
raise TypeError(
|
|
160
|
+
"assignments must contain exact RoleAssignmentMember values"
|
|
161
|
+
)
|
|
162
|
+
value.__post_init__()
|
|
163
|
+
option_ids = tuple(value.option_id for value in self.assignments)
|
|
164
|
+
if option_ids != tuple(sorted(set(option_ids))):
|
|
165
|
+
raise ValueError("assignments must use unique canonical option order")
|
|
166
|
+
_finite(self.utility_value, name="utility_value")
|
|
167
|
+
|
|
168
|
+
def to_record(self) -> dict[str, object]:
|
|
169
|
+
self.__post_init__()
|
|
170
|
+
return {
|
|
171
|
+
"schema_version": 1,
|
|
172
|
+
"utility_definition_sha256": self.utility_definition_sha256,
|
|
173
|
+
"forecast_receipt_sha256": self.forecast_receipt_sha256,
|
|
174
|
+
"quantile": self.quantile.value,
|
|
175
|
+
"assignments": [value.to_record() for value in self.assignments],
|
|
176
|
+
"utility_value_hex": self.utility_value.hex(),
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _quantile_index(value: ForecastQuantile) -> int:
|
|
181
|
+
if value is ForecastQuantile.P10:
|
|
182
|
+
return 0
|
|
183
|
+
if value is ForecastQuantile.P50:
|
|
184
|
+
return 1
|
|
185
|
+
if value is ForecastQuantile.P90:
|
|
186
|
+
return 2
|
|
187
|
+
raise TypeError("quantile must be exact")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _midrank_scores(values: dict[str, float]) -> dict[str, float]:
|
|
191
|
+
if not values:
|
|
192
|
+
raise ValueError("role score table cannot be empty")
|
|
193
|
+
ordered = sorted(values.values())
|
|
194
|
+
count = len(ordered)
|
|
195
|
+
result: dict[str, float] = {}
|
|
196
|
+
for option_id, value in values.items():
|
|
197
|
+
lower = sum(candidate < value for candidate in ordered)
|
|
198
|
+
equal = sum(candidate == value for candidate in ordered)
|
|
199
|
+
result[option_id] = (lower + 0.5 * equal) / count
|
|
200
|
+
return result
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@lru_cache(maxsize=32)
|
|
204
|
+
def _cached_role_sequences(
|
|
205
|
+
exploit_slots: int,
|
|
206
|
+
bridge_slots: int,
|
|
207
|
+
probe_slots: int,
|
|
208
|
+
member_count: int,
|
|
209
|
+
) -> tuple[tuple[ActionAcquisitionRole, ...], ...]:
|
|
210
|
+
slots = (
|
|
211
|
+
(ActionAcquisitionRole.RELIABLE_ARCHIVE_EXPLOIT,) * exploit_slots
|
|
212
|
+
+ (ActionAcquisitionRole.RESIDUAL_BRIDGE,) * bridge_slots
|
|
213
|
+
+ (ActionAcquisitionRole.EPISTEMIC_PROBE,) * probe_slots
|
|
214
|
+
)
|
|
215
|
+
return tuple(
|
|
216
|
+
sorted(
|
|
217
|
+
set(itertools.permutations(slots, member_count)),
|
|
218
|
+
key=lambda row: tuple(value.value for value in row),
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@dataclass(frozen=True, slots=True)
|
|
224
|
+
class RoleFactorizedActionPortfolioUtility:
|
|
225
|
+
"""Identified utility with an explicit workload-neutral role budget."""
|
|
226
|
+
|
|
227
|
+
exploit_utility: ReliabilityAdjustedResidualCellExpectedHypervolumeUtility
|
|
228
|
+
bridge_utility: ResidualTargetClosurePortfolioUtility
|
|
229
|
+
forecast_receipt_sha256: str
|
|
230
|
+
eligible_option_ids_sha256: str
|
|
231
|
+
score_rows: tuple[RoleScoreRow, ...]
|
|
232
|
+
exploit_denominators: tuple[tuple[float, ...], ...]
|
|
233
|
+
exploit_slots: int = 2
|
|
234
|
+
bridge_slots: int = 1
|
|
235
|
+
probe_slots: int = 1
|
|
236
|
+
_exploit_value_cache: dict[tuple[str, tuple[str, ...]], float] = field(
|
|
237
|
+
default_factory=dict,
|
|
238
|
+
init=False,
|
|
239
|
+
repr=False,
|
|
240
|
+
compare=False,
|
|
241
|
+
hash=False,
|
|
242
|
+
)
|
|
243
|
+
_row_cache: dict[str, RoleScoreRow] = field(
|
|
244
|
+
default_factory=dict,
|
|
245
|
+
init=False,
|
|
246
|
+
repr=False,
|
|
247
|
+
compare=False,
|
|
248
|
+
hash=False,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def __post_init__(self) -> None:
|
|
252
|
+
if (
|
|
253
|
+
type(self.exploit_utility)
|
|
254
|
+
is not ReliabilityAdjustedResidualCellExpectedHypervolumeUtility
|
|
255
|
+
):
|
|
256
|
+
raise TypeError("exploit_utility must be exact")
|
|
257
|
+
self.exploit_utility.__post_init__()
|
|
258
|
+
if type(self.bridge_utility) is not ResidualTargetClosurePortfolioUtility:
|
|
259
|
+
raise TypeError("bridge_utility must be exact")
|
|
260
|
+
self.bridge_utility.__post_init__()
|
|
261
|
+
require_sha256(self.forecast_receipt_sha256, "forecast_receipt_sha256")
|
|
262
|
+
require_sha256(
|
|
263
|
+
self.eligible_option_ids_sha256,
|
|
264
|
+
"eligible_option_ids_sha256",
|
|
265
|
+
)
|
|
266
|
+
if type(self.score_rows) is not tuple or not self.score_rows:
|
|
267
|
+
raise ValueError("score_rows must be non-empty")
|
|
268
|
+
for row in self.score_rows:
|
|
269
|
+
if type(row) is not RoleScoreRow:
|
|
270
|
+
raise TypeError("score_rows must contain exact RoleScoreRow values")
|
|
271
|
+
row.__post_init__()
|
|
272
|
+
option_ids = tuple(value.option_id for value in self.score_rows)
|
|
273
|
+
if option_ids != tuple(sorted(set(option_ids))):
|
|
274
|
+
raise ValueError("score_rows must use unique canonical option order")
|
|
275
|
+
for name in ("exploit_slots", "bridge_slots", "probe_slots"):
|
|
276
|
+
value = getattr(self, name)
|
|
277
|
+
if type(value) is not int or value < 0:
|
|
278
|
+
raise ValueError(f"{name} must be a non-negative exact integer")
|
|
279
|
+
if self.exploit_slots <= 0:
|
|
280
|
+
raise ValueError("role allocation requires at least one exploit slot")
|
|
281
|
+
if self.bridge_slots > 1 or self.probe_slots > 1:
|
|
282
|
+
raise ValueError("v2 supports at most one protected bridge/probe slot")
|
|
283
|
+
if self.portfolio_size > 8:
|
|
284
|
+
raise ValueError("role-factorized portfolios are bounded to eight")
|
|
285
|
+
if (
|
|
286
|
+
type(self.exploit_denominators) is not tuple
|
|
287
|
+
or len(self.exploit_denominators) != 3
|
|
288
|
+
):
|
|
289
|
+
raise ValueError("exploit_denominators must contain three quantiles")
|
|
290
|
+
for values in self.exploit_denominators:
|
|
291
|
+
if type(values) is not tuple or len(values) != self.exploit_slots:
|
|
292
|
+
raise ValueError("exploit denominator width differs from slots")
|
|
293
|
+
previous = 0.0
|
|
294
|
+
for value in values:
|
|
295
|
+
_finite(value, name="exploit denominator")
|
|
296
|
+
if value < previous or value < 0.0:
|
|
297
|
+
raise ValueError(
|
|
298
|
+
"exploit denominators must be cumulative and non-negative"
|
|
299
|
+
)
|
|
300
|
+
previous = value
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def portfolio_size(self) -> int:
|
|
304
|
+
return self.exploit_slots + self.bridge_slots + self.probe_slots
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def binding_definition_sha256(self) -> str:
|
|
308
|
+
self.__post_init__()
|
|
309
|
+
payload = {
|
|
310
|
+
"schema_version": 1,
|
|
311
|
+
"base_policy_definition_sha256": (
|
|
312
|
+
ROLE_FACTORIZED_ACTION_UTILITY_DEFINITION_SHA256
|
|
313
|
+
),
|
|
314
|
+
"exploit_utility_definition_sha256": (
|
|
315
|
+
self.exploit_utility.binding_definition_sha256
|
|
316
|
+
),
|
|
317
|
+
"bridge_utility_definition_sha256": (
|
|
318
|
+
self.bridge_utility.binding_definition_sha256
|
|
319
|
+
),
|
|
320
|
+
"forecast_receipt_sha256": self.forecast_receipt_sha256,
|
|
321
|
+
"eligible_option_ids_sha256": self.eligible_option_ids_sha256,
|
|
322
|
+
"role_slots": {
|
|
323
|
+
ActionAcquisitionRole.RELIABLE_ARCHIVE_EXPLOIT.value: (
|
|
324
|
+
self.exploit_slots
|
|
325
|
+
),
|
|
326
|
+
ActionAcquisitionRole.RESIDUAL_BRIDGE.value: self.bridge_slots,
|
|
327
|
+
ActionAcquisitionRole.EPISTEMIC_PROBE.value: self.probe_slots,
|
|
328
|
+
},
|
|
329
|
+
"score_rows": [value.to_record() for value in self.score_rows],
|
|
330
|
+
"exploit_denominators_hex": [
|
|
331
|
+
[value.hex() for value in row]
|
|
332
|
+
for row in self.exploit_denominators
|
|
333
|
+
],
|
|
334
|
+
}
|
|
335
|
+
return hashlib.sha256(
|
|
336
|
+
_BINDING_DOMAIN + _canonical_json(payload)
|
|
337
|
+
).hexdigest()
|
|
338
|
+
|
|
339
|
+
def binding(self) -> ForecastPortfolioUtilityBinding:
|
|
340
|
+
return ForecastPortfolioUtilityBinding(
|
|
341
|
+
utility=self,
|
|
342
|
+
policy_id=ROLE_FACTORIZED_ACTION_UTILITY_ID,
|
|
343
|
+
policy_version=ROLE_FACTORIZED_ACTION_UTILITY_VERSION,
|
|
344
|
+
definition_sha256=self.binding_definition_sha256,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
@property
|
|
348
|
+
def _rows_by_id(self) -> dict[str, RoleScoreRow]:
|
|
349
|
+
if not self._row_cache:
|
|
350
|
+
self._row_cache.update(
|
|
351
|
+
(value.option_id, value) for value in self.score_rows
|
|
352
|
+
)
|
|
353
|
+
return self._row_cache
|
|
354
|
+
|
|
355
|
+
def _role_sequences(
|
|
356
|
+
self,
|
|
357
|
+
member_count: int,
|
|
358
|
+
) -> tuple[tuple[ActionAcquisitionRole, ...], ...]:
|
|
359
|
+
if not 0 < member_count <= self.portfolio_size:
|
|
360
|
+
raise ValueError("member_count lies outside the role portfolio")
|
|
361
|
+
return _cached_role_sequences(
|
|
362
|
+
self.exploit_slots,
|
|
363
|
+
self.bridge_slots,
|
|
364
|
+
self.probe_slots,
|
|
365
|
+
member_count,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
def _subinput(
|
|
369
|
+
self,
|
|
370
|
+
request: ForecastPortfolioUtilityInput,
|
|
371
|
+
members: tuple[ResolvedActionForecast, ...],
|
|
372
|
+
) -> ForecastPortfolioUtilityInput:
|
|
373
|
+
return ForecastPortfolioUtilityInput(
|
|
374
|
+
optimization_semantics=request.optimization_semantics,
|
|
375
|
+
parent_metric_values=request.parent_metric_values,
|
|
376
|
+
metric_scales=request.metric_scales,
|
|
377
|
+
members=members,
|
|
378
|
+
quantile=request.quantile,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
def _assignment_score(
|
|
382
|
+
self,
|
|
383
|
+
request: ForecastPortfolioUtilityInput,
|
|
384
|
+
roles: tuple[ActionAcquisitionRole, ...],
|
|
385
|
+
*,
|
|
386
|
+
rows: dict[str, RoleScoreRow],
|
|
387
|
+
) -> float:
|
|
388
|
+
index = _quantile_index(request.quantile)
|
|
389
|
+
exploit_members = tuple(
|
|
390
|
+
member
|
|
391
|
+
for member, role in zip(request.members, roles, strict=True)
|
|
392
|
+
if role is ActionAcquisitionRole.RELIABLE_ARCHIVE_EXPLOIT
|
|
393
|
+
)
|
|
394
|
+
score = 0.0
|
|
395
|
+
if exploit_members:
|
|
396
|
+
cache_key = (
|
|
397
|
+
request.quantile.value,
|
|
398
|
+
tuple(value.option_id for value in exploit_members),
|
|
399
|
+
)
|
|
400
|
+
raw = self._exploit_value_cache.get(cache_key)
|
|
401
|
+
if raw is None:
|
|
402
|
+
raw = self.exploit_utility(
|
|
403
|
+
self._subinput(request, exploit_members)
|
|
404
|
+
)
|
|
405
|
+
self._exploit_value_cache[cache_key] = raw
|
|
406
|
+
denominator = self.exploit_denominators[index][
|
|
407
|
+
len(exploit_members) - 1
|
|
408
|
+
]
|
|
409
|
+
if denominator > 0.0:
|
|
410
|
+
score += len(exploit_members) * min(1.0, raw / denominator)
|
|
411
|
+
else:
|
|
412
|
+
score += sum(
|
|
413
|
+
rows[value.option_id].exploit_rank_scores[index]
|
|
414
|
+
for value in exploit_members
|
|
415
|
+
)
|
|
416
|
+
for member, role in zip(request.members, roles, strict=True):
|
|
417
|
+
row = rows.get(member.option_id)
|
|
418
|
+
if row is None:
|
|
419
|
+
raise ValueError("utility member is outside the sealed score table")
|
|
420
|
+
if role is ActionAcquisitionRole.RESIDUAL_BRIDGE:
|
|
421
|
+
score += row.bridge_rank_scores[index]
|
|
422
|
+
elif role is ActionAcquisitionRole.EPISTEMIC_PROBE:
|
|
423
|
+
score += row.probe_rank_score
|
|
424
|
+
if not math.isfinite(score):
|
|
425
|
+
raise RuntimeError("role assignment score became non-finite")
|
|
426
|
+
return float(score)
|
|
427
|
+
|
|
428
|
+
def _best_assignment(
|
|
429
|
+
self,
|
|
430
|
+
request: ForecastPortfolioUtilityInput,
|
|
431
|
+
) -> tuple[tuple[ActionAcquisitionRole, ...], float]:
|
|
432
|
+
rows = self._rows_by_id
|
|
433
|
+
if any(member.option_id not in rows for member in request.members):
|
|
434
|
+
raise ValueError("utility member is outside the sealed score table")
|
|
435
|
+
best_roles: tuple[ActionAcquisitionRole, ...] | None = None
|
|
436
|
+
best_score: float | None = None
|
|
437
|
+
for roles in self._role_sequences(len(request.members)):
|
|
438
|
+
score = self._assignment_score(request, roles, rows=rows)
|
|
439
|
+
if best_score is None or score > best_score:
|
|
440
|
+
best_roles = roles
|
|
441
|
+
best_score = score
|
|
442
|
+
if best_roles is None or best_score is None:
|
|
443
|
+
raise AssertionError("role assignment search produced no assignment")
|
|
444
|
+
return best_roles, best_score
|
|
445
|
+
|
|
446
|
+
def assign_roles(
|
|
447
|
+
self,
|
|
448
|
+
request: ForecastPortfolioUtilityInput,
|
|
449
|
+
) -> tuple[RoleAssignmentMember, ...]:
|
|
450
|
+
if type(request) is not ForecastPortfolioUtilityInput:
|
|
451
|
+
raise TypeError("request must be exact ForecastPortfolioUtilityInput")
|
|
452
|
+
request.__post_init__()
|
|
453
|
+
self.__post_init__()
|
|
454
|
+
if len(request.members) > self.portfolio_size:
|
|
455
|
+
raise ValueError("members exceed the role portfolio size")
|
|
456
|
+
best_roles, _ = self._best_assignment(request)
|
|
457
|
+
return tuple(
|
|
458
|
+
RoleAssignmentMember(member.option_id, role)
|
|
459
|
+
for member, role in zip(request.members, best_roles, strict=True)
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
def __call__(self, request: ForecastPortfolioUtilityInput) -> float:
|
|
463
|
+
if type(request) is not ForecastPortfolioUtilityInput:
|
|
464
|
+
raise TypeError("request must be exact")
|
|
465
|
+
if len(request.members) > self.portfolio_size:
|
|
466
|
+
raise ValueError("members exceed the role portfolio size")
|
|
467
|
+
_, score = self._best_assignment(request)
|
|
468
|
+
return score
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def build_role_factorized_action_utility(
|
|
472
|
+
*,
|
|
473
|
+
forecast_request: ActionForecastRequest,
|
|
474
|
+
forecasts: ResolvedActionForecastBatch,
|
|
475
|
+
eligible_option_ids: tuple[str, ...],
|
|
476
|
+
exploit_utility: ReliabilityAdjustedResidualCellExpectedHypervolumeUtility,
|
|
477
|
+
bridge_utility: ResidualTargetClosurePortfolioUtility,
|
|
478
|
+
exploit_slots: int = 2,
|
|
479
|
+
bridge_slots: int = 1,
|
|
480
|
+
probe_slots: int = 1,
|
|
481
|
+
) -> RoleFactorizedActionPortfolioUtility:
|
|
482
|
+
"""Freeze rank-normalized role evidence from one forecast cutoff."""
|
|
483
|
+
|
|
484
|
+
if type(forecast_request) is not ActionForecastRequest:
|
|
485
|
+
raise TypeError("forecast_request must be exact")
|
|
486
|
+
forecast_request.__post_init__()
|
|
487
|
+
if type(forecasts) is not ResolvedActionForecastBatch:
|
|
488
|
+
raise TypeError("forecasts must be exact")
|
|
489
|
+
validate_resolved_action_forecasts(forecast_request, forecasts)
|
|
490
|
+
if (
|
|
491
|
+
type(eligible_option_ids) is not tuple
|
|
492
|
+
or not eligible_option_ids
|
|
493
|
+
or eligible_option_ids != tuple(sorted(set(eligible_option_ids)))
|
|
494
|
+
):
|
|
495
|
+
raise ValueError("eligible_option_ids must be a non-empty canonical tuple")
|
|
496
|
+
by_id = {value.option_id: value for value in forecasts.forecasts}
|
|
497
|
+
if not set(eligible_option_ids).issubset(by_id):
|
|
498
|
+
raise ValueError("eligible_option_ids contains a foreign forecast")
|
|
499
|
+
if (
|
|
500
|
+
type(exploit_utility)
|
|
501
|
+
is not ReliabilityAdjustedResidualCellExpectedHypervolumeUtility
|
|
502
|
+
):
|
|
503
|
+
raise TypeError("exploit_utility must be exact")
|
|
504
|
+
exploit_utility.__post_init__()
|
|
505
|
+
if type(bridge_utility) is not ResidualTargetClosurePortfolioUtility:
|
|
506
|
+
raise TypeError("bridge_utility must be exact")
|
|
507
|
+
bridge_utility.__post_init__()
|
|
508
|
+
if type(exploit_slots) is not int or exploit_slots <= 0:
|
|
509
|
+
raise ValueError("exploit_slots must be a positive exact integer")
|
|
510
|
+
for name, value in (
|
|
511
|
+
("bridge_slots", bridge_slots),
|
|
512
|
+
("probe_slots", probe_slots),
|
|
513
|
+
):
|
|
514
|
+
if type(value) is not int or not 0 <= value <= 1:
|
|
515
|
+
raise ValueError(f"{name} must be zero or one")
|
|
516
|
+
if exploit_slots + bridge_slots + probe_slots > 8:
|
|
517
|
+
raise ValueError("role-factorized portfolios are bounded to eight")
|
|
518
|
+
|
|
519
|
+
quantiles = (
|
|
520
|
+
ForecastQuantile.P10,
|
|
521
|
+
ForecastQuantile.P50,
|
|
522
|
+
ForecastQuantile.P90,
|
|
523
|
+
)
|
|
524
|
+
exploit_raw: list[dict[str, float]] = []
|
|
525
|
+
bridge_raw: list[dict[str, float]] = []
|
|
526
|
+
for quantile in quantiles:
|
|
527
|
+
exploit_values: dict[str, float] = {}
|
|
528
|
+
bridge_values: dict[str, float] = {}
|
|
529
|
+
for option_id in eligible_option_ids:
|
|
530
|
+
member = by_id[option_id]
|
|
531
|
+
query = ForecastPortfolioUtilityInput(
|
|
532
|
+
optimization_semantics=forecast_request.optimization_semantics,
|
|
533
|
+
parent_metric_values=forecast_request.parent_metric_values,
|
|
534
|
+
metric_scales=forecast_request.metric_scales,
|
|
535
|
+
members=(member,),
|
|
536
|
+
quantile=quantile,
|
|
537
|
+
)
|
|
538
|
+
exploit_values[option_id] = exploit_utility(query)
|
|
539
|
+
bridge_values[option_id] = bridge_utility(query)
|
|
540
|
+
exploit_raw.append(exploit_values)
|
|
541
|
+
bridge_raw.append(bridge_values)
|
|
542
|
+
exploit_ranks = tuple(_midrank_scores(value) for value in exploit_raw)
|
|
543
|
+
bridge_ranks = tuple(_midrank_scores(value) for value in bridge_raw)
|
|
544
|
+
|
|
545
|
+
probe_raw: dict[str, float] = {}
|
|
546
|
+
target_forecast_ids = {
|
|
547
|
+
value.forecast_metric_id for value in exploit_utility.aliases
|
|
548
|
+
} or set(exploit_utility.target.metric_ids)
|
|
549
|
+
for option_id in eligible_option_ids:
|
|
550
|
+
member = by_id[option_id]
|
|
551
|
+
metric_by_id = {
|
|
552
|
+
value.metric_id: value for value in member.metric_forecasts
|
|
553
|
+
}
|
|
554
|
+
if not target_forecast_ids.issubset(metric_by_id):
|
|
555
|
+
raise ValueError("forecast omits a target metric for probing")
|
|
556
|
+
probe_raw[option_id] = 1.0 - min(
|
|
557
|
+
metric_by_id[metric_id].confidence
|
|
558
|
+
for metric_id in target_forecast_ids
|
|
559
|
+
)
|
|
560
|
+
probe_ranks = _midrank_scores(probe_raw)
|
|
561
|
+
|
|
562
|
+
score_rows = tuple(
|
|
563
|
+
RoleScoreRow(
|
|
564
|
+
option_id=option_id,
|
|
565
|
+
exploit_rank_scores=tuple(
|
|
566
|
+
values[option_id] for values in exploit_ranks
|
|
567
|
+
), # type: ignore[arg-type]
|
|
568
|
+
bridge_rank_scores=tuple(
|
|
569
|
+
values[option_id] for values in bridge_ranks
|
|
570
|
+
), # type: ignore[arg-type]
|
|
571
|
+
probe_rank_score=probe_ranks[option_id],
|
|
572
|
+
)
|
|
573
|
+
for option_id in eligible_option_ids
|
|
574
|
+
)
|
|
575
|
+
denominators: list[tuple[float, ...]] = []
|
|
576
|
+
for values in exploit_raw:
|
|
577
|
+
ordered = sorted(values.values(), reverse=True)
|
|
578
|
+
cumulative = []
|
|
579
|
+
total = 0.0
|
|
580
|
+
for index in range(exploit_slots):
|
|
581
|
+
total += ordered[index] if index < len(ordered) else 0.0
|
|
582
|
+
cumulative.append(float(total))
|
|
583
|
+
denominators.append(tuple(cumulative))
|
|
584
|
+
eligible_sha256 = hashlib.sha256(
|
|
585
|
+
_ELIGIBLE_DOMAIN
|
|
586
|
+
+ _canonical_json({"eligible_option_ids": list(eligible_option_ids)})
|
|
587
|
+
).hexdigest()
|
|
588
|
+
return RoleFactorizedActionPortfolioUtility(
|
|
589
|
+
exploit_utility=exploit_utility,
|
|
590
|
+
bridge_utility=bridge_utility,
|
|
591
|
+
forecast_receipt_sha256=forecasts.receipt_sha256,
|
|
592
|
+
eligible_option_ids_sha256=eligible_sha256,
|
|
593
|
+
score_rows=score_rows,
|
|
594
|
+
exploit_denominators=tuple(denominators),
|
|
595
|
+
exploit_slots=exploit_slots,
|
|
596
|
+
bridge_slots=bridge_slots,
|
|
597
|
+
probe_slots=probe_slots,
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def audit_role_factorized_action_portfolio(
|
|
602
|
+
*,
|
|
603
|
+
utility: RoleFactorizedActionPortfolioUtility,
|
|
604
|
+
forecast_request: ActionForecastRequest,
|
|
605
|
+
forecasts: ResolvedActionForecastBatch,
|
|
606
|
+
selected_option_ids: tuple[str, ...],
|
|
607
|
+
) -> tuple[RoleAssignmentAudit, ...]:
|
|
608
|
+
"""Explain a final portfolio at all forecast quantiles without outcomes."""
|
|
609
|
+
|
|
610
|
+
if type(utility) is not RoleFactorizedActionPortfolioUtility:
|
|
611
|
+
raise TypeError("utility must be exact")
|
|
612
|
+
utility.__post_init__()
|
|
613
|
+
if type(forecast_request) is not ActionForecastRequest:
|
|
614
|
+
raise TypeError("forecast_request must be exact")
|
|
615
|
+
forecast_request.__post_init__()
|
|
616
|
+
if type(forecasts) is not ResolvedActionForecastBatch:
|
|
617
|
+
raise TypeError("forecasts must be exact")
|
|
618
|
+
validate_resolved_action_forecasts(forecast_request, forecasts)
|
|
619
|
+
if forecasts.receipt_sha256 != utility.forecast_receipt_sha256:
|
|
620
|
+
raise ValueError("utility belongs to a foreign forecast receipt")
|
|
621
|
+
if (
|
|
622
|
+
type(selected_option_ids) is not tuple
|
|
623
|
+
or selected_option_ids != tuple(sorted(set(selected_option_ids)))
|
|
624
|
+
or len(selected_option_ids) != utility.portfolio_size
|
|
625
|
+
):
|
|
626
|
+
raise ValueError(
|
|
627
|
+
"selected_option_ids must be one complete canonical role portfolio"
|
|
628
|
+
)
|
|
629
|
+
by_id = {value.option_id: value for value in forecasts.forecasts}
|
|
630
|
+
if not set(selected_option_ids).issubset(by_id):
|
|
631
|
+
raise ValueError("selected_option_ids contains a foreign option")
|
|
632
|
+
members = tuple(
|
|
633
|
+
sorted(
|
|
634
|
+
(by_id[option_id] for option_id in selected_option_ids),
|
|
635
|
+
key=lambda value: (value.option_identity_sha256, value.option_id),
|
|
636
|
+
)
|
|
637
|
+
)
|
|
638
|
+
audits: list[RoleAssignmentAudit] = []
|
|
639
|
+
for quantile in (
|
|
640
|
+
ForecastQuantile.P10,
|
|
641
|
+
ForecastQuantile.P50,
|
|
642
|
+
ForecastQuantile.P90,
|
|
643
|
+
):
|
|
644
|
+
request = ForecastPortfolioUtilityInput(
|
|
645
|
+
optimization_semantics=forecast_request.optimization_semantics,
|
|
646
|
+
parent_metric_values=forecast_request.parent_metric_values,
|
|
647
|
+
metric_scales=forecast_request.metric_scales,
|
|
648
|
+
members=members,
|
|
649
|
+
quantile=quantile,
|
|
650
|
+
)
|
|
651
|
+
assignments = tuple(
|
|
652
|
+
sorted(
|
|
653
|
+
utility.assign_roles(request),
|
|
654
|
+
key=lambda value: value.option_id,
|
|
655
|
+
)
|
|
656
|
+
)
|
|
657
|
+
audits.append(
|
|
658
|
+
RoleAssignmentAudit(
|
|
659
|
+
utility_definition_sha256=utility.binding_definition_sha256,
|
|
660
|
+
forecast_receipt_sha256=forecasts.receipt_sha256,
|
|
661
|
+
quantile=quantile,
|
|
662
|
+
assignments=assignments,
|
|
663
|
+
utility_value=utility(request),
|
|
664
|
+
)
|
|
665
|
+
)
|
|
666
|
+
return tuple(audits)
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
__all__ = [
|
|
670
|
+
"ActionAcquisitionRole",
|
|
671
|
+
"ROLE_FACTORIZED_ACTION_UTILITY_DEFINITION_SHA256",
|
|
672
|
+
"ROLE_FACTORIZED_ACTION_UTILITY_ID",
|
|
673
|
+
"ROLE_FACTORIZED_ACTION_UTILITY_VERSION",
|
|
674
|
+
"RoleAssignmentAudit",
|
|
675
|
+
"RoleAssignmentMember",
|
|
676
|
+
"RoleFactorizedActionPortfolioUtility",
|
|
677
|
+
"RoleScoreRow",
|
|
678
|
+
"audit_role_factorized_action_portfolio",
|
|
679
|
+
"build_role_factorized_action_utility",
|
|
680
|
+
]
|