diff --git a/proto/ommx/v1/instance.proto b/proto/ommx/v1/instance.proto index 38a0bc73..9066aaa2 100644 --- a/proto/ommx/v1/instance.proto +++ b/proto/ommx/v1/instance.proto @@ -31,4 +31,18 @@ message Instance { // // TODO: Add semi-definite constraints to represent SDP // repeated SemiDefiniteConstraint semi_definite_constraints = ?; + + // The sense of this instance + enum Sense { + SENSE_UNSPECIFIED = 0; + SENSE_MINIMIZE = 1; + SENSE_MAXIMIZE = 2; + } + + // The sense of this problem, i.e. minimize the objective or maximize it. + // + // Design decision note: + // - This is a required field. Most mathematical modeling tools allow for an empty sense and default to minimization. Alternatively, some tools do not create such a field and represent maximization problems by negating the objective function. This project prefers explicit descriptions over implicit ones to avoid such ambiguity and to make it unnecessary for developers to look up the reference for the treatment of omitted cases. + // + Sense sense = 5; } diff --git a/python/ommx/v1/instance_pb2.py b/python/ommx/v1/instance_pb2.py index 6d310868..40004714 100644 --- a/python/ommx/v1/instance_pb2.py +++ b/python/ommx/v1/instance_pb2.py @@ -17,7 +17,7 @@ from ommx.v1 import function_pb2 as ommx_dot_v1_dot_function__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16ommx/v1/instance.proto\x12\x07ommx.v1\x1a\x18ommx/v1/constraint.proto\x1a ommx/v1/decision_variables.proto\x1a\x16ommx/v1/function.proto\"\xb3\x03\n\x08Instance\x12?\n\x0b\x64\x65scription\x18\x01 \x01(\x0b\x32\x1d.ommx.v1.Instance.DescriptionR\x0b\x64\x65scription\x12H\n\x12\x64\x65\x63ision_variables\x18\x02 \x03(\x0b\x32\x19.ommx.v1.DecisionVariableR\x11\x64\x65\x63isionVariables\x12/\n\tobjective\x18\x03 \x01(\x0b\x32\x11.ommx.v1.FunctionR\tobjective\x12\x35\n\x0b\x63onstraints\x18\x04 \x03(\x0b\x32\x13.ommx.v1.ConstraintR\x0b\x63onstraints\x1a\xb3\x01\n\x0b\x44\x65scription\x12\x17\n\x04name\x18\x01 \x01(\tH\x00R\x04name\x88\x01\x01\x12%\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x01R\x0b\x64\x65scription\x88\x01\x01\x12\x18\n\x07\x61uthors\x18\x03 \x03(\tR\x07\x61uthors\x12\"\n\ncreated_by\x18\x04 \x01(\tH\x02R\tcreatedBy\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_descriptionB\r\n\x0b_created_byBY\n\x0b\x63om.ommx.v1B\rInstanceProtoP\x01\xa2\x02\x03OXX\xaa\x02\x07Ommx.V1\xca\x02\x07Ommx\\V1\xe2\x02\x13Ommx\\V1\\GPBMetadata\xea\x02\x08Ommx::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16ommx/v1/instance.proto\x12\x07ommx.v1\x1a\x18ommx/v1/constraint.proto\x1a ommx/v1/decision_variables.proto\x1a\x16ommx/v1/function.proto\"\xaa\x04\n\x08Instance\x12?\n\x0b\x64\x65scription\x18\x01 \x01(\x0b\x32\x1d.ommx.v1.Instance.DescriptionR\x0b\x64\x65scription\x12H\n\x12\x64\x65\x63ision_variables\x18\x02 \x03(\x0b\x32\x19.ommx.v1.DecisionVariableR\x11\x64\x65\x63isionVariables\x12/\n\tobjective\x18\x03 \x01(\x0b\x32\x11.ommx.v1.FunctionR\tobjective\x12\x35\n\x0b\x63onstraints\x18\x04 \x03(\x0b\x32\x13.ommx.v1.ConstraintR\x0b\x63onstraints\x12-\n\x05sense\x18\x05 \x01(\x0e\x32\x17.ommx.v1.Instance.SenseR\x05sense\x1a\xb3\x01\n\x0b\x44\x65scription\x12\x17\n\x04name\x18\x01 \x01(\tH\x00R\x04name\x88\x01\x01\x12%\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x01R\x0b\x64\x65scription\x88\x01\x01\x12\x18\n\x07\x61uthors\x18\x03 \x03(\tR\x07\x61uthors\x12\"\n\ncreated_by\x18\x04 \x01(\tH\x02R\tcreatedBy\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_descriptionB\r\n\x0b_created_by\"F\n\x05Sense\x12\x15\n\x11SENSE_UNSPECIFIED\x10\x00\x12\x12\n\x0eSENSE_MINIMIZE\x10\x01\x12\x12\n\x0eSENSE_MAXIMIZE\x10\x02\x42Y\n\x0b\x63om.ommx.v1B\rInstanceProtoP\x01\xa2\x02\x03OXX\xaa\x02\x07Ommx.V1\xca\x02\x07Ommx\\V1\xe2\x02\x13Ommx\\V1\\GPBMetadata\xea\x02\x08Ommx::V1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -26,7 +26,9 @@ _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'\n\013com.ommx.v1B\rInstanceProtoP\001\242\002\003OXX\252\002\007Ommx.V1\312\002\007Ommx\\V1\342\002\023Ommx\\V1\\GPBMetadata\352\002\010Ommx::V1' _globals['_INSTANCE']._serialized_start=120 - _globals['_INSTANCE']._serialized_end=555 - _globals['_INSTANCE_DESCRIPTION']._serialized_start=376 - _globals['_INSTANCE_DESCRIPTION']._serialized_end=555 + _globals['_INSTANCE']._serialized_end=674 + _globals['_INSTANCE_DESCRIPTION']._serialized_start=423 + _globals['_INSTANCE_DESCRIPTION']._serialized_end=602 + _globals['_INSTANCE_SENSE']._serialized_start=604 + _globals['_INSTANCE_SENSE']._serialized_end=674 # @@protoc_insertion_point(module_scope) diff --git a/python/ommx/v1/instance_pb2.pyi b/python/ommx/v1/instance_pb2.pyi index 0aa75070..39405f1d 100644 --- a/python/ommx/v1/instance_pb2.pyi +++ b/python/ommx/v1/instance_pb2.pyi @@ -7,18 +7,48 @@ import builtins import collections.abc import google.protobuf.descriptor import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper import google.protobuf.message import ommx.v1.constraint_pb2 import ommx.v1.decision_variables_pb2 import ommx.v1.function_pb2 +import sys import typing +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @typing.final class Instance(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + class _Sense: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _SenseEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Instance._Sense.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + SENSE_UNSPECIFIED: Instance._Sense.ValueType # 0 + SENSE_MINIMIZE: Instance._Sense.ValueType # 1 + SENSE_MAXIMIZE: Instance._Sense.ValueType # 2 + + class Sense(_Sense, metaclass=_SenseEnumTypeWrapper): + """Other types of constraints will be appended here + + TODO: Add semi-definite constraints to represent SDP + repeated SemiDefiniteConstraint semi_definite_constraints = ?; + + The sense of this instance + """ + + SENSE_UNSPECIFIED: Instance.Sense.ValueType # 0 + SENSE_MINIMIZE: Instance.Sense.ValueType # 1 + SENSE_MAXIMIZE: Instance.Sense.ValueType # 2 + @typing.final class Description(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -54,6 +84,13 @@ class Instance(google.protobuf.message.Message): DECISION_VARIABLES_FIELD_NUMBER: builtins.int OBJECTIVE_FIELD_NUMBER: builtins.int CONSTRAINTS_FIELD_NUMBER: builtins.int + SENSE_FIELD_NUMBER: builtins.int + sense: global___Instance.Sense.ValueType + """The sense of this problem, i.e. minimize the objective or maximize it. + + Design decision note: + - This is a required field. Most mathematical modeling tools allow for an empty sense and default to minimization. Alternatively, some tools do not create such a field and represent maximization problems by negating the objective function. This project prefers explicit descriptions over implicit ones to avoid such ambiguity and to make it unnecessary for developers to look up the reference for the treatment of omitted cases. + """ @property def description(self) -> global___Instance.Description: ... @property @@ -77,8 +114,9 @@ class Instance(google.protobuf.message.Message): decision_variables: collections.abc.Iterable[ommx.v1.decision_variables_pb2.DecisionVariable] | None = ..., objective: ommx.v1.function_pb2.Function | None = ..., constraints: collections.abc.Iterable[ommx.v1.constraint_pb2.Constraint] | None = ..., + sense: global___Instance.Sense.ValueType = ..., ) -> None: ... def HasField(self, field_name: typing.Literal["description", b"description", "objective", b"objective"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["constraints", b"constraints", "decision_variables", b"decision_variables", "description", b"description", "objective", b"objective"]) -> None: ... + def ClearField(self, field_name: typing.Literal["constraints", b"constraints", "decision_variables", b"decision_variables", "description", b"description", "objective", b"objective", "sense", b"sense"]) -> None: ... global___Instance = Instance diff --git a/python/pyproject.toml b/python/pyproject.toml index 2b416829..0c0186a5 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ommx" -version = "0.1.1" +version = "0.2.0" description = "Open Mathematical prograMming eXchange (OMMX)" authors = [ { name="Jij Inc.", email="info@j-ij.com" }, diff --git a/rust/Cargo.lock b/rust/Cargo.lock index a3979216..68daae98 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -154,7 +154,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "ommx" -version = "0.1.0" +version = "0.2.0" dependencies = [ "prost", ] diff --git a/rust/ommx/Cargo.toml b/rust/ommx/Cargo.toml index f6e52b38..88f9312c 100644 --- a/rust/ommx/Cargo.toml +++ b/rust/ommx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ommx" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" diff --git a/rust/ommx/src/ommx.v1.rs b/rust/ommx/src/ommx.v1.rs index b22050ec..aa05130f 100644 --- a/rust/ommx/src/ommx.v1.rs +++ b/rust/ommx/src/ommx.v1.rs @@ -240,6 +240,13 @@ pub struct Instance { /// Constraints of the optimization problem #[prost(message, repeated, tag = "4")] pub constraints: ::prost::alloc::vec::Vec, + /// The sense of this problem, i.e. minimize the objective or maximize it. + /// + /// Design decision note: + /// - This is a required field. Most mathematical modeling tools allow for an empty sense and default to minimization. Alternatively, some tools do not create such a field and represent maximization problems by negating the objective function. This project prefers explicit descriptions over implicit ones to avoid such ambiguity and to make it unnecessary for developers to look up the reference for the treatment of omitted cases. + /// + #[prost(enumeration = "instance::Sense", tag = "5")] + pub sense: i32, } /// Nested message and enum types in `Instance`. pub mod instance { @@ -256,6 +263,36 @@ pub mod instance { #[prost(string, optional, tag = "4")] pub created_by: ::core::option::Option<::prost::alloc::string::String>, } + /// The sense of this instance + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum Sense { + Unspecified = 0, + Minimize = 1, + Maximize = 2, + } + impl Sense { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Sense::Unspecified => "SENSE_UNSPECIFIED", + Sense::Minimize => "SENSE_MINIMIZE", + Sense::Maximize => "SENSE_MAXIMIZE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SENSE_UNSPECIFIED" => Some(Self::Unspecified), + "SENSE_MINIMIZE" => Some(Self::Minimize), + "SENSE_MAXIMIZE" => Some(Self::Maximize), + _ => None, + } + } + } } /// A solution obtained by the solver. #[allow(clippy::derive_partial_eq_without_eq)]