From 68b792981898a015717bd0fdd957a20946573d00 Mon Sep 17 00:00:00 2001 From: NY57 Date: Tue, 23 Apr 2024 14:38:09 +0900 Subject: [PATCH 1/6] add `sense` field to `Instance` --- proto/ommx/v1/instance.proto | 9 +++++++++ python/ommx/v1/instance_pb2.py | 10 ++++++---- python/ommx/v1/instance_pb2.pyi | 35 ++++++++++++++++++++++++++++++++- rust/ommx/src/ommx.v1.rs | 32 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/proto/ommx/v1/instance.proto b/proto/ommx/v1/instance.proto index 38a0bc73..f1d0d724 100644 --- a/proto/ommx/v1/instance.proto +++ b/proto/ommx/v1/instance.proto @@ -31,4 +31,13 @@ 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; + } + + 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..6ea1e7ca 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,8 @@ 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 @property def description(self) -> global___Instance.Description: ... @property @@ -77,8 +109,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/rust/ommx/src/ommx.v1.rs b/rust/ommx/src/ommx.v1.rs index b22050ec..24538c86 100644 --- a/rust/ommx/src/ommx.v1.rs +++ b/rust/ommx/src/ommx.v1.rs @@ -240,6 +240,8 @@ pub struct Instance { /// Constraints of the optimization problem #[prost(message, repeated, tag = "4")] pub constraints: ::prost::alloc::vec::Vec, + #[prost(enumeration = "instance::Sense", tag = "5")] + pub sense: i32, } /// Nested message and enum types in `Instance`. pub mod instance { @@ -256,6 +258,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)] From 2974a19ce68ab2eb69e083aecb21c60de3986140 Mon Sep 17 00:00:00 2001 From: NY57 Date: Tue, 23 Apr 2024 14:49:03 +0900 Subject: [PATCH 2/6] update version --- python/pyproject.toml | 2 +- rust/Cargo.lock | 2 +- rust/ommx/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 2b416829..e1bd943b 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ommx" -version = "0.1.1" +version = "0.1.2" 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..06dd1080 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -154,7 +154,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "ommx" -version = "0.1.0" +version = "0.1.1" dependencies = [ "prost", ] diff --git a/rust/ommx/Cargo.toml b/rust/ommx/Cargo.toml index f6e52b38..398f90aa 100644 --- a/rust/ommx/Cargo.toml +++ b/rust/ommx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ommx" -version = "0.1.0" +version = "0.1.1" edition = "2021" license = "MIT OR Apache-2.0" From 4701e17bf5c622d0f66aa061a3b039e63b79d001 Mon Sep 17 00:00:00 2001 From: NY57 <121103446+NY57@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:45:04 +0900 Subject: [PATCH 3/6] Update proto/ommx/v1/instance.proto Co-authored-by: Toshiki Teramura --- proto/ommx/v1/instance.proto | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proto/ommx/v1/instance.proto b/proto/ommx/v1/instance.proto index f1d0d724..9066aaa2 100644 --- a/proto/ommx/v1/instance.proto +++ b/proto/ommx/v1/instance.proto @@ -39,5 +39,10 @@ message Instance { 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; } From dd44cfbadba90d4b7c6ffd1c28300ce300a30edc Mon Sep 17 00:00:00 2001 From: NY57 <121103446+NY57@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:45:12 +0900 Subject: [PATCH 4/6] Update rust/ommx/Cargo.toml Co-authored-by: Toshiki Teramura --- rust/ommx/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ommx/Cargo.toml b/rust/ommx/Cargo.toml index 398f90aa..88f9312c 100644 --- a/rust/ommx/Cargo.toml +++ b/rust/ommx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ommx" -version = "0.1.1" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" From 4c2c4f104d2c4616213cc8088c38accd85a558f8 Mon Sep 17 00:00:00 2001 From: NY57 <121103446+NY57@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:45:21 +0900 Subject: [PATCH 5/6] Update python/pyproject.toml Co-authored-by: Toshiki Teramura --- python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index e1bd943b..0c0186a5 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ommx" -version = "0.1.2" +version = "0.2.0" description = "Open Mathematical prograMming eXchange (OMMX)" authors = [ { name="Jij Inc.", email="info@j-ij.com" }, From 685232c82509c22e8510ea26b8135db963346b8c Mon Sep 17 00:00:00 2001 From: NY57 Date: Tue, 23 Apr 2024 15:49:56 +0900 Subject: [PATCH 6/6] regenerate --- python/ommx/v1/instance_pb2.pyi | 5 +++++ rust/Cargo.lock | 2 +- rust/ommx/src/ommx.v1.rs | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/python/ommx/v1/instance_pb2.pyi b/python/ommx/v1/instance_pb2.pyi index 6ea1e7ca..39405f1d 100644 --- a/python/ommx/v1/instance_pb2.pyi +++ b/python/ommx/v1/instance_pb2.pyi @@ -86,6 +86,11 @@ class Instance(google.protobuf.message.Message): 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 diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 06dd1080..68daae98 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -154,7 +154,7 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "ommx" -version = "0.1.1" +version = "0.2.0" dependencies = [ "prost", ] diff --git a/rust/ommx/src/ommx.v1.rs b/rust/ommx/src/ommx.v1.rs index 24538c86..aa05130f 100644 --- a/rust/ommx/src/ommx.v1.rs +++ b/rust/ommx/src/ommx.v1.rs @@ -240,6 +240,11 @@ 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, }