Reference documentation for deal.II version 9.6.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
symengine_scalar_operations.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2019 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_differentiation_sd_symengine_scalar_operations_h
16#define dealii_differentiation_sd_symengine_scalar_operations_h
17
18#include <deal.II/base/config.h>
19
20#ifdef DEAL_II_WITH_SYMENGINE
21
22# include <deal.II/base/numbers.h>
23
26
27# include <symengine/basic.h>
28# include <symengine/symengine_rcp.h>
29
30# include <algorithm>
31# include <type_traits>
32# include <utility>
33# include <vector>
34
36
37namespace Differentiation
38{
39 namespace SD
40 {
60 Expression
61 make_symbol(const std::string &symbol);
62
83 Expression
84 make_symbolic_function(const std::string &symbol,
85 const types::symbol_vector &arguments);
86
109 make_symbolic_function(const std::string &symbol,
110 const types::substitution_map &arguments);
111
131 differentiate(const Expression &f, const Expression &x);
132
140 namespace internal
141 {
146 bool
147 is_valid_substitution_symbol(const SymEngine::Basic &entry);
148
158 void
160 types::substitution_map &substitution_map,
161 const SymEngine::RCP<const SymEngine::Basic> &symbol,
162 const SymEngine::RCP<const SymEngine::Basic> &value);
163 } // namespace internal
164
185 template <bool ignore_invalid_symbols = false,
186 typename ValueType = double,
187 typename SymbolicType>
189 make_symbol_map(const SymbolicType &symbol);
190
226 template <bool ignore_invalid_symbols = false,
227 typename ValueType = double,
228 typename SymbolicType,
229 typename... Args>
231 make_symbol_map(const SymbolicType &symbol, const Args &...other_symbols);
232
269 template <bool ignore_invalid_symbols = false, typename ValueType = double>
270 void
272 const Expression &symbol);
273
302 template <bool ignore_invalid_symbols = false,
303 typename ValueType = double,
304 typename SymbolicType,
305 typename T = std::enable_if_t<
306 !std::is_base_of_v<Expression, SymbolicType> &&
308 SymbolicType,
309 const SymEngine::RCP<const SymEngine::Basic> &>::value>>
310 void
312 const SymbolicType &symbol);
313
339 template <bool ignore_invalid_symbols = false,
340 typename ValueType = double,
341 typename SymbolicType>
342 void
344 const std::vector<SymbolicType> &symbols);
345
365 template <bool ignore_invalid_symbols = false, typename ValueType = double>
366 void
368 const types::substitution_map &other_symbols);
369
412 template <bool ignore_invalid_symbols = false,
413 typename ValueType = double,
414 typename SymbolicType,
415 typename... Args>
416 void
418 const SymbolicType &symbol,
419 const Args &...other_symbols);
420
429 void
431 const Expression &symbol,
432 const Expression &value);
433
460 template <typename SymbolicType,
461 typename ValueType,
462 typename T = std::enable_if_t<
464 SymbolicType,
465 const SymEngine::RCP<const SymEngine::Basic> &>::value &&
466 std::is_constructible_v<SymbolicType, ValueType>>>
467 void
469 const SymbolicType &symbol,
470 const ValueType &value);
471
491 template <typename SymbolicType, typename ValueType>
492 void
494 const std::vector<SymbolicType> &symbols,
495 const std::vector<ValueType> &values);
496
518 template <typename SymbolicType, typename ValueType>
519 void
521 types::substitution_map &substitution_map,
522 const std::pair<SymbolicType, ValueType> &symbol_value);
523
548 template <typename SymbolicType, typename ValueType, typename... Args>
549 void
551 types::substitution_map &substitution_map,
552 const std::pair<SymbolicType, ValueType> &symbol_value,
553 const Args &...other_symbol_values);
554
576 template <typename SymbolicType, typename ValueType>
577 void
579 types::substitution_map &substitution_map,
580 const std::vector<std::pair<SymbolicType, ValueType>> &symbol_values);
581
592 void
594 const types::substitution_map &symbol_values);
595
616 make_substitution_map(const Expression &symbol, const Expression &value);
617
649 template <typename ExpressionType,
650 typename ValueType,
651 typename T = std::enable_if_t<
653 ExpressionType,
654 const SymEngine::RCP<const SymEngine::Basic> &>::value &&
655 std::is_constructible_v<ExpressionType, ValueType>>>
657 make_substitution_map(const ExpressionType &symbol, const ValueType &value);
658
680 template <typename ExpressionType, typename ValueType>
682 make_substitution_map(const std::vector<ExpressionType> &symbols,
683 const std::vector<ValueType> &values);
684
706 template <typename ExpressionType, typename ValueType>
709 const std::pair<ExpressionType, ValueType> &symbol_value);
710
733 template <typename ExpressionType, typename ValueType>
736 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values);
737
778 template <typename ExpressionType, typename ValueType, typename... Args>
781 const std::pair<ExpressionType, ValueType> &symbol_value,
782 const Args &...other_symbol_values);
783
791 namespace internal
792 {
815 template <bool ignore_invalid_symbols = false>
816 void
818 types::substitution_map &substitution_map,
819 const SymEngine::RCP<const SymEngine::Basic> &symbol,
820 const SymEngine::RCP<const SymEngine::Basic> &value);
821 } // namespace internal
822
853 template <bool ignore_invalid_symbols = false>
854 void
856 const Expression &symbol,
857 const Expression &value);
858
891 template <bool ignore_invalid_symbols = false,
892 typename ExpressionType,
893 typename ValueType,
894 typename = std::enable_if_t<
896 ExpressionType,
897 const SymEngine::RCP<const SymEngine::Basic> &>::value &&
898 std::is_constructible_v<ExpressionType, ValueType>>>
899 void
901 const ExpressionType &symbol,
902 const ValueType &value);
903
937 template <bool ignore_invalid_symbols = false,
938 typename ExpressionType,
939 typename ValueType,
940 typename = std::enable_if_t<
942 ExpressionType,
943 const SymEngine::RCP<const SymEngine::Basic> &>::value &&
944 std::is_constructible_v<ExpressionType, ValueType>>>
945 void
947 const std::vector<ExpressionType> &symbols,
948 const std::vector<ValueType> &values);
949
966 template <bool ignore_invalid_symbols = false>
967 void
969 const types::substitution_map &symbol_values);
970
1011 template <bool ignore_invalid_symbols = false,
1012 typename ExpressionType,
1013 typename ValueType>
1014 void
1016 types::substitution_map &substitution_map,
1017 const std::pair<ExpressionType, ValueType> &symbol_value);
1018
1063 template <bool ignore_invalid_symbols = false,
1064 typename ExpressionType,
1065 typename ValueType>
1066 void
1068 types::substitution_map &substitution_map,
1069 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values);
1070
1115 template <bool ignore_invalid_symbols = false,
1116 typename ExpressionType,
1117 typename ValueType,
1118 typename... Args>
1119 void
1121 types::substitution_map &substitution_map,
1122 const std::pair<ExpressionType, ValueType> &symbol_value,
1123 const Args &...other_symbol_values);
1124
1133 void
1135 const types::substitution_map &substitution_map_in);
1136
1146 template <typename... Args>
1147 void
1149 const types::substitution_map &substitution_map_in,
1150 const Args &...other_substitution_maps_in);
1151
1159 template <typename... Args>
1162 const Args &...other_substitution_maps_in);
1163
1211 const types::substitution_map &substitution_map,
1212 const bool force_cyclic_dependency_resolution = false);
1213
1244 template <typename ExpressionType, typename ValueType>
1247 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values,
1248 const bool force_cyclic_dependency_resolution = false);
1249
1297 substitute(const Expression &expression,
1298 const types::substitution_map &substitution_map);
1299
1321 template <typename ValueType>
1323 substitute(const Expression &expression,
1324 const Expression &symbol,
1325 const ValueType &value);
1326
1355 template <typename ExpressionType, typename... Args>
1356 ExpressionType
1357 substitute(const ExpressionType &expression, const Args &...symbol_values);
1358
1384 template <typename ValueType>
1385 ValueType
1387 const types::substitution_map &substitution_map);
1388
1420 template <typename ValueType, typename... Args>
1421 ValueType
1423 const Args &...symbol_values);
1424
1427 } // namespace SD
1428} // namespace Differentiation
1429
1430
1431/* -------------------- inline and template functions ------------------ */
1432
1433
1434# ifndef DOXYGEN
1435
1436
1437namespace Differentiation
1438{
1439 namespace SD
1440 {
1441 /* ---------------- Symbol map creation and manipulation --------------*/
1442
1443
1444 template <bool ignore_invalid_symbols,
1445 typename ValueType,
1446 typename SymbolicType>
1448 make_symbol_map(const SymbolicType &symbol)
1449 {
1450 types::substitution_map symbol_map;
1452 return symbol_map;
1453 }
1454
1455
1456 template <bool ignore_invalid_symbols,
1457 typename ValueType,
1458 typename SymbolicType,
1459 typename... Args>
1461 make_symbol_map(const SymbolicType &symbol, const Args &...other_symbols)
1462 {
1463 types::substitution_map symbol_map;
1465 symbol,
1466 other_symbols...);
1467 return symbol_map;
1468 }
1469
1470
1471 template <bool ignore_invalid_symbols, typename ValueType>
1472 void
1474 const Expression &symbol)
1475 {
1476 // Call the above function
1478 symbol_map,
1479 symbol,
1481 }
1482
1483
1484 template <bool ignore_invalid_symbols,
1485 typename ValueType,
1486 typename SymbolicType,
1487 typename>
1488 void
1490 const SymbolicType &symbol)
1491 {
1492 // Call the above function
1493 using SE_RCP_Basic = const SymEngine::RCP<const SymEngine::Basic> &;
1495 symbol_map,
1496 static_cast<SE_RCP_Basic>(symbol),
1498 }
1499
1500
1501 template <bool ignore_invalid_symbols,
1502 typename ValueType,
1503 typename SymbolicType>
1504 void
1506 const std::vector<SymbolicType> &symbols)
1507 {
1508 for (const auto &symbol : symbols)
1509 add_to_symbol_map<ignore_invalid_symbols, ValueType>(symbol_map,
1510 symbol);
1511 }
1512
1513
1514 template <bool ignore_invalid_symbols, typename ValueType>
1515 void
1517 const types::substitution_map &other_symbols)
1518 {
1519 // We should be cautious as to whether or not the user has
1520 // hand-made the other_symbols map to be "merged" in.
1521 // So instead of blindly merging using the merge_substitution_maps()
1522 // function, we do it by hand and check for invalid symbols
1523 // if required.
1524 for (types::substitution_map::const_iterator it = other_symbols.begin();
1525 it != other_symbols.end();
1526 ++it)
1527 {
1528 Assert(symbol_map.find(it->first) == symbol_map.end(),
1529 ExcMessage("Entry already exists in symbol map"));
1531 symbol_map, Expression(it->first));
1532 }
1533 }
1534
1535
1536 template <bool ignore_invalid_symbols,
1537 typename ValueType,
1538 typename SymbolicType,
1539 typename... Args>
1540 void
1542 const SymbolicType &symbol,
1543 const Args &...other_symbols)
1544 {
1547 other_symbols...);
1548 }
1549
1550
1551 template <typename SymbolicType, typename ValueType, typename>
1552 void
1554 const SymbolicType &symbol,
1555 const ValueType &value)
1556 {
1557 // Call the above function
1558 using SE_RCP_Basic = const SymEngine::RCP<const SymEngine::Basic> &;
1559 internal::set_value_in_symbol_map(substitution_map,
1560 static_cast<SE_RCP_Basic>(symbol),
1561 static_cast<SE_RCP_Basic>(
1562 SymbolicType(value)));
1563 }
1564
1565
1566 template <typename SymbolicType, typename ValueType>
1567 void
1569 const std::vector<SymbolicType> &symbols,
1570 const std::vector<ValueType> &values)
1571 {
1572 Assert(symbols.size() == values.size(),
1573 ExcDimensionMismatch(symbols.size(), values.size()));
1574
1575 typename std::vector<SymbolicType>::const_iterator it_symb =
1576 symbols.begin();
1577 typename std::vector<ValueType>::const_iterator it_val = values.begin();
1578 for (; it_symb != symbols.end(); ++it_symb, ++it_val)
1579 {
1580 Assert(it_val != values.end(), ExcInternalError());
1581 set_value_in_symbol_map(substitution_map, *it_symb, *it_val);
1582 }
1583 }
1584
1585
1586 template <typename SymbolicType, typename ValueType>
1587 void
1589 types::substitution_map &substitution_map,
1590 const std::pair<SymbolicType, ValueType> &symbol_value)
1591 {
1592 set_value_in_symbol_map(substitution_map,
1593 symbol_value.first,
1594 symbol_value.second);
1595 }
1596
1597
1598 template <typename SymbolicType, typename ValueType, typename... Args>
1599 void
1601 types::substitution_map &substitution_map,
1602 const std::pair<SymbolicType, ValueType> &symbol_value,
1603 const Args &...other_symbol_values)
1604 {
1605 set_value_in_symbol_map(substitution_map, symbol_value);
1606 set_value_in_symbol_map(substitution_map, other_symbol_values...);
1607 }
1608
1609
1610 template <typename SymbolicType, typename ValueType>
1611 void
1613 types::substitution_map &substitution_map,
1614 const std::vector<std::pair<SymbolicType, ValueType>> &symbol_values)
1615 {
1616 // Call the above function
1617 for (const auto &entry : symbol_values)
1619 }
1620
1621
1622 /* ------------------ Symbol substitution map creation ----------------*/
1623
1624
1625 template <typename ExpressionType, typename ValueType, typename>
1627 make_substitution_map(const ExpressionType &symbol, const ValueType &value)
1628 {
1630 add_to_substitution_map(substitution_map, symbol, value);
1631 return substitution_map;
1632 }
1633
1634
1635 template <typename ExpressionType, typename ValueType>
1637 make_substitution_map(const std::vector<ExpressionType> &symbols,
1638 const std::vector<ValueType> &values)
1639 {
1641 add_to_substitution_map(substitution_map, symbols, values);
1642 return substitution_map;
1643 }
1644
1645
1646 template <typename ExpressionType, typename ValueType>
1649 const std::pair<ExpressionType, ValueType> &symbol_value)
1650 {
1652 add_to_substitution_map(substitution_map, symbol_value);
1653 return substitution_map;
1654 }
1655
1656
1657 template <typename ExpressionType, typename ValueType>
1660 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values)
1661 {
1663 add_to_substitution_map(substitution_map, symbol_values);
1664 return substitution_map;
1665 }
1666
1667
1668 template <typename ExpressionType, typename ValueType, typename... Args>
1671 const std::pair<ExpressionType, ValueType> &symbol_value,
1672 const Args &...other_symbol_values)
1673 {
1675 add_to_substitution_map(substitution_map,
1676 symbol_value,
1677 other_symbol_values...);
1678 return substitution_map;
1679 }
1680
1681
1682 /* ---------------- Symbolic substitution map enlargement --------------*/
1683
1684 namespace internal
1685 {
1697 template <bool ignore_invalid_symbols>
1698 void
1700 types::substitution_map &substitution_map,
1701 const SymEngine::RCP<const SymEngine::Basic> &symbol,
1702 const SymEngine::RCP<const SymEngine::Basic> &value)
1703 {
1704 if (ignore_invalid_symbols == false)
1705 {
1706 Assert(
1708 ExcMessage(
1709 "Substitution with a number that does not represent a symbol or symbolic derivative"));
1710 Assert(substitution_map.find(symbol) == substitution_map.end(),
1711 ExcMessage("This symbol is already in the map."));
1712 substitution_map[Expression(symbol)] = Expression(value);
1713 }
1714 else
1715 {
1717 {
1718 Assert(substitution_map.find(symbol) == substitution_map.end(),
1719 ExcMessage("This symbol is already in the map."));
1720 substitution_map[Expression(symbol)] = Expression(value);
1721 }
1722 }
1723 }
1724
1725 } // namespace internal
1726
1727
1728 template <bool ignore_invalid_symbols>
1729 void
1731 const Expression &symbol,
1732 const Expression &value)
1733 {
1735 substitution_map, symbol.get_RCP(), value.get_RCP());
1736 }
1737
1738
1739 template <bool ignore_invalid_symbols,
1740 typename ExpressionType,
1741 typename ValueType,
1742 typename>
1743 void
1745 const ExpressionType &symbol,
1746 const ValueType &value)
1747 {
1748 using SE_RCP_Basic = const SymEngine::RCP<const SymEngine::Basic> &;
1750 substitution_map,
1751 static_cast<SE_RCP_Basic>(symbol),
1752 static_cast<SE_RCP_Basic>(ExpressionType(value)));
1753 }
1754
1755
1756 template <bool ignore_invalid_symbols,
1757 typename ExpressionType,
1758 typename ValueType,
1759 typename>
1760 void
1762 const std::vector<ExpressionType> &symbols,
1763 const std::vector<ValueType> &values)
1764 {
1765 Assert(symbols.size() == values.size(),
1766 ExcMessage(
1767 "Vector of symbols and values must be of equal length."));
1768
1769 typename types::symbol_vector::const_iterator it_s = symbols.begin();
1770 typename std::vector<ValueType>::const_iterator it_v = values.begin();
1771 using SE_RCP_Basic = const SymEngine::RCP<const SymEngine::Basic> &;
1772 for (; it_s != symbols.end(); ++it_s, ++it_v)
1773 {
1774 Assert(it_v != values.end(), ExcInternalError());
1776 substitution_map,
1777 static_cast<SE_RCP_Basic>(*it_s),
1778 static_cast<SE_RCP_Basic>(ExpressionType(*it_v)));
1779 }
1780 }
1781
1782
1783 template <bool ignore_invalid_symbols,
1784 typename ExpressionType,
1785 typename ValueType>
1786 void
1788 types::substitution_map &substitution_map,
1789 const std::pair<ExpressionType, ValueType> &symbol_value)
1790 {
1792 symbol_value.first,
1793 symbol_value.second);
1794 }
1795
1796
1797 template <bool ignore_invalid_symbols,
1798 typename ExpressionType,
1799 typename ValueType>
1800 void
1802 types::substitution_map &substitution_map,
1803 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values)
1804 {
1805 for (const auto &entry : symbol_values)
1806 {
1808 entry);
1809 }
1810 }
1811
1812
1813 template <bool ignore_invalid_symbols>
1814 void
1816 const types::substitution_map &symbol_values)
1817 {
1818 for (const auto &entry : symbol_values)
1819 {
1820 const SymEngine::RCP<const SymEngine::Basic> &symbol = entry.first;
1821 const SymEngine::RCP<const SymEngine::Basic> &value = entry.second;
1823 substitution_map, symbol, value);
1824 }
1825 }
1826
1827
1828 template <bool ignore_invalid_symbols,
1829 typename ExpressionType,
1830 typename ValueType,
1831 typename... Args>
1832 void
1834 types::substitution_map &substitution_map,
1835 const std::pair<ExpressionType, ValueType> &symbol_value,
1836 const Args &...other_symbol_values)
1837 {
1839 symbol_value);
1841 other_symbol_values...);
1842 }
1843
1844
1845 template <typename... Args>
1848 const types::substitution_map &substitution_map_in_1,
1849 const Args &...other_substitution_maps_in)
1850 {
1851 types::substitution_map substitution_map_out = substitution_map_in_1;
1852 merge_substitution_maps(substitution_map_out,
1853 other_substitution_maps_in...);
1854 return substitution_map_out;
1855 }
1856
1857
1858 template <typename... Args>
1859 void
1861 types::substitution_map &substitution_map_out,
1862 const types::substitution_map &substitution_map_in_1,
1863 const Args &...other_substitution_maps_in)
1864 {
1865 merge_substitution_maps(substitution_map_out, substitution_map_in_1);
1866 merge_substitution_maps(substitution_map_out,
1867 other_substitution_maps_in...);
1868 }
1869
1870
1871 /* ---------------- Symbol substitution and evaluation --------------*/
1872
1873
1874 template <typename ExpressionType, typename ValueType>
1877 const std::vector<std::pair<ExpressionType, ValueType>> &symbol_values,
1878 const bool force_cyclic_dependency_resolution)
1879 {
1881 force_cyclic_dependency_resolution);
1882 }
1883
1884
1885 template <typename ValueType>
1886 Expression
1887 substitute(const Expression &expression,
1888 const Expression &symbol,
1889 const ValueType &value)
1890 {
1891 return expression.substitute(symbol, value);
1892 }
1893
1894
1895 template <typename ExpressionType, typename... Args>
1896 ExpressionType
1897 substitute(const ExpressionType &expression, const Args &...symbol_values)
1898 {
1899 // Call other function
1900 return substitute(expression, make_substitution_map(symbol_values...));
1901 }
1902
1903
1904 template <typename ValueType>
1905 ValueType
1906 substitute_and_evaluate(const Expression &expression,
1907 const types::substitution_map &substitution_map)
1908 {
1909 return expression.substitute_and_evaluate<ValueType>(substitution_map);
1910 }
1911
1912
1913 template <typename ValueType, typename... Args>
1914 ValueType
1915 substitute_and_evaluate(const Expression &expression,
1916 const Args &...symbol_values)
1917 {
1918 // Call other function
1920 expression, make_substitution_map(symbol_values...));
1921 }
1922
1923 } // namespace SD
1924} // namespace Differentiation
1925
1926
1927# endif // DOXYGEN
1928
1930
1931#endif // DEAL_II_WITH_SYMENGINE
1932
1933#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:503
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:504
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
void add_to_substitution_map(types::substitution_map &substitution_map, const SymEngine::RCP< const SymEngine::Basic > &symbol, const SymEngine::RCP< const SymEngine::Basic > &value)
bool is_valid_substitution_symbol(const SymEngine::Basic &entry)
void set_value_in_symbol_map(types::substitution_map &substitution_map, const SymEngine::RCP< const SymEngine::Basic > &symbol, const SymEngine::RCP< const SymEngine::Basic > &value)
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
std::vector< SD::Expression > symbol_vector
void merge_substitution_maps(types::substitution_map &substitution_map_out, const types::substitution_map &substitution_map_in)
Expression differentiate(const Expression &f, const Expression &x)
ValueType substitute_and_evaluate(const Expression &expression, const types::substitution_map &substitution_map)
types::substitution_map make_symbol_map(const SymbolicType &symbol)
Expression make_symbolic_function(const std::string &symbol, const types::symbol_vector &arguments)
void set_value_in_symbol_map(types::substitution_map &substitution_map, const Expression &symbol, const Expression &value)
void add_to_symbol_map(types::substitution_map &symbol_map, const Expression &symbol)
void add_to_substitution_map(types::substitution_map &substitution_map, const Expression &symbol, const Expression &value)
types::substitution_map resolve_explicit_dependencies(const types::substitution_map &substitution_map, const bool force_cyclic_dependency_resolution=false)
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
types::substitution_map make_substitution_map(const Expression &symbol, const Expression &value)
Expression make_symbol(const std::string &symbol)