198 auto state = std::make_unique<State>();
199 state->objective = objective;
200 state->cached = cached;
202 const double inf = std::numeric_limits<double>::infinity();
203 state->low.assign(dim, -inf);
204 state->high.assign(dim, inf);
211 state->desc.schema_id = state->schema.c_str();
212 state->desc.producer_id = state->producer.c_str();
213 state->desc.length_unit = state->length_unit.c_str();
214 state->desc.energy_unit = state->energy_unit.c_str();
220 state->desc.tensor_dtype_bits =
222 state->desc.tensor_dtype_lanes =
226 state->obj.dim = dim;
227 state->obj.low = state->low.data();
228 state->obj.high = state->high.data();
229 state->obj.eval_fn = eval_cb;
230 state->obj.grad_fn = grad_cb;
231 state->obj.user_data = state.get();
232 state->obj.free_fn =
nullptr;
233 state->obj.descriptor = &state->desc;
235 throw std::runtime_error(
"eOn eindir objective descriptor was rejected");
237 const auto stamp = eindir_core_abi_stamp();
238 if (eindir_core_abi_compatible(&stamp) == 0 ||
240 throw std::runtime_error(
"incompatible eindir ABI stamp");
242 if (eindir_objective_has_grad(&state->obj) == 0) {
243 throw std::runtime_error(
"eindir objective has no gradient");
245 eindir_objective_descriptor_t required_desc = state->desc;
246 required_desc.producer_id =
"";
247 if (eindir_objective_descriptor_compatible(&state->desc, &required_desc) ==
249 const char *err = eindir_last_error();
250 throw std::runtime_error(err !=
nullptr ? err
251 :
"eindir descriptor mismatch");
253 const auto xts = xts_abi_stamp();
255 std::format(
"xts-{}.{}.{}+eindir-{}.{}-layout-{}", xts.abi_major,
256 xts.abi_minor, xts.layout_revision, stamp.abi_major,
257 stamp.abi_minor, stamp.objective_layout);
258 return state.release();
270int eval_grad(State *state,
const DLManagedTensorVersioned *x,
double *value,
271 DLManagedTensorVersioned *gradient) {
279 if (state ==
nullptr) {
282 if (eindir_objective_eval(&state->obj, x, value) != EINDIR_SUCCESS ||
283 eindir_objective_grad(&state->obj, x, gradient) != EINDIR_SUCCESS) {
290int minimize(State *state,
double *x, std::size_t n, std::size_t maxiter,
291 double gtol,
double istep, std::size_t memory,
int method,
305 if (state ==
nullptr || x ==
nullptr) {
308 auto *tensor = xts_tensor_borrow_cpu_f64(x, n);
309 if (tensor ==
nullptr) {
312 const auto stamp = eindir_core_abi_stamp();
313 xts_control_t control{maxiter, gtol, istep, memory, 0.0};
314 xts_report_t report{};
316 xts_minimize_eindir(&state->obj, &stamp, tensor, &control,
317 static_cast<xts_method_t
>(method), &report);
318 xts_tensor_free(tensor);
319 if (value_out !=
nullptr) {
320 *value_out = report.value;
322 return static_cast<int>(status);