Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
gen_python.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <memory>
17#include <set>
18#include <string>
19
20#include "absl/base/optimization.h"
21#include "absl/strings/ascii.h"
22#include "absl/strings/str_cat.h"
23#include "absl/strings/str_format.h"
24#include "absl/strings/str_join.h"
25#include "absl/strings/string_view.h"
26#include "absl/types/span.h"
28
30
31namespace {
32
33const AttrOpFunctionInfos* GetPythonFunctionInfos() {
34 // We're not generating functions for python, only enums.
35 static const auto* const kResult = new AttrOpFunctionInfos();
36 return kResult;
37}
38
39// Emits a set of numbered python enumerators for the given range.
40void EmitEnumerators(const absl::Span<const absl::string_view> names,
41 std::string* out) {
42 for (int i = 0; i < names.size(); ++i) {
43 absl::StrAppendFormat(out, " %s = %i\n", absl::AsciiStrToUpper(names[i]),
44 i);
45 }
46}
47
48// Returns the python type for the given value type.
49absl::string_view GetAttrPyValueType(
50 const CodegenAttrTypeDescriptor::ValueType& value_type) {
51 switch (value_type) {
53 return "bool";
55 return "int";
57 return "float";
58 }
59 ABSL_UNREACHABLE();
60}
61
62// Returns the python type for the given value type.
63absl::string_view GetAttrNumpyValueType(
64 const CodegenAttrTypeDescriptor::ValueType& value_type) {
65 switch (value_type) {
67 return "np.bool_";
69 return "np.int64";
71 return "np.float64";
72 }
73 ABSL_UNREACHABLE();
74}
75
76class PythonEnumsGenerator : public CodeGenerator {
77 public:
78 PythonEnumsGenerator() : CodeGenerator(GetPythonFunctionInfos()) {}
79
80 void EmitHeader(std::string* out) const override {
81 absl::StrAppend(out, R"(
82'''DO NOT EDIT: This file is autogenerated.'''
83
84import enum
85from typing import Generic, TypeVar, Union
86
87import numpy as np
88)");
89 }
90
91 void EmitElements(absl::Span<const absl::string_view> elements,
92 std::string* out) const override {
93 // Generate an enum for the elements.
94 absl::StrAppend(out, "class ElementType(enum.Enum):\n");
95 EmitEnumerators(elements, out);
96 absl::StrAppend(out, "\n");
97 }
98
99 void EmitAttributes(absl::Span<const CodegenAttrTypeDescriptor> descriptors,
100 std::string* out) const override {
101 absl::StrAppend(out, "\n");
102
103 {
104 // Collect the list of unique types:
105 std::set<absl::string_view> value_types;
106 for (const auto& descriptor : descriptors) {
107 value_types.insert(GetAttrNumpyValueType(descriptor.value_type));
108 }
109
110 // Emit `AttrValueType`, a type variable for all attribute value types.
111 absl::StrAppend(out, "AttrValueType = TypeVar('AttrValueType', ",
112 absl::StrJoin(value_types, ", "), ")\n");
113 }
114 absl::StrAppend(out, "\n");
115 {
116 std::set<absl::string_view> py_value_types;
117 for (const auto& descriptor : descriptors) {
118 py_value_types.insert(GetAttrPyValueType(descriptor.value_type));
119 }
120 absl::StrAppend(out, "AttrPyValueType = TypeVar('AttrPyValueType', ",
121 absl::StrJoin(py_value_types, ", "), ")\n");
122 }
123
124 // `Attr` is an attribute with any value type.
125 absl::StrAppend(out, R"(
126class Attr(Generic[AttrValueType]):
127 pass
128)");
129
130 // `PyAttr` is an attribute with any value type.
131 absl::StrAppend(out, R"(
132class PyAttr(Generic[AttrPyValueType]):
133 pass
134)");
135
136 // Generate an enum for the attribute type.
137 for (const auto& descriptor : descriptors) {
138 absl::StrAppendFormat(
139 out, "\nclass %s(Attr[%s], PyAttr[%s], int, enum.Enum):\n",
140 descriptor.name, GetAttrNumpyValueType(descriptor.value_type),
141 GetAttrPyValueType(descriptor.value_type));
142 EmitEnumerators(descriptor.attribute_names, out);
143 absl::StrAppend(out, "\n");
144 }
145
146 // Add a type alias for the union of all attribute types.
147 absl::StrAppend(
148 out, "AnyAttr = Union[",
149 absl::StrJoin(
150 descriptors, ", ",
151 [](std::string* out, const CodegenAttrTypeDescriptor& descriptor) {
152 absl::StrAppend(out, descriptor.name);
153 }),
154 "]\n");
155 }
156};
157
158} // namespace
159
160std::unique_ptr<CodeGenerator> PythonEnums() {
161 return std::make_unique<PythonEnumsGenerator>();
162}
163
164} // namespace operations_research::math_opt::codegen
std::unique_ptr< CodeGenerator > PythonEnums()
std::array< AttrOpFunctionInfo, kNumAttrOps > AttrOpFunctionInfos
Definition gen.h:96