Google OR-Tools v9.14
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/strings/ascii.h"
21#include "absl/strings/str_cat.h"
22#include "absl/strings/str_format.h"
23#include "absl/strings/str_join.h"
24#include "absl/strings/string_view.h"
25#include "absl/types/span.h"
27
29
30namespace {
31
32const AttrOpFunctionInfos* GetPythonFunctionInfos() {
33 // We're not generating functions for python, only enums.
34 static const auto* const kResult = new AttrOpFunctionInfos();
35 return kResult;
36}
37
38// Emits a set of numbered python enumerators for the given range.
39void EmitEnumerators(const absl::Span<const absl::string_view> names,
40 std::string* out) {
41 for (int i = 0; i < names.size(); ++i) {
42 absl::StrAppendFormat(out, " %s = %i\n", absl::AsciiStrToUpper(names[i]),
43 i);
44 }
45}
46
47// Returns the python type for the given value type.
48absl::string_view GetAttrPyValueType(
49 const CodegenAttrTypeDescriptor::ValueType& value_type) {
50 switch (value_type) {
52 return "bool";
54 return "int";
56 return "float";
57 }
58}
59
60// Returns the python type for the given value type.
61absl::string_view GetAttrNumpyValueType(
62 const CodegenAttrTypeDescriptor::ValueType& value_type) {
63 switch (value_type) {
65 return "np.bool_";
67 return "np.int64";
69 return "np.float64";
70 }
71}
72
73class PythonEnumsGenerator : public CodeGenerator {
74 public:
75 PythonEnumsGenerator() : CodeGenerator(GetPythonFunctionInfos()) {}
76
77 void EmitHeader(std::string* out) const override {
78 absl::StrAppend(out, R"(
79'''DO NOT EDIT: This file is autogenerated.'''
80
81import enum
82from typing import Generic, TypeVar, Union
83
84import numpy as np
85)");
86 }
87
88 void EmitElements(absl::Span<const absl::string_view> elements,
89 std::string* out) const override {
90 // Generate an enum for the elements.
91 absl::StrAppend(out, "class ElementType(enum.Enum):\n");
92 EmitEnumerators(elements, out);
93 absl::StrAppend(out, "\n");
94 }
95
96 void EmitAttributes(absl::Span<const CodegenAttrTypeDescriptor> descriptors,
97 std::string* out) const override {
98 absl::StrAppend(out, "\n");
99
100 {
101 // Collect the list of unique types:
102 std::set<absl::string_view> value_types;
103 for (const auto& descriptor : descriptors) {
104 value_types.insert(GetAttrNumpyValueType(descriptor.value_type));
105 }
106
107 // Emit `AttrValueType`, a type variable for all attribute value types.
108 absl::StrAppend(out, "AttrValueType = TypeVar('AttrValueType', ",
109 absl::StrJoin(value_types, ", "), ")\n");
110 }
111 absl::StrAppend(out, "\n");
112 {
113 std::set<absl::string_view> py_value_types;
114 for (const auto& descriptor : descriptors) {
115 py_value_types.insert(GetAttrPyValueType(descriptor.value_type));
116 }
117 absl::StrAppend(out, "AttrPyValueType = TypeVar('AttrPyValueType', ",
118 absl::StrJoin(py_value_types, ", "), ")\n");
119 }
120
121 // `Attr` is an attribute with any value type.
122 absl::StrAppend(out, R"(
123class Attr(Generic[AttrValueType]):
124 pass
125)");
126
127 // `PyAttr` is an attribute with any value type.
128 absl::StrAppend(out, R"(
129class PyAttr(Generic[AttrPyValueType]):
130 pass
131)");
132
133 // Generate an enum for the attribute type.
134 for (const auto& descriptor : descriptors) {
135 absl::StrAppendFormat(
136 out, "\nclass %s(Attr[%s], PyAttr[%s], int, enum.Enum):\n",
137 descriptor.name, GetAttrNumpyValueType(descriptor.value_type),
138 GetAttrPyValueType(descriptor.value_type));
139 EmitEnumerators(descriptor.attribute_names, out);
140 absl::StrAppend(out, "\n");
141 }
142
143 // Add a type alias for the union of all attribute types.
144 absl::StrAppend(
145 out, "AnyAttr = Union[",
146 absl::StrJoin(
147 descriptors, ", ",
148 [](std::string* out, const CodegenAttrTypeDescriptor& descriptor) {
149 absl::StrAppend(out, descriptor.name);
150 }),
151 "]\n");
152 }
153};
154
155} // namespace
156
157std::unique_ptr<CodeGenerator> PythonEnums() {
158 return std::make_unique<PythonEnumsGenerator>();
159}
160
161} // namespace operations_research::math_opt::codegen
Language-agnostic utilities for Elemental codegen.
Definition codegen.cc:29
std::unique_ptr< CodeGenerator > PythonEnums()
std::array< AttrOpFunctionInfo, kNumAttrOps > AttrOpFunctionInfos
Definition gen.h:96