Skip to content

Commit

Permalink
Avoid redundant input/output calls to model in server-side checks
Browse files Browse the repository at this point in the history
  • Loading branch information
linusseelinger committed Nov 22, 2023
1 parent 5dbc08d commit 172aea5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 33 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="umbridge",
version="1.2.3",
version="1.2.4",
author="UM-Bridge",
author_email="",
description="UM-Bridge (the UQ and Model Bridge) provides a unified interface for numerical models that is accessible from virtually any programming language or framework. It is primarily intended for coupling advanced models (e.g. simulations of complex physical processes) to advanced statistical or optimization methods.",
Expand Down
76 changes: 44 additions & 32 deletions umbridge/um.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,15 @@ async def evaluate(request):
if "config" in req_json:
config = req_json["config"]

input_sizes = model.get_input_sizes(config)
output_sizes = model.get_output_sizes(config)

# Check if parameter dimensions match model input sizes
if len(parameters) != len(model.get_input_sizes(config)):
if len(parameters) != len(input_sizes):
return error_response("InvalidInput", "Number of input parameters does not match model number of model inputs!", 400)
for i in range(len(parameters)):
if len(parameters[i]) != model.get_input_sizes(config)[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {model.get_input_sizes(config)[i]} but got {len(parameters[i])}.", 400)
if len(parameters[i]) != input_sizes[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {input_sizes[i]} but got {len(parameters[i])}.", 400)

output_future = model_executor.submit(model.__call__, parameters, config)
output = await asyncio.wrap_future(output_future)
Expand All @@ -213,11 +216,11 @@ async def evaluate(request):
return error_response("InvalidOutput", "Model output is not a list of lists!", 500)

# Check if output dimensions match model output sizes
if len(output) != len(model.get_output_sizes(config)):
if len(output) != len(output_sizes):
return error_response("InvalidOutput", "Number of output vectors returned by model does not match number of model outputs declared by model!", 500)
for i in range(len(output)):
if len(output[i]) != model.get_output_sizes(config)[i]:
return error_response("InvalidOutput", f"Output vector {i} has invalid length! Model declared {model.get_output_sizes(config)[i]} but returned {len(output[i])}.", 500)
if len(output[i]) != output_sizes[i]:
return error_response("InvalidOutput", f"Output vector {i} has invalid length! Model declared {output_sizes[i]} but returned {len(output[i])}.", 500)

return web.Response(text=f"{{\"output\": {output} }}")

Expand All @@ -240,21 +243,24 @@ async def gradient(request):
if "config" in req_json:
config = req_json["config"]

input_sizes = model.get_input_sizes(config)
output_sizes = model.get_output_sizes(config)

# Check if parameter dimensions match model input sizes
if len(parameters) != len(model.get_input_sizes(config)):
if len(parameters) != len(input_sizes):
return error_response("InvalidInput", "Number of input parameters does not match model number of model inputs!", 400)
for i in range(len(parameters)):
if len(parameters[i]) != model.get_input_sizes(config)[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {model.get_input_sizes(config)[i]} but got {len(parameters[i])}.", 400)
if len(parameters[i]) != input_sizes[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {input_sizes[i]} but got {len(parameters[i])}.", 400)
# Check if outWrt is not between zero and number of outputs
if out_wrt < 0 or out_wrt >= len(model.get_output_sizes(config)):
if out_wrt < 0 or out_wrt >= len(output_sizes):
return error_response("InvalidInput", "Invalid outWrt index! Expected between 0 and number of outputs minus one, but got " + str(out_wrt), 400)
# Check if inWrt is between zero and number of inputs
if in_wrt < 0 or in_wrt >= len(model.get_input_sizes(config)):
if in_wrt < 0 or in_wrt >= len(input_sizes):
return error_response("InvalidInput", "Invalid inWrt index! Expected between 0 and number of inputs minus one, but got " + str(in_wrt), 400)
# Check if sensitivity vector length matches model output outWrt
if len(sens) != model.get_output_sizes(config)[out_wrt]:
return error_response("InvalidInput", f"Sensitivity vector sens has invalid length! Expected {model.get_output_sizes(config)[out_wrt]} but got {len(sens)}.", 400)
if len(sens) != output_sizes[out_wrt]:
return error_response("InvalidInput", f"Sensitivity vector sens has invalid length! Expected {output_sizes[out_wrt]} but got {len(sens)}.", 400)

output_future = model_executor.submit(model.gradient, out_wrt, in_wrt, parameters, sens, config)
output = await asyncio.wrap_future(output_future)
Expand All @@ -264,8 +270,8 @@ async def gradient(request):
return error_response("InvalidOutput", "Model output is not a list!", 500)

# Check if output dimension matches model ipuut size inWrt
if len(output) != model.get_input_sizes(config)[in_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {model.get_input_sizes(config)[in_wrt]} but returned {len(output)}.", 500)
if len(output) != input_sizes[in_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {input_sizes[in_wrt]} but returned {len(output)}.", 500)

return web.Response(text=f"{{\"output\": {output} }}")

Expand All @@ -288,21 +294,24 @@ async def applyjacobian(request):
if "config" in req_json:
config = req_json["config"]

input_sizes = model.get_input_sizes(config)
output_sizes = model.get_output_sizes(config)

# Check if parameter dimensions match model input sizes
if len(parameters) != len(model.get_input_sizes(config)):
if len(parameters) != len(input_sizes):
return error_response("InvalidInput", "Number of input parameters does not match model number of model inputs!", 400)
for i in range(len(parameters)):
if len(parameters[i]) != model.get_input_sizes(config)[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {model.get_input_sizes(config)[i]} but got {len(parameters[i])}.", 400)
if len(parameters[i]) != input_sizes[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {input_sizes[i]} but got {len(parameters[i])}.", 400)
# Check if outWrt is not between zero and number of outputs
if out_wrt < 0 or out_wrt >= len(model.get_output_sizes(config)):
if out_wrt < 0 or out_wrt >= len(output_sizes):
return error_response("InvalidInput", "Invalid outWrt index! Expected between 0 and number of outputs minus one, but got " + str(out_wrt), 400)
# Check if inWrt is between zero and number of inputs
if in_wrt < 0 or in_wrt >= len(model.get_input_sizes(config)):
if in_wrt < 0 or in_wrt >= len(input_sizes):
return error_response("InvalidInput", "Invalid inWrt index! Expected between 0 and number of inputs minus one, but got " + str(in_wrt), 400)
# Check if vector length matches model input inWrt
if len(vec) != model.get_input_sizes(config)[in_wrt]:
return error_response("InvalidInput", f"Vector vec has invalid length! Expected {model.get_input_sizes(config)[in_wrt]} but got {len(vec)}.", 400)
if len(vec) != input_sizes[in_wrt]:
return error_response("InvalidInput", f"Vector vec has invalid length! Expected {input_sizes[in_wrt]} but got {len(vec)}.", 400)

output_future = model_executor.submit(model.apply_jacobian, out_wrt, in_wrt, parameters, vec, config)
output = await asyncio.wrap_future(output_future)
Expand All @@ -312,8 +321,8 @@ async def applyjacobian(request):
return error_response("InvalidOutput", "Model output is not a list!", 500)

# Check if output dimension matches model output size outWrt
if len(output) != model.get_output_sizes(config)[out_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {model.get_output_sizes(config)[out_wrt]} but returned {len(output)}.", 500)
if len(output) != output_sizes[out_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {output_sizes[out_wrt]} but returned {len(output)}.", 500)

return web.Response(text=f"{{\"output\": {output} }}")

Expand All @@ -338,20 +347,23 @@ async def applyhessian(request):
if "config" in req_json:
config = req_json["config"]

input_sizes = model.get_input_sizes(config)
output_sizes = model.get_output_sizes(config)

# Check if parameter dimensions match model input sizes
if len(parameters) != len(model.get_input_sizes(config)):
if len(parameters) != len(input_sizes):
return error_response("InvalidInput", "Number of input parameters does not match model number of model inputs!", 400)
for i in range(len(parameters)):
if len(parameters[i]) != model.get_input_sizes(config)[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {model.get_input_sizes(config)[i]} but got {len(parameters[i])}.", 400)
if len(parameters[i]) != input_sizes[i]:
return error_response("InvalidInput", f"Input parameter {i} has invalid length! Expected {input_sizes[i]} but got {len(parameters[i])}.", 400)
# Check if outWrt is not between zero and number of outputs
if out_wrt < 0 or out_wrt >= len(model.get_output_sizes(config)):
if out_wrt < 0 or out_wrt >= len(output_sizes):
return error_response("InvalidInput", "Invalid outWrt index! Expected between 0 and number of outputs minus one, but got " + str(out_wrt), 400)
# Check if inWrt is between zero and number of inputs
if in_wrt1 < 0 or in_wrt1 >= len(model.get_input_sizes(config)):
if in_wrt1 < 0 or in_wrt1 >= len(input_sizes):
return error_response("InvalidInput", "Invalid inWrt1 index! Expected between 0 and number of inputs minus one, but got " + str(in_wrt1), 400)
# Check if inWrt is between zero and number of inputs
if in_wrt2 < 0 or in_wrt2 >= len(model.get_input_sizes(config)):
if in_wrt2 < 0 or in_wrt2 >= len(input_sizes):
return error_response("InvalidInput", "Invalid inWrt2 index! Expected between 0 and number of inputs minus one, but got " + str(in_wrt2), 400)

output_future = model_executor.submit(model.apply_hessian, out_wrt, in_wrt1, in_wrt2, parameters, sens, vec, config)
Expand All @@ -362,8 +374,8 @@ async def applyhessian(request):
return error_response("InvalidOutput", "Model output is not a list!", 500)

# Check if output dimension matches model output size outWrt
if len(output) != model.get_output_sizes(config)[out_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {model.get_output_sizes(config)[out_wrt]} but returned {len(output)}.", 500)
if len(output) != output_sizes[out_wrt]:
return error_response("InvalidOutput", f"Output vector has invalid length! Model declared {output_sizes[out_wrt]} but returned {len(output)}.", 500)

return web.Response(text=f"{{\"output\": {output} }}")

Expand Down

0 comments on commit 172aea5

Please sign in to comment.