text:
Copied to
clipboard

G = SD32⋊S3order 192 = 26·3

2nd semidirect product of SD32 and S3 acting via S3/C3=C2

Series: Derived Chief Lower central Upper central

 Derived series C1 — C24 — SD32⋊S3
 Chief series C1 — C3 — C6 — C12 — C24 — S3×C8 — S3×Q16 — SD32⋊S3
 Lower central C3 — C6 — C12 — C24 — SD32⋊S3
 Upper central C1 — C2 — C4 — C8 — SD32

Generators and relations for SD32⋊S3
G = < a,b,c,d | a16=b2=c3=d2=1, bab=a7, ac=ca, dad=a9, bc=cb, dbd=a8b, dcd=c-1 >

Subgroups: 268 in 82 conjugacy classes, 31 normal (all characteristic)
C1, C2, C2, C3, C4, C4, C22, S3, C6, C6, C8, C8, C2×C4, D4, Q8, Dic3, Dic3, C12, C12, D6, C2×C6, C16, C16, C2×C8, D8, SD16, Q16, Q16, C2×Q8, C4○D4, C3⋊C8, C24, Dic6, C4×S3, C4×S3, C2×Dic3, C3⋊D4, C3×D4, C3×Q8, M5(2), SD32, SD32, Q32, C2×Q16, C4○D8, C3⋊C16, C48, S3×C8, Dic12, D4.S3, C3⋊Q16, C3×D8, C3×Q16, D42S3, S3×Q8, Q32⋊C2, D6.C8, Dic24, D8.S3, C3⋊Q32, C3×SD32, D83S3, S3×Q16, SD32⋊S3
Quotients: C1, C2, C22, S3, D4, C23, D6, D8, C2×D4, C22×S3, C2×D8, S3×D4, Q32⋊C2, S3×D8, SD32⋊S3

Character table of SD32⋊S3

 class 1 2A 2B 2C 3 4A 4B 4C 4D 4E 6A 6B 8A 8B 8C 12A 12B 16A 16B 16C 16D 24A 24B 48A 48B 48C 48D size 1 1 6 8 2 2 6 8 24 24 2 16 2 2 12 4 16 4 4 12 12 4 4 4 4 4 4 ρ1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 trivial ρ2 1 1 1 -1 1 1 1 1 1 -1 1 -1 1 1 1 1 1 -1 -1 -1 -1 1 1 -1 -1 -1 -1 linear of order 2 ρ3 1 1 -1 1 1 1 -1 -1 1 -1 1 1 1 1 -1 1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 linear of order 2 ρ4 1 1 -1 -1 1 1 -1 -1 1 1 1 -1 1 1 -1 1 -1 1 1 -1 -1 1 1 1 1 1 1 linear of order 2 ρ5 1 1 1 1 1 1 1 -1 -1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 1 1 -1 -1 -1 -1 linear of order 2 ρ6 1 1 1 -1 1 1 1 -1 -1 -1 1 -1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 linear of order 2 ρ7 1 1 -1 1 1 1 -1 1 -1 -1 1 1 1 1 -1 1 1 1 1 -1 -1 1 1 1 1 1 1 linear of order 2 ρ8 1 1 -1 -1 1 1 -1 1 -1 1 1 -1 1 1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 linear of order 2 ρ9 2 2 0 -2 -1 2 0 2 0 0 -1 1 2 2 0 -1 -1 -2 -2 0 0 -1 -1 1 1 1 1 orthogonal lifted from D6 ρ10 2 2 2 0 2 2 2 0 0 0 2 0 -2 -2 -2 2 0 0 0 0 0 -2 -2 0 0 0 0 orthogonal lifted from D4 ρ11 2 2 0 2 -1 2 0 -2 0 0 -1 -1 2 2 0 -1 1 -2 -2 0 0 -1 -1 1 1 1 1 orthogonal lifted from D6 ρ12 2 2 0 -2 -1 2 0 -2 0 0 -1 1 2 2 0 -1 1 2 2 0 0 -1 -1 -1 -1 -1 -1 orthogonal lifted from D6 ρ13 2 2 0 2 -1 2 0 2 0 0 -1 -1 2 2 0 -1 -1 2 2 0 0 -1 -1 -1 -1 -1 -1 orthogonal lifted from S3 ρ14 2 2 -2 0 2 2 -2 0 0 0 2 0 -2 -2 2 2 0 0 0 0 0 -2 -2 0 0 0 0 orthogonal lifted from D4 ρ15 2 2 -2 0 2 -2 2 0 0 0 2 0 0 0 0 -2 0 √2 -√2 -√2 √2 0 0 -√2 -√2 √2 √2 orthogonal lifted from D8 ρ16 2 2 2 0 2 -2 -2 0 0 0 2 0 0 0 0 -2 0 √2 -√2 √2 -√2 0 0 -√2 -√2 √2 √2 orthogonal lifted from D8 ρ17 2 2 2 0 2 -2 -2 0 0 0 2 0 0 0 0 -2 0 -√2 √2 -√2 √2 0 0 √2 √2 -√2 -√2 orthogonal lifted from D8 ρ18 2 2 -2 0 2 -2 2 0 0 0 2 0 0 0 0 -2 0 -√2 √2 √2 -√2 0 0 √2 √2 -√2 -√2 orthogonal lifted from D8 ρ19 4 4 0 0 -2 4 0 0 0 0 -2 0 -4 -4 0 -2 0 0 0 0 0 2 2 0 0 0 0 orthogonal lifted from S3×D4 ρ20 4 4 0 0 -2 -4 0 0 0 0 -2 0 0 0 0 2 0 2√2 -2√2 0 0 0 0 √2 √2 -√2 -√2 orthogonal lifted from S3×D8 ρ21 4 4 0 0 -2 -4 0 0 0 0 -2 0 0 0 0 2 0 -2√2 2√2 0 0 0 0 -√2 -√2 √2 √2 orthogonal lifted from S3×D8 ρ22 4 -4 0 0 4 0 0 0 0 0 -4 0 -2√2 2√2 0 0 0 0 0 0 0 -2√2 2√2 0 0 0 0 symplectic lifted from Q32⋊C2, Schur index 2 ρ23 4 -4 0 0 4 0 0 0 0 0 -4 0 2√2 -2√2 0 0 0 0 0 0 0 2√2 -2√2 0 0 0 0 symplectic lifted from Q32⋊C2, Schur index 2 ρ24 4 -4 0 0 -2 0 0 0 0 0 2 0 -2√2 2√2 0 0 0 0 0 0 0 √2 -√2 2ζ165ζ3+ζ165+2ζ163ζ3+ζ163 2ζ165ζ32+ζ165+2ζ163ζ32+ζ163 2ζ1615ζ32+ζ1615+2ζ169ζ32+ζ169 2ζ167ζ32+ζ167+2ζ16ζ32+ζ16 symplectic faithful, Schur index 2 ρ25 4 -4 0 0 -2 0 0 0 0 0 2 0 2√2 -2√2 0 0 0 0 0 0 0 -√2 √2 2ζ167ζ32+ζ167+2ζ16ζ32+ζ16 2ζ1615ζ32+ζ1615+2ζ169ζ32+ζ169 2ζ165ζ3+ζ165+2ζ163ζ3+ζ163 2ζ165ζ32+ζ165+2ζ163ζ32+ζ163 symplectic faithful, Schur index 2 ρ26 4 -4 0 0 -2 0 0 0 0 0 2 0 -2√2 2√2 0 0 0 0 0 0 0 √2 -√2 2ζ165ζ32+ζ165+2ζ163ζ32+ζ163 2ζ165ζ3+ζ165+2ζ163ζ3+ζ163 2ζ167ζ32+ζ167+2ζ16ζ32+ζ16 2ζ1615ζ32+ζ1615+2ζ169ζ32+ζ169 symplectic faithful, Schur index 2 ρ27 4 -4 0 0 -2 0 0 0 0 0 2 0 2√2 -2√2 0 0 0 0 0 0 0 -√2 √2 2ζ1615ζ32+ζ1615+2ζ169ζ32+ζ169 2ζ167ζ32+ζ167+2ζ16ζ32+ζ16 2ζ165ζ32+ζ165+2ζ163ζ32+ζ163 2ζ165ζ3+ζ165+2ζ163ζ3+ζ163 symplectic faithful, Schur index 2

Smallest permutation representation of SD32⋊S3
On 96 points
Generators in S96
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)(17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32)(33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48)(49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64)(65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80)(81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96)
(2 8)(3 15)(4 6)(5 13)(7 11)(10 16)(12 14)(17 25)(18 32)(19 23)(20 30)(22 28)(24 26)(27 31)(33 45)(34 36)(35 43)(37 41)(38 48)(40 46)(42 44)(49 57)(50 64)(51 55)(52 62)(54 60)(56 58)(59 63)(65 69)(66 76)(68 74)(70 72)(71 79)(73 77)(78 80)(81 83)(82 90)(84 88)(85 95)(87 93)(89 91)(92 96)
(1 94 39)(2 95 40)(3 96 41)(4 81 42)(5 82 43)(6 83 44)(7 84 45)(8 85 46)(9 86 47)(10 87 48)(11 88 33)(12 89 34)(13 90 35)(14 91 36)(15 92 37)(16 93 38)(17 57 79)(18 58 80)(19 59 65)(20 60 66)(21 61 67)(22 62 68)(23 63 69)(24 64 70)(25 49 71)(26 50 72)(27 51 73)(28 52 74)(29 53 75)(30 54 76)(31 55 77)(32 56 78)
(1 25)(2 18)(3 27)(4 20)(5 29)(6 22)(7 31)(8 24)(9 17)(10 26)(11 19)(12 28)(13 21)(14 30)(15 23)(16 32)(33 59)(34 52)(35 61)(36 54)(37 63)(38 56)(39 49)(40 58)(41 51)(42 60)(43 53)(44 62)(45 55)(46 64)(47 57)(48 50)(65 88)(66 81)(67 90)(68 83)(69 92)(70 85)(71 94)(72 87)(73 96)(74 89)(75 82)(76 91)(77 84)(78 93)(79 86)(80 95)

G:=sub<Sym(96)| (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)(17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32)(33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48)(49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)(65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80)(81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96), (2,8)(3,15)(4,6)(5,13)(7,11)(10,16)(12,14)(17,25)(18,32)(19,23)(20,30)(22,28)(24,26)(27,31)(33,45)(34,36)(35,43)(37,41)(38,48)(40,46)(42,44)(49,57)(50,64)(51,55)(52,62)(54,60)(56,58)(59,63)(65,69)(66,76)(68,74)(70,72)(71,79)(73,77)(78,80)(81,83)(82,90)(84,88)(85,95)(87,93)(89,91)(92,96), (1,94,39)(2,95,40)(3,96,41)(4,81,42)(5,82,43)(6,83,44)(7,84,45)(8,85,46)(9,86,47)(10,87,48)(11,88,33)(12,89,34)(13,90,35)(14,91,36)(15,92,37)(16,93,38)(17,57,79)(18,58,80)(19,59,65)(20,60,66)(21,61,67)(22,62,68)(23,63,69)(24,64,70)(25,49,71)(26,50,72)(27,51,73)(28,52,74)(29,53,75)(30,54,76)(31,55,77)(32,56,78), (1,25)(2,18)(3,27)(4,20)(5,29)(6,22)(7,31)(8,24)(9,17)(10,26)(11,19)(12,28)(13,21)(14,30)(15,23)(16,32)(33,59)(34,52)(35,61)(36,54)(37,63)(38,56)(39,49)(40,58)(41,51)(42,60)(43,53)(44,62)(45,55)(46,64)(47,57)(48,50)(65,88)(66,81)(67,90)(68,83)(69,92)(70,85)(71,94)(72,87)(73,96)(74,89)(75,82)(76,91)(77,84)(78,93)(79,86)(80,95)>;

G:=Group( (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)(17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32)(33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48)(49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)(65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80)(81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96), (2,8)(3,15)(4,6)(5,13)(7,11)(10,16)(12,14)(17,25)(18,32)(19,23)(20,30)(22,28)(24,26)(27,31)(33,45)(34,36)(35,43)(37,41)(38,48)(40,46)(42,44)(49,57)(50,64)(51,55)(52,62)(54,60)(56,58)(59,63)(65,69)(66,76)(68,74)(70,72)(71,79)(73,77)(78,80)(81,83)(82,90)(84,88)(85,95)(87,93)(89,91)(92,96), (1,94,39)(2,95,40)(3,96,41)(4,81,42)(5,82,43)(6,83,44)(7,84,45)(8,85,46)(9,86,47)(10,87,48)(11,88,33)(12,89,34)(13,90,35)(14,91,36)(15,92,37)(16,93,38)(17,57,79)(18,58,80)(19,59,65)(20,60,66)(21,61,67)(22,62,68)(23,63,69)(24,64,70)(25,49,71)(26,50,72)(27,51,73)(28,52,74)(29,53,75)(30,54,76)(31,55,77)(32,56,78), (1,25)(2,18)(3,27)(4,20)(5,29)(6,22)(7,31)(8,24)(9,17)(10,26)(11,19)(12,28)(13,21)(14,30)(15,23)(16,32)(33,59)(34,52)(35,61)(36,54)(37,63)(38,56)(39,49)(40,58)(41,51)(42,60)(43,53)(44,62)(45,55)(46,64)(47,57)(48,50)(65,88)(66,81)(67,90)(68,83)(69,92)(70,85)(71,94)(72,87)(73,96)(74,89)(75,82)(76,91)(77,84)(78,93)(79,86)(80,95) );

G=PermutationGroup([[(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),(17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32),(33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48),(49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64),(65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80),(81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96)], [(2,8),(3,15),(4,6),(5,13),(7,11),(10,16),(12,14),(17,25),(18,32),(19,23),(20,30),(22,28),(24,26),(27,31),(33,45),(34,36),(35,43),(37,41),(38,48),(40,46),(42,44),(49,57),(50,64),(51,55),(52,62),(54,60),(56,58),(59,63),(65,69),(66,76),(68,74),(70,72),(71,79),(73,77),(78,80),(81,83),(82,90),(84,88),(85,95),(87,93),(89,91),(92,96)], [(1,94,39),(2,95,40),(3,96,41),(4,81,42),(5,82,43),(6,83,44),(7,84,45),(8,85,46),(9,86,47),(10,87,48),(11,88,33),(12,89,34),(13,90,35),(14,91,36),(15,92,37),(16,93,38),(17,57,79),(18,58,80),(19,59,65),(20,60,66),(21,61,67),(22,62,68),(23,63,69),(24,64,70),(25,49,71),(26,50,72),(27,51,73),(28,52,74),(29,53,75),(30,54,76),(31,55,77),(32,56,78)], [(1,25),(2,18),(3,27),(4,20),(5,29),(6,22),(7,31),(8,24),(9,17),(10,26),(11,19),(12,28),(13,21),(14,30),(15,23),(16,32),(33,59),(34,52),(35,61),(36,54),(37,63),(38,56),(39,49),(40,58),(41,51),(42,60),(43,53),(44,62),(45,55),(46,64),(47,57),(48,50),(65,88),(66,81),(67,90),(68,83),(69,92),(70,85),(71,94),(72,87),(73,96),(74,89),(75,82),(76,91),(77,84),(78,93),(79,86),(80,95)]])

Matrix representation of SD32⋊S3 in GL4(𝔽7) generated by

 0 5 3 6 3 2 3 3 6 2 2 6 5 4 5 3
,
 5 3 1 6 1 0 0 5 0 0 6 0 6 1 4 3
,
 0 0 5 2 5 3 0 3 2 5 0 3 5 5 1 2
,
 3 2 2 2 3 0 1 0 5 2 1 1 2 2 2 3
G:=sub<GL(4,GF(7))| [0,3,6,5,5,2,2,4,3,3,2,5,6,3,6,3],[5,1,0,6,3,0,0,1,1,0,6,4,6,5,0,3],[0,5,2,5,0,3,5,5,5,0,0,1,2,3,3,2],[3,3,5,2,2,0,2,2,2,1,1,2,2,0,1,3] >;

SD32⋊S3 in GAP, Magma, Sage, TeX

{\rm SD}_{32}\rtimes S_3
% in TeX

G:=Group("SD32:S3");
// GroupNames label

G:=SmallGroup(192,474);
// by ID

G=gap.SmallGroup(192,474);
# by ID

G:=PCGroup([7,-2,-2,-2,-2,-2,-2,-3,232,758,135,346,185,192,851,438,102,6278]);
// Polycyclic

G:=Group<a,b,c,d|a^16=b^2=c^3=d^2=1,b*a*b=a^7,a*c=c*a,d*a*d=a^9,b*c=c*b,d*b*d=a^8*b,d*c*d=c^-1>;
// generators/relations

Export

׿
×
𝔽


text:
Thread: find the inverse

1. find the inverse

f(x) = e^(x^3) + 3x
show that f(x) is invertible

2. Hello,

$f'(x)>0$

Hence f is a strictly monotone function. And thus it is a bijection and is invertible.

3. thanks so much
can u help with this part as well

Let g(y) denote the inverse of f(x). What is the domain and range of g(y)? What is g(e+3)?
Find g'(e+3)

4. Originally Posted by rphagoo
thanks so much
can u help with this part as well

Let g(y) denote the inverse of f(x).

What is the domain and range of g(y)? the range and domain of f(x)

What is g(e+3)?

f(1) = e+3 , so g(e+3) = 1

Find g'(e+3)

$\textcolor{red}{g'(e+3) = \frac{1}{f'(1)}}$
...

5. thanks so much!

format: plain


text:
AL N*N Tic Tac Toe Game

Here is a simple Tic Tac Toe game. I would like to know how I can improve this code further.

#include <iostream>
#include <cctype>
#include <array>
#include <random>

enum struct Player : char
{
none    = '-',
first   = 'X',
second  = 'O'
};

std::ostream& operator<<(std::ostream& os, Player const& p)
{
return os << std::underlying_type<Player>::type(p);
}

enum struct Type : int
{
row,
column,
diagonal
};

enum struct Diagonals : int
{
leftTopRightBottom,
rightTopleftBottom
};

template<std::size_t DIM>
class TicTacToe
{
public:
TicTacToe();

bool isFull() const;
void draw() const;
bool isWinner(Player player) const;
bool applyMove(Player player, std::size_t row, std::size_t column);

private:
std::size_t mRemain = DIM * DIM;
std::array<Player, DIM * DIM> mGrid;
};

template<int DIM>
struct Match
{
Match(Type t, int i)
: mCategory(t)
, mNumber(i)
{}

bool operator() (int number) const
{
switch (mCategory)
{
case Type::row:
return (std::abs(number / DIM) == mNumber);

case Type::column:
return (number % DIM == mNumber);

case Type::diagonal:
if (mNumber == static_cast<int>(Diagonals::leftTopRightBottom))
{
return ((std::abs(number / DIM) - number % DIM) == mNumber);
}

if (mNumber == static_cast<int>(Diagonals::rightTopleftBottom))
{
return ((std::abs(number / DIM) + number % DIM) == DIM - mNumber);
}

default:
return false;
}
}

Type mCategory;
int mNumber;
};

template<std::size_t DIM>
TicTacToe<DIM>::TicTacToe()
{
mGrid.fill(Player::none);
}

template<std::size_t DIM>
bool TicTacToe<DIM>::applyMove(Player player, std::size_t row, std::size_t column)
{
std::size_t position = row + DIM * column;

if ((position > mGrid.size()) || (mGrid[position] != Player::none))
{
return true;
}

--mRemain;

mGrid[position] = player;

return false;
}

template<std::size_t DIM>
bool TicTacToe<DIM>::isFull() const
{
return (mRemain == 0);
}

template<std::size_t DIM>
bool TicTacToe<DIM>::isWinner(Player player) const
{
std::array<bool, 2 * (DIM + 1)> win;

win.fill(true);

int j = 0;

for (auto i : mGrid)
{
int x = j++;

for (auto k = 0; k < DIM; ++k)
{
if (Match<DIM>(Type::column, k)(x))
{
win[k] &= i == player;
}

if (Match<DIM>(Type::row, k)(x))
{
win[DIM + k] &= i == player;
}

if (Match<DIM>(Type::diagonal, k)(x))
{
win[2 * DIM + k] &= i == player;
}
}
}

for (auto i : win)
{
if (i)
{
return true;
}
}

return false;
}

template<std::size_t DIM>
void TicTacToe<DIM>::draw() const
{
std::cout << ' ';
for (auto i = 1; i <= DIM; ++i)
{
std::cout << "  " << i;
}

int j = 0;
char A = 'A';

for (auto i : mGrid)
{
if (j == 0)
{
std::cout << "\n " << A++;
j = DIM;
}
--j;

std::cout << ' ' << i << ' ';
}

std::cout << "\n\n";
}

struct Random
{
Random(int min, int max)
: mUniformDistribution(min, max)
{}

int operator()()
{
return mUniformDistribution(mEngine);
}

std::default_random_engine mEngine{ std::random_device()() };
std::uniform_int_distribution<int> mUniformDistribution;
};

class Game
{
public:
void run();

private:
void showResult() const;
void turn();

static const std::size_t mDim = 4;
int mNumberOfPlayers = 2;
TicTacToe<mDim> mGame;
std::array<Player, mNumberOfPlayers> mPlayers{ { Player::first, Player::second } };
int mPlayer = 1;
Random getRandom{ 0, mDim - 1 };
};

void Game::run()
{
while (!mGame.isWinner(mPlayers[mPlayer]) && !mGame.isFull())
{
mPlayer ^= 1;
mGame.draw();
turn();
}

showResult();
}

void Game::showResult() const
{
mGame.draw();

if (mGame.isWinner(mPlayers[mPlayer]))
{
std::cout << "\n" << mPlayers[mPlayer] << " is the Winner!\n";
}
else
{
std::cout << "\nTie game!\n";
}
}

void Game::turn()
{
char row = 0;
char column = 0;

for (bool pending = true; pending;)
{
switch (mPlayers[mPlayer])
{
case Player::first:
std::cout << "\n" << mPlayers[mPlayer] << ": Please play. \n";
std::cout << "Row(1,2,3,...): ";
std::cin >> row;
std::cout << mPlayers[mPlayer] << ": Column(a,b,c,...): ";
std::cin >> column;

column = std::toupper(column) - 'A';
row -= '1';

pending = column < 0 || row < 0 || mGame.applyMove(mPlayers[mPlayer], row, column);

if (pending)
{
std::cout << "Invalid position.  Try again.\n";
}
break;
case Player::second:
row = getRandom();
column = getRandom();

pending = mGame.applyMove(mPlayers[mPlayer], row, column);
break;
}
}

std::cout << "\n\n";
}

int main()
{
Game game;
game.run();
}

Avoid non-standard extensions

While your compiler may allow them, the use of non-standard extensions makes your code non-portable and less readable to others. In particular, we have this:

int mNumberOfPlayers = 2;
// ...
std::array<Player, mNumberOfPlayers> mPlayers{ { Player::first, Player::second } };

The problem is that mNumberOfPlayers is neither const nor static, so the std::array size is indeterminate.

Reconsider the class roles

The division of the game in to Game and TicTacToe classes seems odd to me. I did not discern a logical reason for them not to be a single class. Maybe the idea was to separate the playing field from the game logic? If so, then it seems that perhaps applyMove and isWinner would more logically belong to the Game rather than the board. Match also seems to be superfluous.

Consider an array rather than an enum

The use of the enum for Player has some good features, such as type safety, but it doesn't lend itself to allowing more than two players, which seems to have been the idea behind having the mNumberOfPlayers instance variable. An array of player tokens might have been a better choice, with some tie between the number of players and the rest of the game. Similarly, the only places that Diagonals are used, they're used with a static_cast<int>. That would seem to be a sign that they shouldn't have been declared as enum.

Understand what auto does

In some instances, the use of auto is perfectly clear and well suited to the job, as when using a "range for":

for (auto i : mGrid)

However, other places it doesn't make as much sense:

for (auto i = 1; i <= DIM; ++i)

The variable i in the latter case will always be an int because 1 is an int. Some compilers will complain about comparing signed and unsigned values here.

Be consistent with template parameters

In some cases, DIM is an int, but in others it's a std::size_t. It's hard to imagine that was intentional and I can't think of a use, so it's probably better to declare them all the same way. Alternatively, see the next suggestion.

Use a constructor argument instead of a template parameter

Having the Match and TicTacToe use DIM as a template parameter instead of as a constructor argument means that the code must be recompiled to accomodate a different size board. With a bit of redesign, it could easily instead be a constructor argument, allowing flexible use without recompiling.

Reconsider member functions

The applyMove() member function does two things -- it checks to see if the move would be valid and then applies it if it's valid. I'd suggest that those two steps might be different functions since a function that checks but does not alter the board might be very handy for a smarter automatic player.

Consider allowing a std::ostream parameter for output

As it stands, the draw() function is only capable of sending its output to std::cout, but it could easily be made more flexible by allowing it to take an std::ostream as a parameter. In fact, I'd be inclined to refactor it as a friend like this:

std::ostream& operator<<(std::ostream& out, const TicTacToe& ttt) { //... }

Consider making Random a templated class

The use of the Random class is good and appropriate. One suggestion I have is that it might be a candidate for a template to allow a range of either int or unsigned values. It doesn't make much practical difference, but might be handy to quiet signed/unsigned type mismatch warnings if an unsigned were needed.

Be cautious with object construction/destruction

In the shortest possible 4x4 game (4 moves by each of 2 players) there are 1728 calls each to the Match constructor and destructor due to the way that class is used in isWinner. That is neither particularly efficient for the computer, nor does it particularly simplify the code for a human reader, so I would strongly advise rewriting the isWinner code.

Consider separating I/O from program logic

The showResult() and draw() functions are both clearly primarily related to I/O function and do nothing else. That's good design. The turn() function could similarly be refactored into the logic portion and the I/O portion, which would make it easier to see how to adapt the program to, say, a non-text GUI version, without altering the underlying game logic.

Allow rational reuse of objects

If we want to play the game twice, there is currently no provision to do so because the game state can't be reset using the existing interface. Adding a Game.reset() function would be simple to do and add to the usability of the object.

Several things worth pointing out here I think.

Match

There is zero reason for Match to take a category or really anything else. You don't need the Type or Diagonals enums. Given a move, you sohuld be able to determine if that move completed a row, column, or major diagonal.

// return true if given player won with the given move,
// false otherwise
bool won(Player, size_t row, size_t column);

TicTacToe

You may find it easier to just use a 2-d array to represent a 2-d object. That way:

bool applyMove(Player player, size_t row, size_t col)
{
Player& square = mGrid.at(row).at(col);
if (square == Player::none) {
square = player;
return true;
}
else {
return false;
}
}

Also you'll note I flipped the return type of applyMove. Returning true on success makes way more sense. Also this will throw std::out_of_range instead of silently doing nothing - that way you can catch that in Game and log an appropriate message. This differentiates an invalid move from attempting to play on a bad square.

Game

It is confusing to have getRandom be a member variable rather than a member function. I would change it. It took me a while to find the first time around. Now, turn() should just defer to the appropriate user:

void turn() {
if (mPlayers[mPlayer] == Player::first) {
userTurn();
}
else {
compTurn();
}
}

The pending loop is weird. Just have each sub-case return when they're done.

Also for the compTurn part, picking a random square each time is hugely inefficient. If there's only 1 open square left, you're spending on average N^2 loops to try to find it. Instead, first find the empty squares then pick a random one:

std::vector<std::pair<size_t, size_t>> open;
for (size_t r = 0; r < mDim; ++r) {
for (size_t c = 0; c < mDim; ++c) {
if (mGame.isOpen(r, c)) {
open.emplace_back(r, c);
}
}
}

auto choice = chooseRandom(open);
applyMove(Player::second, choice.first, choice.second);

Also, the TicTacToe member object should really be named board. It's not the Game after all. The Game is already the Game.

Lastly, why is TicTacToe a class template? If you made the dimension a variable and used a vector<vector<Player>> instead, you could ask for the dimension as input up front.


text:
## The Annals of Statistics

### All Admissible Linear Estimators of the Mean of a Gaussian Distribution on a Hilbert Space

Avi Mandelbaum

#### Abstract

We consider linear estimators for the mean $\theta$ of a Gaussian distribution $N(\theta, C)$ on a Hilbert space, when the covariance operator $C$ is known. It was argued in a previous work that the natural class of linear estimators is the class of measurable linear transformations. Using the simplest quadratic loss we prove that the linear estimator $L$ is admissible if and only if the operator $C^{-1/2}LC^{1/2}$ is Hilbert-Schmidt, self-adjoint, its eigenvalues are all between 0 and 1 and two are equal to 1 at the most. As an application of the general theory, we investigate some linear estimators for the drift function of a Brownian motion.

#### Article information

Source
Ann. Statist., Volume 12, Number 4 (1984), 1448-1466.

Dates
First available in Project Euclid: 12 April 2007

https://projecteuclid.org/euclid.aos/1176346803

Digital Object Identifier
doi:10.1214/aos/1176346803

Mathematical Reviews number (MathSciNet)
MR760699

Zentralblatt MATH identifier
0558.62009

JSTOR


text:
# toHTML() method to generate HTML output #690

Closed
opened this Issue Jul 19, 2016 · 49 comments

Projects
None yet
3 participants
Contributor

### Nekomajin42 commented Jul 19, 2016 • edited

Hi Jos!

After the discussion in a previous issue (#684), I decided to give the toHTML() function a try. The regexp and the tree.traverse() solutions were both messy, and I really needed a customisable HTML output.

At the end, I implemented a toHTML() function to every node, and it works like a charm. I'd like to contribute it, if it's OK to you. It would be a good addition to the library for those who want to build web-based interfaces on top of math.js.

The idea was to enclose every element of the expression between  tags and give them semantic class names. In this way, I get a nice structure, which can be styled easily.

# Examples

For the expression 2+2=5 the output will be:
2
+
2
=
5

For the expression (a<42)?true:false the output will be:
(
a
<
42
)
?
true
:
false

# Styling

Using the class names, it is really easy to assign different colors or other styles to the elements. The user even has the ability to decide about spaces without tempering the toString() function.

An example for the first expression:
.number {color: blue;}
.operator::before, .operator::after {content: " ";}

If you give it a go, I will send a pull request and I can write a documentation too. (However, I have 18 pending items in the test, and I don't understand how I caused them, because I did nothing else besides this implementation in the *Node.js files.)

Owner

### josdejong commented Jul 21, 2016

 That's nice! Thanks for your offer to contribute! Your proposal looks good. There is only one thing: it may be wise to give the classes a more specific class name like math-number, math-operator, etc. to prevent possible CSS collisions with frameworks like bootstrap. What do you think? As for the problems with the tests: can you tell me what errors you get?

Contributor

### Nekomajin42 commented Jul 21, 2016 • edited

 It's a good idea! I will change the class names. After the build, I will run a test too and show you the results. However, a few additions to the nodes would be helpful. First of all, there was a discusson before about the introduction of UnitNodes. What is the status of that? My greates problem is still that a SymbolNode can contain a lot of different things. It might be indifferent for the parser, but it's really hard to differentiate between them for me. It is easy to filter a few special symbold like i, NaN, etc., but to do it with units... Not to mention the user defined units. Second, the function and operator nodes could have a category property. So we can append them as class names too, like .math-arithmetic-function. In this way, we can have different styles for constructors, expression functions, utils and such. The same for operators. We might want to display a+b without spaces, but a and b is bad without them. Third, the ConstantNode should specify the type of numbers. Besides "number", there should be a "BigNumber", "Complex" and "Fraction" value. Please, tell me what do you think!
Contributor

### Nekomajin42 commented Jul 21, 2016

 Curretly the following classes exist in the toHTML() function: .math-number - Numbers and "Infinity" .math-string - Strings and "NaN" .math-boolean - "true" and "false" .math-variable - Variables names (currently working only with object properties) .math-property - Property names of objects (currently working only with object properties) .math-keyword - "function" .math-symbol - Some kind of symbols, with the following special cases: .math-imaginary-symbol - "i" .math-novalue-symbol - "null" and "uninitialized" .math-operator - Any kind of operator, with the following special cases: .math-unary-operator - Unary operators .math-lefthand-unary-operator - Lefthand unary operators .math-righthand-unary-operator - Righthand unary operators .math-binary-operator - Binary operators .math-implicit-binary-operator - Implicit binary operators .math-explicit-binary-operator - Explicit binary operators .math-separator-operator - ",", ":", ";" and "\n" .math-assignment-operator - "=" .math-accessor-operator - "." .math-range-operator - ":" .math-conditional-operator - "?" and ":" .math-function - Any kind of function names (symbols), with the following special cases: .math-custom-function - User defined function names .math-parenthesis - Any kind of parenthesis, with the following special cases: .math-round-parenthesis - "(" and ")" .math-square-parenthesis - "[" and "]" .math-curly-parenthesis - "{" and "}" Any remarks?
Contributor

### Nekomajin42 commented Jul 21, 2016 • edited

 And here are the pending test results: - should import a factory with name - should import a factory with path - should import a factory without name - should pass the namespace to a factory function - should import an Array - should calculate the modulus of bignumbers for fractions - should calculate the modulus of bignumbers for negative values - should multiply a bignumber and a unit correctly - should multiply a bignumber and a unit without value correctly - should return bignumber unary minus of a boolean - should return bignumber unary plus of a boolean - should return bignumber unary plus on a string - should calculate xgcd for edge cases with negative values - should not cast a single number or boolean to string - should throw an error if called with invalid arguments - should return the quantileSeq of an array of bignumbers with number probability - should throw an error when input array does not have two dimensions - should throw an error when the dimensions of the input array are invalid
Collaborator

### FSMaxB commented Jul 23, 2016

 Looks good to me so far. The only thing that looks a bit odd to me is that NaN is treated like a string. I think it should be either a number or have its own class. @Nekomajin42 If you have questions or ideas about using or improving the common infrastructure used by conversion functions (toString and toTex) feel free to reach out to me.
Contributor

### Nekomajin42 commented Jul 23, 2016

 @FSMaxB Thanks! Since NaN is not a number, I don't want to treat it as a number. But an own class is a good idea. What do you think about the suggestions regarding the Nodes?
Collaborator

### FSMaxB commented Jul 23, 2016

 Looks good to me. The only thing I'm not sure about is if the separators should really be treated as operators, but I don't have any suggestions either.
Owner

### josdejong commented Jul 25, 2016

 Sounds good @Nekomajin42, your list with classes looks complete. How about splitting operators and separtors into two separate categories? You refer to the sort mentioning of a UnitNode here: #279 (comment). It's not trivial to implement such a UnitNode, it would require some serious changes. Right now units are evaluated as regular variables at evaluation time. At parse time the parser doesn't know whether a symbol is a unit or not. Maybe it makes sense to create a helper function which recognizes whether a Node tree holds a unit (like m/s^2), by traversing the node and its childs and checks whether: it only contains OperatorNodes multiplication/division/power, and each of the operands is a SymbolNode, which name is a unit (Unit.isValuelessUnit(...) == true) the second argument of power OperatorNodes is an integer number (ConstantNode) In that case you could use toString() inside toHTML() and return markup for a unit. Does that make sense?
Contributor

### Nekomajin42 commented Jul 25, 2016

 The operator/separator idea is fine. I will make the changes. And I understand your workaround. I will give it a try. However, the same problem exists for built in constants. Would it be possible to create a list/dictionary before the first parse event from the hard coded constants, units and prefixes? And finally, can you take a look at the pending test results? I use the latest stable branch for developement, so I guess there should be no issues, but I don't understand what is the problem.
Owner

### josdejong commented Jul 27, 2016

 Would it be possible to create a list/dictionary before the first parse event from the hard coded constants, units and prefixes? Yes, I think you can simply check their existence in the math namespace And finally, can you take a look at the pending test results? Sure! Where can I see your tests?
Contributor

### Nekomajin42 commented Jul 27, 2016

 Sure! Where can I see your tests? A few comments above. :) Well, I am not sure what am I doing. But after I made the changes in the Node* files, I ran the npm test command, and the results were a lot of passed tests and 18 pending. You can see those above. This is my first time using Node.js and npm, so I don't know whether I caused them.
Owner

### josdejong commented Jul 27, 2016

 To see what's going wrong I have to get your code on my computer and run the tests here. Are you familiar with git? Normal way is to clone the mathjs project, make your changes in a new branch, and push that to your clone on github - at that point I can simply grab your version of the code from github and run it on my computer.
Contributor

### Nekomajin42 commented Jul 27, 2016

 I am doing it right now.
Contributor

### Nekomajin42 commented Jul 27, 2016

 I finally managed to make it work. You can find it here: https://github.com/Nekomajin42/mathjs
Owner

### josdejong commented Jul 27, 2016

 I've run your clone on my computer, and it runs fine here. Are you maybe using an old version of node.js or something like that? Can you post the exact output (the errors at least) you get when running the tests?
Contributor

### Nekomajin42 commented Jul 27, 2016

 There are no errors, only pending items. You can see them here: #690 (comment) I am using v4.4.7, which is the latest LTS version, according to the official page. Should I update it? Btw, I have problem with comments and function assignments. Both of them give an error: input: "#comment" output: "TypeError: Cannot read property 'toString' of undefined" input: "f(x)=x+x" output: "SyntaxError: Unexpected operator { (char 18)" Is it possible that they are related to the Node.js version?
Owner

### josdejong commented Jul 28, 2016

 Ah, now I get it. These 18 tests are just skipped tests (I thought you had 18 tests failing or something). Most are just unit tests that need to be implemented for better test coverage. You can ignore this. node.js v4 works just fine, that can't be the problem here. How can I reproduce your issue with comments and function assignments? Do you run these expressions in the command line application or something?
Contributor

### Nekomajin42 commented Jul 28, 2016

 OK, I see now. I'm building a web based interface. When the user submits an expression, I call the parser.eval() method to evaluate it. It works fine with simple expressions, like 5+5, or built-in function calls, I can even handle the help() function, but those two always give the same error.
Owner

### josdejong commented Aug 1, 2016

 How can I reproduce this? Can you demonstrate it in a clone of this jsbin for example?
Contributor

### Nekomajin42 commented Aug 1, 2016

 Here is what I do in my script: http://jsbin.com/fucamuquho/1/edit?html,output I get the same errors. The only difference, is that I get the expressions from a form element, but that's also a string, so it's the same.
Owner

### josdejong commented Aug 1, 2016

 argh! jsbin is down
Contributor

### Nekomajin42 commented Aug 1, 2016 • edited by FSMaxB

 Here is my code: var parser = math.parser(); // comment print("#comment"); // function assignment print("f(x)=x^2"); // helper function to output formatted results. function print(expression) { try { var result = parser.eval(expression); document.write(math.parse(result.toString()) + '
'); } catch (e) { document.write(e + '
'); } } The outputs are: TypeError: Cannot read property 'toString' of undefined SyntaxError: Unexpected operator { (char 18) The first one for the comment, the second one for the function assignment.
Owner

### josdejong commented Aug 1, 2016

 The issue is because you call toString() on the result and then try to parse it again. I suppose you want to do: document.write(math.format(result) + '
'); instead of document.write(math.parse(result.toString()) + '
');
Contributor

### Nekomajin42 commented Aug 1, 2016

 No, I want to parse it again, because I have to use the toHTML() on the result too. Parsing the evaluated result works fine with other expressions. Only these to give me trouble.
Owner

### josdejong commented Aug 1, 2016

 In that case I think you don't want to use the parser, but simply do something like this: var expression = 'f(x) = x^2' var node = math.parse(expression) var html = node.toHTML() var scope = {} var result = node.compile().eval(scope) var formattedResult = math.format(result)
Contributor

### Nekomajin42 commented Aug 7, 2016

 I managed to solve the function assignment issue. However, the comment issue still exists. math.parse("#comment") returns ConstantNode {value: "undefined", valueType: "undefined"}, while math.eval("#comment") returns undefined. You can try this in the JSbin you inserted a few comments above. It is strange, because math.parse("comment") returns SymbolNode {name: "comment"}, and math.eval("comment") returns Error: Undefined symbol comment, which is the correct behavior. So I assume, the parser looks for the # character to find comments. But then why does it return a ConstantNode?
Owner

### josdejong commented Aug 8, 2016

 Comments are simply ignored so math.parse('#comment') results in the same as math.parse(''): it is an empty expression which is parsed as a constant undefined. Things that never change, like booleans, numbers, strings, null, and undefined are parsed into a ConstantNode. Variables which value has to be evaluated at evaluation time, like pi, myVariable, and comment, are parsed into a SymbolNode.
Contributor

### Nekomajin42 commented Aug 8, 2016

 OK, I get it now. From the docs: Comments can be added to explain or describe calculations in the text. A comment starts with a sharp sign character #, and ends at the end of the line. A line can contain a comment only, or can contain an expression followed by a comment. I think it is misleading, because it suggests that the parser handles the comments, like a string constant or something. No problem though, I can handle it at my end. Thanks! And I am about to finish the toHTML implementation. I will send a pull request soon.
Owner

### josdejong commented Aug 9, 2016

 OK, looking forward to your PR :)
Contributor

### Nekomajin42 commented Aug 10, 2016

 OK, it is finished, except the comment thing. I've made it work in my calculator interface, but it is messy. After you previous comment, I finally understand how the parser handles comments, and from the perspective of evaluation, it's fine to skip any characters from # to \n. However, the point of the HTML output is to format not just the result, but the input expression too, to create rich interfaces without regexp. And in the current implementation, the text of the comment gets lost, so I can not print it back with the rest of the (formatted) expression. So, can we somehow store the text of the comment in the expression tree?
Collaborator

### FSMaxB commented Aug 11, 2016

 One Suggestion: Add a comment attribute to Node that represents a comment right to the Node. Problem with this approach: It doesn't support comments at the beginning of an expression.
Contributor

### Nekomajin42 commented Aug 11, 2016

 If an expression is empty, it is evaluated as a ConstantNode with undefined value, isn't it? So a comment, which starts at the beginning of the line, is actually a ConstantNode with an undefined value and a comment attribute. It can work.
Collaborator

### FSMaxB commented Aug 11, 2016 • edited

 You're right, this should actually work. I think this would need a global option though in order to turn it off by default for HTML, String and LaTeX.
Owner

### josdejong commented Aug 14, 2016

 Hm, that's nasty. It's not just comments, this will also be an issue with white space, which isn't stored by the expression parser. Like when someone enters 2 or more spaces between two values, or uses a tab. Maybe we can extend the parser such that it can store white space left of a node, and white space and an optional comment right from the node? So we can always reconstruct the exact input from a node tree using toString and toHTML?
Contributor

### Nekomajin42 commented Aug 14, 2016

 I don't think we should store the exact input with all the different white spaces. If you build an interface, you can always leave the input on the screen, or print back the original expression with any kind of modifications. Both toString and toHTML exist to format the input/output, not to store the original expression, as it was typed be the user, because that's easy to achieve without the API. (The HTML output even gives you the opportunity to decide about white spaces via CSS.) My problem with the comments is their content. I can filter them, store them, even format them on my end, but it's very messy to store their position. (Imagine a multi-line expression with comments at the end of a few line, but not all of them!) Inside the comment, I think we should keep everything as is, and don't mind multiple white spaces. But, as @FSMaxB suggested, we can extend the Nodes with a comment property, and store the comment of the line in the comment property of the root Node. I think a few Nodes can not be roots by themselves (index, range, parenthesis?), but for the others, there are the following scenarios: The line is a single expression with a comment at the end. The comment is appended to the root of the expression. The input is a multi-line expression. The comments are appended to the roots inside the BlockNode. The line is a single comment only. The comment is appended to the root, which is a ConstantNode with valueType undefined. The input is a multi-line expression with single comment lines at the beginning, or anywhere in the middle. The solution is the mix of the previous cases. What do you think?
Collaborator

### FSMaxB commented Aug 15, 2016

 I agree that storing all whitespaces might be a bit overkill.
Owner

### josdejong commented Aug 15, 2016

 I'm not really in favor of storing white spaces either, it feels out of scope of the intention of the parser. But if it solves a serious need we can consider it. Keeping a comment property sounds similarly out of scope to me. So if we go that way anyway we can probably solve it in a more general way storing all white spaces information ignored right now by the parser and be able to reproduce the original expression 100% precise instead of 95%. Just thinking aloud. My problem with the comments is their content. I can filter them, store them, even format them on my end, but it's very messy to store their position. Why is this not the case with white spaces in your editor, why don't you have to (re)store them? Isn't that the same problem as keeping a comment intact?
Contributor

### Nekomajin42 commented Aug 15, 2016

 Well, my editor does not print back the original expression. It prints the HTML output of the parsed expression, and white spaces between operands/operators are handled by CSS. I don't want to keep multiple white-spaces at all, but I need to keep the comment strings. However, I see your point, but still don't think white-spaces are as important as comments. The latter adds extra information to the expression, while the other is only there for readability.
Owner

### josdejong commented Aug 17, 2016

 Ah then the white space issue is indeed no problem in your case. A comment indeed holds information so we could store that somehow. That's a good argument. Ok then let's go for that: store comments, ignore whitespaces. How can we concretely store this comment? I can think of two ways: Wrap the expression in a new CommentNode which holds the comment Allow setting properties in a meta data object on every Node, like myNode.setMeta({comment: 'The comment'}) var comment = myNode.getMeta().comment What do you think?
Contributor

### Nekomajin42 commented Aug 17, 2016

 Well, for the sake of the toHTML and toString functions, the CommentNode would be easier, I guess. But what about a third way? The one from @FSMaxB #690 (comment) ? The parser reads the comment, and stores it until the end of the parse operation. At that time, it already knows which Node is the root, so it can append the comment to the root, and only to the root. The toHTML and toString can check whether the .comment property is undefined, and print it or skip it. What do you think?
Collaborator

### FSMaxB commented Aug 18, 2016

 Do we have inline comments, like an equivalent to /* */ in C or are there any plans to do this in the future? If yes it might not be a good idea to just add it to the root node. My idea was more like allowing it to be stored in every kind of node. For example suppose we have inline comments: With 2 * /* comment */ 3 it would be stored in the ConstantNode's leftComment attribute.
Owner

### josdejong commented Aug 18, 2016

 @FSMaxB block comments /* */ are not supported right now though we could add them in the future. What is supported though is multiple lines in one expression like a=2 #foo \n b=3 #bar, so we can actually have comments in nested nodes. @Nekomajin42 yes the setMeta({comment: 'The comment'}) solution is more or less the same as storing a plain property .comment on a node (the idea of Max). I thought it may be a good idea to clearly separate the stuff that's needed for calculations from "meta" stuff (i.e. a comment) by getting/setting it via explicit methods getMeta and setMeta. Just an idea, it may be overkill. .comment will work just as good in practice, but adding this property to the Nodes sometimes (and leaving it undefined in most cases?) feels a bit hacky. Besides the way how we store the comment, we have to decide whether the default behavior for toString, toTex and toHTML will be: output comments too or not? The typical use cases for these methods that I can think of are: display an unambiguous or colored text output including parenthesis to the user like https://qalculate.github.io/ does display the entered expression in a mathematical way with toTex (see this example). Use toString or toHTML in an editor with two way binding like @Nekomajin42 is working on to normalize, sanitize, or colorize expressions. In the first two cases you don't want the comment to be added to the output. In the third case you do want to keep the comments there, but typically you want to maintain white spaces too (though not in particular case of @Nekomajin42 ). It's most flexible if we don't output comments by default and leave it up to the developer to concat the output with a comment if any - the other way around is less convenient for the developer. Or we could create an option for this like we can customize parenthesis in the output. But if we do that I expect that people will also want to be able to (optionally) restore the exact white spacing too, what I pointed out before, so then we still should go all in. Storing all whitespace information I think is about the same amount of code compared to storing a rightComment and/or leftComment in nodes, it doesn't need to be that complicated. Let me give it a bit more thought.

### josdejong added a commit that referenced this issue Aug 23, 2016

 Comments of expressions are are now stored in the parsed nodes, see #690
 23d1786
Owner

### josdejong commented Aug 23, 2016

 I've had a look in the code to see what it would take to implement this. Storing comments is very easy, but storing all whitespace characters would be very intrusive (unlike I expected at first). So lets KISS and just add a comment property to all nodes (Max's idea). I've implemented storing comments now see 23d1786 (it's still in a separate branch feature/comments). If you agree this solves our needs I will merge it into develop. As for the behavior of toString, toTex, and toHTML: I think these methods should not output comments by default. We can leave it up to the user to append a comment if any, or introduce a new option for this.
Contributor

### Nekomajin42 commented Aug 24, 2016

 I think the HTML output could contain comments, because it's easy to hide them with CSS. But for the sake of coherence, a global option would be fine.
Owner

### josdejong commented Aug 24, 2016

 Yes indeed for HTML it would be easy to hide if unwanted but I would indeed like to keep the behavior of methods (toString, toTex, toHTML) consistent with each other. If we make such an option it would not be global, but passed as argument to the method, similar to the parenthesis option (see docs).
Owner

### josdejong commented Sep 7, 2016

 FYI: the new comment property is now available in mathjs v3.5.0.
Contributor

### Nekomajin42 commented Sep 8, 2016

 Thanks! I will look into the toHTML() fix and the unit tests for the union operations as soon as I have time. I'm a bit busy at the beginning of the school year.
Owner


text:
Monitoring Mechanical, Electronic, and Catalytic Trends in a Titanium Metal Organic Framework Under the Influence of Guest-Molecule Encapsulation Using Density Functional Theory

Abstract

In this study, we conduct a density functional theory investigation to study the mechanical stability of a titanium-based metal organic framework (MOF-901), which was hypothetically assumed to possess 2D characteristics. It is systematically found that the encapsulation of methanol enhances the mechanical stability of MOF-901 as the elastic tensors Cij of MOF-901∙nMeOH are higher than the corresponding Cij quantities reported for solvent-free MOF-901. Moreover, the 2D characteristics of MOF-901 is confirmed by verifying the negative values of C33. At the same time, the band gap of MOF-901 is observed to be solvent-dependent. In its pure form, MOF-901 possesses a direct gap (Eg) of 2.07 eV, with the valence and conduction bands mainly constituted by electrons of 4-aminobenzoate linkers. Introducing methanol into MOF-901 causes distortion to the 4-aminobenzoate geometry, thereby induces electronic degeneracy to the conduction bands. Consequently, Eg is narrowed to 1.84 eV with 5.7 wt% MeOH or 1.63 eV with 11.4 wt% MeOH. Hence, it is possible to tailor the band gap of MOF-901 by controlling methanol guest, which only acquires van der Waals interaction to the framework. In addition, our theoretical prediction shows a Ti(IV) site can undergo electronic hopping to become Ti(III) under the effect of visible light (~440–443 nm). Then, Ti(III) is capable of breaking the C-Br bond in ethyl α-bromophenylacetate spontaneously, which in turn activates the polymerization of methyl methacrylate with an energy barrier of 0.30 eV.

Introduction

Metal–Organic Frameworks, a hybrid material comprised of inorganic metal–oxo clusters and organic linking units, have been intensively studied and developed for past few decades, as proven by nearly 700,000 reported MOFs structures1. Possessing well-defined characteristics including high porosity, post-synthetic modification of crystal structure, structural engineering, and surface decoration, MOFs have emerged as promising candidates for key applications of global issues such as renewable energy2, gas storage and separation3, catalysis4,5,6, and drug release7. Among these applications, utilizing MOFs as highly tunable photocatalytic materials for catalytic transformation such as CO2 reduction, H2 production, water splitting, polymerization, and organic reactions is a key technological component of energy economics8. Hence, the quest for stable MOFs with promising optical properties and redox activities has led to the motivation of the MOF research community in the past decade.

For those purposes, MOFs based on tetravalent metal–oxo building units (i.e. Ti(IV), Zr(IV), and Hf(IV)) have been especially realized as promising candidates due to its high stability under harsh-working conditions9. Moreover, MOFs based on so-mentioned secondary building units (SBU) possess suitable band gaps for photocatalytic transformation under UV-vis irradiation which can be tailored due to the nature of MOFs structures. In order to engineer band gaps of MOFs materials, post-synthetic modification on linkers which introduces functionalities into the framework of MOFs via direct synthesis or covalent bonding, was reported by experiments as well as modeling approaches. In particular, Hendon et al10. synthesized the MIL-125-X analogues (with X = NH2, OH, and halogen) which exhibited a wide-tuning range of band gap from 1.1 eV to 3.6 eV. The modification of electronic structures and band gaps of MOFs were further demonstrated by Pham et al11. by employing state-of-the-art density functional theory12,13,14 (DFT) calculations to investigate the effect of functional groups to the isoreticular structures of MOF-5. Recently, Nguyen and co-workers introduced a high conjugation system of imine linking unit into MOF-90115, a 2D-resembled Ti-MOF constructed through imine linker and hexameric Ti–oxo cluster, to further extend the framework and reduce the band gap of the resulting material, termed MOF-902, which subsequently enhanced the photoresponsive properties compared to other competitors16.

By taking the advantage of molecular modeling method, band structure and electronic properties of MOFs can be fully explored and studied in details, which provides a new insight to engineer and optimize the optical response of MOFs, an imperative requirement in photocatalytic applications. In this article, we utilize molecular modeling through DFT calculations to investigate the mechanical stability of MOF-901 and present a novel approach to tailor the highest-occupied molecular orbital (HOMO)-lowest-unoccupied molecular orbital (LUMO) gap energy of this material by controlling guest molecules in the pores. We suspect that the encapsulation of solvent with the MOF structure would enhance the capability to sustain external pressure. In particular, we attempt to resolve such a hypothesis by investigating the contribution of guest molecules on the elastic tensors of the framework. In another aspect, we seek for an energetic profile of mechanism activation under visible-light irradiation of a polymerization reaction promoted by MOF-901 in the presence of ethyl α-bromophenylacetate co-initiator, which has been mentioned in the previous experimental report15.

Results

Electronic structure and mechanical stability from condensed-phase calculations

Electronic structure and mechanical stability of MOF-901

In a previous report, Nguyen et al15. employed power X-ray diffraction analysis to elucidate the structural information of MOF-901 (shown in Fig. 1). Upon such analysis, the unit cell parameters a and c of the hexagonal cell were reported to be 27.40 Å and 8.94 Å, respectively. In this report, we verify the structure of MOF-901 by carrying out two sets of calculations: PBE and PBE-D3 (including D3 correction terms for van der Waals interactions). After a full optimization using PBE calculations without the inclusion of empirical D3 correction, we obtain a to be 27.33 Å, which is in very good agreement with the experiment-reported parameter. However, the c lattice parameter is compressed by 7.6% (given as 8.26 Å in our calculation). In the examination of such compressing behavior, we pay most attention to the Ti-O bonds. Specifically speaking, there are two types of Ti-O bonds in the MOF-901 structure: Ti-O(methoxy) and Ti-O(carboxylate). The Ti-O(carboxylate) bond is established within the [Ti6O6(O-CH3)6(4-aminobenzoate)6] core cluster as first synthesized by Hong and Chun17, while the Ti-O(methoxy) bond links Ti to a methoxy group. The available experimental data also revealed that the two types of Ti-O bonds fell in the range of 1.98–2.00 Å. From our DFT optimization, the Ti-O(carboxylate) bond is extended to 2.12 Å, while the Ti-O(methoxy) bond is compressed in comparison with the experimental values. The compression of Ti-O(methoxy) bonds is associated with the compression of the c lattice parameter. In addition, we also observe that both Ti-O(methoxy) and Ti-O(carboxylate) bonds are tilted (Fig. 1), while in experiment, those two bonds are shown almost parallel to the z axis. Introducing the D3 correction for long-range van der Waals interactions, in principle, would enhance long-range binding energetics. With D3 correction accounted, we find the a and c lattice parameters to be 27.27 Å and 8.55 Å, respectively. It should be noted that the c axis seems to suffer less from lattice narrowing of the PBE-D3 optimization. In this case, the Ti-O(methoxy) and Ti-O(carboxylate) bonds are 2.06 Å and 1.90 Å, respectively, slightly smaller than the previous PBE-optimized values. As a result, we can verify that the compressed c lattice is caused by Ti-O tilting behavior. In addition, it should be noted that in our calculations, the long-range van der Waals interactions cannot be perfectly described by the empirical D3 correction. For validation of pseudopotentials, we perform another optimization with a consideration of semicore electron inclusion. At convergence, the c lattice parameter is more compressed in comparison with the previous PBE results. For convenience, we list the resultant a, c lattice parameters and unit-cell volume in each calculation in Table 1.

From electronic structure analysis of PBE calculations, MOF-901 is found to possess a direct HOMO-LUMO gap of 2.07 eV at the Γ point as shown in the band structure in Fig. 2a. Compared with the optical band gap (2.65 eV) measured by UV-vis diffuse reflectance spectroscopy15, our calculated Eg herein is underestimated by 22%. To our knowledge, the resultant percent error is acceptable, considering the fact that PBE calculations always underestimate Eg as a result of poor electron-hole interaction description in the exchange-correlation functional18. In a typical case of band-gap underestimation, the problematic circumstance arises severely when the 3d electrons of metal directly constitute either the HOMO or LUMO levels. Here, our situation is quite different. In this particular case of MOF-901, both HOMO and LUMO are, however, localized on the organic linkers. Thus, the band gap prediction herein does not suffer much from underestimation. When analyzing the HOMO-LUMO gap of PBE-D3 calculations, a direct gap of 2.03 eV is observed, which is slightly lower than the quantity given by conventional PBE calculations.

Subsequently, we examine the contribution of molecular orbital to the nature of HOMO-LUMO gap opening for MOF-901 by analyzing the partial density of states (PDOS) of four different groups: (1) Ti, (2) O(carboxylate), (3) methoxy, and (4) remaining 4-aminobenzoate (Fig. 2b). Even though Ti is considered as an important recipe to construct the building block for hexagonal cell formation, it is surprisingly revealed that the contribution of Ti to the overall HOMO-LUMO gap is insignificant. The cationic charge of Ti is revealed as + 1.26 without D3 correction, or + 1.25 with D3 correction. The covalent group, i.e. 4-aminobenzoate, plays a very important role instead. As we can see from the PDOS plot (Fig. 2b), the eigenstates of HOMO and LUMO are mainly constituted by the hybridized orbitals of 4-aminobenzoate, whereas the 2p orbitals of O(carboxylate) atoms dedicate a smaller contribution.

Besides the theoretical investigation of electronic structure, we also validate the mechanical stability of MOF-901 by evaluating the Cij elastic tensors19 resulted from our DFT calculations. To evaluate the unit-cell elastic response, we employ a central finite difference scheme with two ionic (or lattice) displacements (one positive and one negative) for computational feasibility. For a large structure of 336 atoms within a hexagonal unit cell, and thanks to symmetry consideration, we only need to evaluate 168 degrees of freedom for Hessian evaluation in total. The elastic tensors with consideration of rigid ions and with ionic response inclusion are reported in Table 2. It should be noted, however, that we only reported those elastic tensors given by conventional PBE calculations. The PBE-D3 calculations are not chosen in this case because of empirical fitting in the D3 parameterization, which certainly alters the MOF structure from its actual ground state given by PBE calculations.

For a particular hexagonal system, the mechanical stability can be certified if all four following conditions hold20,21

$${C}_{{11}} > |{C}_{{12}}|$$
(1)
$$2{{C}_{{13}}}^{{2}} < {C}_{{33}}({C}_{{11}}+{C}_{{12}})$$
(2)
$${C}_{{44}} > 0$$
(3)
$${C}_{{66}}=({C}_{{11}}-{C}_{{12}})/2$$
(4)

In the original formalism to calculate elastic constants using the stress-strain relationship22, only lattice distortions (with rigid ions) are considered, and the listed Cij values considering rigid ions in Table 2 provide complete satisfaction to the above inequalities. In other words, MOF-901 can be confirmed to be stable by the elastic tensors derived from lattice distortions. On the other hand, if the approximate harmonic ionic response is taken into account, C33 and C44 become negative after adding the largely negative terms from ionic response, leading to the unsatisfaction of inequalities (2) and (3). The very small value of C44 (−1 kBar) may be a result of calculation deviation from lattice deformation and ionic perturbation in a very large unit cell. As we acknowledge the compression of the c lattice parameter in the earlier part of this discussion, obtaining a negative value of C33 with ionic response inclusion is not surprising. Upon the compression in the z direction, the two types of Ti-O bonds listed above seem to suffer from bending, not from bond compression. More interestingly, the negative value of C33 truly indicates the 2D-characteristics of MOF-901. It should be noted that the z-oriented connection between layers of MOF-901 is established by an alternative zigzag bonding scheme through 4-aminobenzoate, as illustrated in Fig. 1b. Overall, upon consideration of elastic tensors given by unit-cell compression, we conclude that MOF-901 is mechanically stable with 2D characteristics.

Methanol encapsulation with MOF-901: change in electronic structure and effect on mechanical stability

As a solvent in the chemical synthesis, methanol is naturally encapsulated within the pores of MOF-901. Here, we validate different concentrations of methanol adsorbed inside the network. In general, the adsorption energy of multiple methanol molecules inside MOF-901 can be calculated using the following equation:

$${E}_{adsorption}={E}_{n\times methanol@MOF-{901}}-{E}_{MOF-{901}}-{\rm{n}}{E}_{methanol}$$
(5)

where EMOF-901, Emethanol, and En×methanol@MOF-901 are the total energies of MOF-901, an isolated methanol molecule, and MOF-901 with n methanol molecules, respectively. A negative value of Eadsorption indicates attraction between methanol and MOF-901, while a positive value supposingly indicates repulsion.

There are two levels of methanol adsorption concentration inside MOF-901 as reported in a previous experiment15. In the first case, 6 methanol molecules are encapsulated within a MOF-901 primitive cell (5.7 wt%). In the second case, the adsorption concentration is doubled (12 methanol molecules, 11.4 wt%). The structural configurations obtained from power X-ray diffraction reveals that the hexagonal unit cell is nicely retained in both adsorption cases. Those configurations are used in our optimizations.

Subsequently, we perform optimizations for those two structures using the same calculation method. In both cases, methanol tends to establish van der Waals interaction with the six-membered 4-aminobenzoate moiety. Interestingly, this long-range interacting behavior is correlated with an impact on electronic structure that we will discuss later on. To analyze the favorability of settlement, the adsorption energy is subsequently calculated. For PBE calculations without D3 corrections, 6 methanol molecules are shown to expose attraction to the framework (−0.23 eV/molecule). PBE-D3 calculations reveal that 6 methanol molecules find nice dwelling in MOF-901 pores with an improved adsorption energy of −0.42 eV/molecule, as shown in Table 3.

The c lattice parameter is shortened, while a almost remains unchanged. Looking at the two-dimensional characteristics in Fig. 1b, it is reasonable that MeOH establishes long-range interaction with 4-aminobenzoate linkers along the z direction, and acts as a bridge to connect two parallel panels (layers). Hence, the c lattice parameter is shortened to 7.84 Å. The magnitude of binding energy given by PBE-D3 calculations unsurprisingly indicates weak van der Waals interactions. At this stage, we are curious to learn how this concentration of solvent would affect the electronic property of MOF-901. According to band structure and PDOS examination, Eg is now narrowed to 1.84 eV as predicted by PBE calculations as shown in Fig. 3a.

Recall that in pure MOF-901, both HOMO and LUMO are mainly constituted by the hybridized orbitals of 4-aminobenzoate. In the MOF-methanol interacting model, methanol establishes long-range interaction with the phenyl ring and distorts 4-aminobenzoate away from the original equilibrium position, thereby causes an incidental alternation on the electronic structure. Encountering structural distortion from the equilibrium position, the LUMO band is broadened around the region of 0.3–0.5 eV. Interestingly, there is also a split in the LUMO band as shown in the PDOS plot (Fig. 3b), indicating that there is an energetic degeneracy in the virtual eigenstates as a result of structural deformation of 4-aminobenzoate. Moreover, an in-gap state appears near the Fermi level, which is constituted by almost-equal contributions of guest methanol and 4-aminobenzoate. At this point, we can point out two factors causing Eg narrowing. First, guest molecules themselves contribute an intermediate eigenstate in the valence region. Second, the spatial occupancy of MeOH induces distortion to 4-aminobenzoate, and eventually broadens LUMO. It is also interesting to notice that the Fermi level is shifted to a higher energy level (1.5 eV) under the presence of methanol.

The most important goal in this study is to verify elevation of mechanical stability under the presence of methanol inside the MOF-901 network. This can be achieved by conducting elastic moduli calculations. The motivation for elasticity verification of MOF-solvent systems relies on the fact that a MOF product obtained from an experiment usually needs to undergo a stability test after product activation. Therefore, we suspect that the calculated elastic tensors Cij would indicate MOF-solvent to be more mechanically-stable than the pure MOF itself (activated sample). Upon analyzing elastic tensors resulted from lattice distortion, we observe that the Cij values for MOF-901 with 5.7 wt% methanol increase from 3% to 17% (see Tables 2 and 4). When ionic relaxation is included, we again observe that C33 is negative (−155 kBar), while C13 is largely reduced. This is an implication of 2D characteristics. More importantly, the elastic tensor moduli show that MOF-901 with 5.7 wt% methanol is more mechanically stable than pure MOF-901.

Under the presence of 12 methanol molecules, the c lattice parameter is even less shortened than in the case of 6-methanol adsorption as listed in Table 1. In this case, while PBE indicates attraction with an adsorption energy of −0.40 eV/molecule, PBE-D3 gives an adsorption energy of −0.52 eV/molecule. Examining the electronic structure of MOF-901 with 11.4 wt% methanol in Fig. 3b, Eg is observed to reduce to 1.63 eV. From the PDOS plot, we observe contribution of both methanol and 4-aminobenzoate to the formation of HOMO, while the lowest-unoccupied state is constructed by 4-aminobenzoate like the previous case. It should be noticed, however, the contribution of methanol to the in-gap state herein is much more dominant than that in the 6-methanol case. In terms of mechanical stability, we observe that the resultant elastic moduli for MOF-901 with 11.4 wt% methanol are further stabilized in comparison with the previous 5.7 wt% methanol case. More specifically, Cij values given by lattice distortion increase by 4–26%. In general, Cij given by lattice distortion are larger than those values obtained for pure MOF-901 and MOF-901 with 5.7 wt% methanol. As ionic response is taken into account, it should be noticed that C33 is -157 kBar, which again implies the 2D characteristics the framework. Equation (4) is satisfied, which implies that the MOF structure containing methanol still possesses hexagonal symmetry.

In the third case, we hypothetically push up the concentration of solvent to 13.5 wt% (14 methanol molecules). In this hypothesized structure, we assume that methanol can further find settlement in the small pore of MOF-901, which might not be observed in experiment spectrometers. Recall that in the previous adsorption cases, it is demonstrated in experiment that methanol only adsorbs in the large pore. In this case, 14 methanol molecules are placed in both large and small pores randomly. Due to complexity of methanol arrangement, we carry out a molecular dynamic simulation using the PBE functional with a fixed step size of 0.5 fs and fixed unit cell parameters at 300 K. This dynamic process enables us to search for local minimum configurations. We select three configurations of methanol arrangements (blue arrows in the time-energy diagram in Fig. 4) at three different time frames to get variant arrangement of the methanol molecules. The total time period for molecular dynamic simulation is 0.25 ps. Then, the chosen structures are optimized with variant unit cell, and the adsorption energy is calculated as -0.33 eV/molecule without D3 correction or -0.61 eV/molecule with D3 correction. In this case, both PBE and PBE-D3 calculations show that 14-MeOH-molecule encapsulation is even more attractive to the network of MOF-901, which means that MeOH also prefers to occupy small pores. The next goal is to validate mechanical stability of MOF-901 with 14 methanol molecules encapsulation.

The calculated elastic tensors are reported in Table 4. The Cij values given by unit-cell differentiating increases at least 14% in comparison with the value of pure MOF-901. More specifically, C33 (1244 kbar) increases tremendously by 35% in comparison with that of pure MOF-901 (921 kbar). Of course, these values survive the tests from inequalities (1)–(3). As we consider ionic relaxation contribution into total elastic tensors, C33 and C13 are more negative than those reported for the previous pure MOF-901 case.

At this point, our hypothesis has been resolved. The elastic tensor data clearly indicates that solvent (methanol) actually fills the vacuum porosity in MOF-901, thus enhance the mechanical stability of the structure. Elastic tensor data in Table 4 also implies the 2D characteristics of MOF-901. In terms of electronic structure, the appearance of guest molecule (MeOH) in MOF-901 pores causes geometry distortion to phenyl rings, thereby narrows the HOMO-LUMO gap.

Dehalogenation of ethyl α-bromophenylacetate at the electronically excited Ti site of [Ti6O6(O-CH3)6(4-aminobenzoate)6]

Experimentally15, the photocatalytic activity of MOF-901 was demonstrated in the polymerization of methyl methacrylate with ethyl α-bromophenylacetate as a co-initiator as shown in Fig. 5. With the motivation from the experiment, we theoretically demonstrate in this section that Br can be removed from ethyl α-bromophenylacetate (dehalogenation) under the influence of active Ti(III) sites. According to the electronic DOS (Fig. 2), the 3d electrons of Ti contribute partially to build up the HOMO-2 and LUMO+1 level, which corresponds to a hopping energy of 2.93 eV (423 nm). The oxidation state hopping energy was investigated in various theoretical and experimental works. For example, magnetic exchange-coupling constant was investigated for di- and trinuclear transition metal complexes by employing various ab initio levels of theory. For dicobalt complexes, the spin-orbit coupling effect had to be taken into account to obtain qualitative results23. Investigating the mechanism of SBU in a chromium-based MOF, Cantu et al24. suggested the highest barrier of ~35 kcal/mol for the formation of a dimetal linker and high-low spin hopping. The flip of Ti oxidation state from IV to III has been shown to occur under the influence of visible light in the literature. In a previous experiment, Dan-Hardi and co-workers25 synthesized a MOF structure involving titanium-oxo-hydroxo and dicarboxylate linkers (namely MIL-125). Interestingly, an optically-activated electronic hopping was observed by the evidence of electron paramagnetic resonance spectroscopy, and the oxidation state of Ti was reported to switch from IV to III26. Under the photo-activation of UV-A light, the Ti(IV) sites in COK-69 was reported to successfully convert to Ti(III)27. MIL-101, on the other hand, was constructed solely by Ti(III), and possessed a capability to capture O2 at the Ti site (then, the Ti oxidation state became IV after bonding with O2)28. For our case, it is of importance to verify the possibility of switching oxidation state of Ti to further study the mechanism of polymerization reaction under visible light irradiation catalyzed by MOF-901. An isolated model of Ti6O6(OCH3)6(4-aminobenzoate)6 is considered, which consists of 138 atoms and possesses C3v symmetry.

In the singlet ground state of Ti6O6(OCH3)6(4-aminobenzoate)6, when Ti switches the oxidation state from IV to III, the methoxy (•OCH3) radical group should be released as a consequence. Moreover, there is another lone-pair electron at the Ti site. Therefore, the overall multiplicity should be triplet. Indeed, achieving self-consistency in total energy calculation for this triplet state is hardly done; therefore, for such a highly complex molecular system, we perform two doublet calculations instead: one for •OCH3 and another for the remaining cluster. The sum of total energies of two doublet configurations is 4.19 eV higher than the singlet energy of Ti6O6(O-CH3)6(4-aminobenzoate)6 according to PBE/6–31 G calculations or 3.97 eV lower according to PBE/gen calculations. These predicted energy differences correspond to UV-A wavelengths of 296 nm or 312 nm, respectively. To get a more realistic picture of the singlet-triplet hopping energy, we consider a simplified cluster, in which the 4-aminobenzoate moiety is omitted and replaced by a dummy H atom, while all -OCH3 groups still remain in the complex (66 atoms in total). It is still very challenging to achieve self-consistency for triplet-state calculations, and we have to employ a quadratically-convergent method for solving Hartree-Fock SCF29. For this model, upon using PBE/6–31 G, the singlet-triplet hopping energy is 2.82 eV (440 nm, in the visible region), while PBE/gen suggests a hopping energy of 2.80 eV (443 nm). Those two hopping energies indicate good correspondence with the earlier plane-wave calculations and more importantly, possess good agreement with the actual condition for polymerization, where the reaction was catalyzed under visible light15. At this stage, we look forward to validating the removal of Br from ethyl α-bromophenylacetate at the Ti active site (without •OCH3) of the simplified model. In the reaction, Br approaches Ti(III) from a far distance. Ti(III) then captures Br to establish a Ti-Br ionic bond; then, the C-Br bond is broken as a consequence. To achieve a transition state for this proposed mechanism, we first optimize an initial state, where ethyl α-bromophenylacetate is set to interact with the core cluster from a far distance (to be specific, more than 6 Å), and a final state, where Br is successfully captured by Ti and radical ethyl phenylacetate is left behind. While the final state can be successfully optimized, it is interesting to observe from both PBE/6–31 G and PBE/gen calculations that an initial state cannot be found in both sets of calculations; in fact, the initial structure is dragged to converge toward the final state. Hence, dehalogenation under the activation of Ti(III) is a barrierless and thermodynamically spontaneous process because Ti(III) is very active. Thereafter, radical ethyl phenylacetate is produced. We then carry out the key step of polymerization using the gas-phase calculation by allowing the radical C site in ethyl phenylacetate to approach the double bond in methyl methacrylate, as shown in Fig. 6b. In this optimization, the C(radical)-C(double bond) distance is narrowed by a step size of 0.1 Å, while other coordinates are relaxed. As the transition state is located, the radical C atom from ethyl phenylacetate approaches the sp2 C atom in methyl methacrylate with a distance of 2.18 Å, and the potential barrier is 0.30 eV. The Gibbs free energy of this polymerization is 0.37 eV, thus the reaction rate constant at room temperature can be estimated as 3.43·106 s−1 using the Eyring equation30. We believe such a reaction barrier is low enough to be activated in ambient condition. Nevertheless, such reaction free energy and rate constant are estimated in the gas phase. Within the context of this report, we do not carry out a demonstration of polymerization in the condensed phase within the pores of MOF-901; still, we believe that the reaction rate would be slower.

Conclusion

In this study, we carry out a theoretical investigation of MOF-901 to clarify the difference in mechanical stability of solvent-free and solvent-interacting systems. Structural optimizations predict the a lattice parameter to be in good accordance with the experiment, while the c lattice is compressed due to the tilting behavior of −OCH3. The adsorption of methanol is proved to stabilize the framework of MOF-901. The analysis of elastic tensors Cij for solvent-free MOF-901 and MOF-901 with solvent indicates that both systems are mechanically stable and possess 2D characteristics. Moreover, it also unveils the role of solvent in stabilizing the porous material. Upon introducing methanol into MOF-901, all elastic moduli Cij derived from a stress-strain relationship increase. This is an indication that the framework has attained better structural stability. We then examine the band structure of MOF-901 given by PBE calculations, and observe a direct HOMO-LUMO gap of 2.07 eV at the Γ point. From the PDOS analysis, both HOMO and LUMO are mainly constituted by the hybdrized orbitals of 4-aminobenzoate groups, while the contributions from Ti, O(carboxylate), and methoxy are insignificant. The 5.7 wt% encapsulation of methanol within MOF-901 pores (6 methanol molecules) narrows the energy gap to 1.84 eV (decreased by ~12%). By further increasing methanol concentration to 11.4 wt% (12 methanol molecules), the HOMO-LUMO gap suffers more narrowing (1.63 eV) as a result of distorting the equilibrium geometry of 4-aminobenzoate linkers. It should be noted that those two methanol-incorporating structures are obtained from a previous experimental data. Guest methanol itself contributes an in-gap state, which is also responsible for Eg narrowing. This finding opens up a new direction to MOF energy gap tailoring by control solvent concentration.

Finally, the role of Ti(III) in dehalogenation of ethyl α-bromophenylacetate is verified. Our localized atomic-orbital-basis calculations suggest that a Ti(IV) site can undergo electronic hopping to become Ti(III) under the effect of visible light (~440–443 nm). Subsequently, Ti(III) is capable of grabbing Br from a far distance and break the C-Br bond in a spontaneous process without a reaction barrier. Finally, the polymerization of methyl methacrylate can be activated by radical ethyl phenylacetate with a low reaction barrier of 0.30 eV.

Methods

Condensed-phase calculations

Plane-wave DFT calculations are performed for the investigation of MOF-901. With a hexagonal structure, MOF-901 consists of 336 atoms within one primary unit cell (12 Ti, 12 N, 144 C, 120 H, and 48 O atoms) as shown in Fig. 1. The total charge of the system of interest vanishes because all atoms are chemically guaranteed. Electronic structure calculations for periodic MOF-901 are executed using the well-established Vienna Ab Initio Simulation Package (VASP)31,32,33,34. To be specific, DFT calculations are performed by employing the Perdew-Burke-Ernzerhof35,36 (PBE) parameterization for exchange-correlation description within generalized-gradient approximations (GGA). The electronic wave-function is constituted using the well-developed projector-augmented wave (PAW) method implemented within VASP37,38. The cut-off energy for plane-wave expansions is tested at various values from 300 eV to 425 eV, and we observe that total energy is lowest at 400 eV. Therefore, we choose the cut-off energy of 400 eV, which is most suitable and affords computational feasibility for such a large periodic system. The convergence threshold in total energy self-consistency is 10−5 eV. Each optimization process has two steps because of very large and porous structure. In the first step, the unit cell is fixed to retain structural symmetry and ionic position is optimized until total energy difference between self-consistent-field (SCF) loops falls within an allowable limit of 10−3 eV. Subsequently, the unit cell and ionic positions are relaxed simultaneously. In the second step, a convergence criterion of 10−3 eVÅ−1 is applied to gradient convergence. For illustration of structures, crystallographic pictures are made with the Visualization for Electronic and Structural Analysis software39.

We also study methanol encapsulation inside MOF-901 in a later section. To survey the geometric arrangement of multiple methanol molecules, we first introduce 14 CH3OH molecules into MOF-901 randomly; then, a molecular dynamic trajectory is employed to shuffle CH3OH. The constant temperature of 300 K is acquired by utilizing the Andersen thermostat technique40,41, and the total time of this simulation is 0.25 ps (500 molecular dynamic steps).

Localized atomic-orbital-basis calculations

The localized atomic-orbital-basis calculations are executed using unrestricted PBE calculations implemented in the Gaussian 16 suite of program42. Two independent calculation sets are performed for validation purposes. In the first set, we employ the simple split-valence Pople basis set of 6-31 G43,44. In the second calculation set, an effective core potential45 with the LANL2dz basis set46,47,48 (for convenience, we denote the combination of basis sets and effective core potential as gen) is employed. The long-range van der Waals interaction is accounted in those optimizations by activating the empirical Grimme D3 correction terms49.

References

1. 1.

Moghadam, P. Z.; et al Development of a Cambridge Structural Database Subset: A Collection of Metal–Organic Frameworks for Past, Present, and Future. Chem. Mater 29, 2618-2625 (2017).

2. 2.

Nguyen, B. T., Nguyen, H. L., Nguyen, T. C., Cordova, K. E. & Furukawa, H. High Methanol Uptake Capacity in Two New Series of Metal–Organic Frameworks: Promising Materials for Adsorption-Driven Heat Pump Applications. Chem. Mater 28, 6243–6249 (2016).

3. 3.

Trickett, C. A. et al. The Chemistry of Metal–Organic Frameworks for CO2 Capture. Regeneration and Conversion 2, 17045 (2017).

4. 4.

Furukawa, H., Cordova, K. E., O’Keeffe, M. & Yaghi, O. M. The Chemistry and Applications of Metal-Organic Frameworks. Science 341, 1230444 (2013).

5. 5.

Zhang, L. et al. Adv. Sci. 3, 1500243 (2016).

6. 6.

Tran, T. V. et al. A Five Coordination Cu(ii) Cluster-Based MOF and Its Application in the Synthesis of Pharmaceuticals via sp3 C-H/N-H Oxidative Coupling. Catal. Sci. Technol 7, 3453–3458 (2017).

7. 7.

Kitagawa, S. & Kitaura, R. Noro, S.-i. Functional Porous Coordination Polymers. Angew. Chem. Int. Ed. 43, 2334–2375 (2004).

8. 8.

Nasalevich, M. A. et al. Co@NH2-MIL-125(Ti): Cobaloxime-Derived Metal-Organic Framework-Based Composite for Light-Driven H2 Production. Energ. Environ. Sci. 8, 364–375 (2015).

9. 9.

Nguyen, H. L. The Chemistry of Titanium-Based Metal-Organic Frameworks. New J. Chem. 41, 14030–14043 (2017).

10. 10.

Hendon, C. H. et al. Engineering the Optical Response of the Titanium-MIL-125 Metal–Organic Framework through Ligand Functionalization. J. Am. Chem. Soc. 135, 10942–10945 (2013).

11. 11.

Pham, H. Q. et al. Engineering of Band Gap in Metal–Organic Frameworks by Functionalizing Organic Linker: A Systematic Density Functional Theory Investigation. J. Phys. Chem. C 118, 4567–4577 (2014).

12. 12.

Hohenberg, P. & Kohn, W. Inhomogeneous Electron Gas. Phys. Rev. 136, B864–B871 (1964).

13. 13.

Kohn, W. & Sham, L. J. Self-Consistent Equations Including Exchange and Correlation Effects. Phys. Rev. 140, A1133–A1138 (1965).

14. 14.

Becke, A. D. Perspective: Fifty Years of Density-Functional Theory in Chemical Physics. J. Chem. Phys. 140, 18A301 (2014).

15. 15.

Nguyen, H. L. et al. A Titanium–Organic Framework as an Exemplar of Combining the Chemistry of Metal– and Covalent–Organic Frameworks. J. Am. Chem. Soc. 138, 4330–4333 (2016).

16. 16.

Nguyen, H. L. et al. A Titanium–Organic Framework: Engineering of the Band-Gap Energy for Photocatalytic Property Enhancement. ACS Catal. 7, 338–342 (2017).

17. 17.

Hong, K. & Chun, H. Nonporous Titanium–Oxo Molecular Clusters That Reversibly and Selectively Adsorb Carbon Dioxide. Inorg. Chem. 52, 9705–9707 (2013).

18. 18.

Chan, M. K. Y. & Ceder, G. Efficient Band Gap Prediction for Solids. Phys. Rev. Lett. 105, 196403 (2010).

19. 19.

Zhang, R. F. et al. Crystal Field Splitting is Limiting the Stability and Strength of Ultra-incompressible Orthorhombic Transition Metal Tetraborides. Sci. Rep. 6, 23088 (2016).

20. 20.

Mouhat, F. & Coudert, F.-X. Necessary and Sufficient Elastic Stability Conditions in Various Crystal Systems. Phys. Rev. B 90, 224104 (2014).

21. 21.

Hill, R. The Elastic Behaviour of a Crystalline Aggregate. Proceed. Phys. Soc. A 65, 349 (1952).

22. 22.

Le Page, Y. & Saxe, P. Symmetry-general least-squares extraction of elastic data for strained materials from ab initio calculations of stress. Phys. Rev. B 65, 104104 (2002).

23. 23.

Vogiatzis, K. D., Klopper, P. W., Mavrandonakis, D. A. & Karin Fink, D. Magnetic Properties of Paddlewheels and Trinuclear Clusters with Exposed Metal Sites. ChemPhysChem 12(17), 3307–19 (2011).

24. 24.

Cantu, D. C., McGrail, B. P. & Glezakou, V.-A. Formation Mechanism of the Secondary Building Unit in a Chromium Terephthalate Metal–Organic Framework. Chem. Mater 26(22), 6401–6409 (2014).

25. 25.

Dan-Hardi, M. et al. A New Photoactive Crystalline Highly Porous Titanium(IV) Dicarboxylate. J. Am. Chem. Soc. 131, 10857–10859 (2009).

26. 26.

Bueken, B. et al. A Flexible Photoactive Titanium Metal–Organic Framework Based on a [TiIV3(μ3-O)(O)2(COO)6] Cluster. Angew. Chem. Int. Ed. 54, 13912–13917 (2015).

27. 27.

Mason, J. A., Darago, L. E., Lukens, W. W. & Long, J. R. Synthesis and O2 Reactivity of a Titanium(III) Metal–Organic Framework. Inorg. Chem 54, 10096–10104 (2015).

28. 28.

Frisch, M. J., et al Gaussian 16, Wallingford, CT, (2016).

29. 29.

Bacskay, G. B. A Quadratically Convergent Hartree-Fock (QC-SCF) Method. Application to Closed Shell Systems. Chem. Phys. 61, 385–404 (1981).

30. 30.

Eyring, H. The Activated Complex in Chemical Reactions. The Journal of Chemical Physics 3, 107 (1935).

31. 31.

Kresse, G. & Hafner, J. Ab Initio Molecular Dynamics for Liquid Metals. Phys. Rev. B 47, 558–561 (1993).

32. 32.

Kresse, G. & Hafner, J. Ab Initio Molecular-Dynamics Simulation of the Liquid-Metal-Amorphous-Semiconductor Transition in Germanium. Phys. Rev. B 49, 14251–14269 (1994).

33. 33.

Kresse, G. & Furthmüller, J. Efficiency of Ab-Initio Total Energy Calculations for Metals and Semiconductors Using a Plane-Wave Basis Set. Comput. Mater. Sci. 6, 15–50 (1996).

34. 34.

Kresse, G. & Furthmüller, J. Efficient Iterative Schemes for Ab Initio Total-Energy Calculations Using a Plane-Wave Basis Set. Phys. Rev. B 54, 11169–11186 (1996).

35. 35.

Perdew, J. P., Burke, K. & Ernzerhof, M. Generalized Gradient Approximation Made Simple. Phys. Rev. Lett. 77, 3865–3868 (1996).

36. 36.

Perdew, J. P.; Burke, K.; Ernzerhof, M. Generalized Gradient Approximation Made Simple [Phys. Rev. Lett 77, 3865 (1996)]. Phys. Rev. Lett. 78, 1396–1396 (1997).

37. 37.

Blöchl, P. E. Projector Augmented-Wave Method. Phys. Rev. B 50, 17953–17979 (1994).

38. 38.

Kresse, G. & Joubert, D. From Ultrasoft Pseudopotentials to the Projector Augmented-Wave Method. Phys. Rev. B 59, 1758–1775 (1999).

39. 39.

Momma, K. & Izumi, F. VESTA 3 for Three-Dimensional Visualization of Crystal, Volumetric and Morphology Data. J. Appl. Cryst. 44, 1272–1276 (2011).

40. 40.

Andersen, H. C. Molecular Dynamics Simulations at Constant Pressure and/or Temperature. J. Chem. Phys. 72, 2384–2393 (1980).

41. 41.

Tanaka, H., Nakanishi, K. & Watanabe, N. Constant Temperature Molecular Dynamics Calculation on Lennard-Jones Fluid and Its Application to Water. J. Chem. Phys. 78, 2626–2634 (1983).

42. 42.

Ditchfield, R., Hehre, W. J., Pople, J. A. & Self-Consistent Molecular-Orbital Methods., I. X. An Extended Gaussian-Type Basis for Molecular-Orbital Studies of Organic Molecules. J. Chem. Phys. 54, 724–728 (1971).

43. 43.

Hehre, W. J., Ditchfield, R. & Pople, J. A. Self-Consistent Molecular Orbital Methods. XII. Further Extensions of Gaussian-Type Basis Sets for Use in Molecular Orbital Studies of Organic Molecules. J. Chem. Phys. 56, 2257–2261 (1972).

44. 44.

Francl, M. M. et al. Self-Consistent Molecular Orbital Methods. XXIII. A Polarization-Type Basis Set for Second-Row Elements. J. Chem. Phys. 77, 3654–3665 (1982).

45. 45.

Xu, X. & Truhlar, D. G. Accuracy of Effective Core Potentials and Basis Sets for Density Functional Calculations, Including Relativistic Effects, As Illustrated by Calculations on Arsenic Compounds. J. Chem. Theory Comput. 7, 2766–2779 (2011).

46. 46.

Hay, P. J. & Wadt, W. R. Ab Initio Effective Core Potentials for Molecular Calculations. Potentials for the Transition Metal Atoms Sc to Hg. J. Chem. Phys. 82, 270–283 (1985).

47. 47.

Hay, P. J. & Wadt, W. R. Ab Initio Effective Core Potentials for Molecular Calculations. Potentials for K to Au Including the Outermost Core Orbitals. J. Chem. Phys. 82, 299–310 (1985).

48. 48.

Wadt, W. R. & Hay, P. J. Ab Initio Effective Core Potentials for Molecular Calculations. Potentials for Main Group Elements Na to Bi. J. Chem. Phys. 82, 284–298 (1985).

49. 49.

Grimme, S., Antony, J., Ehrlich, S. & Krieg, H. A Consistent and Accurate Ab Initio Parametrization of Density Functional Dispersion Correction (DFT-D) for the 94 Elements H-Pu. J. Chem. Phys. 132, 154104 (2010).

Acknowledgements

We are grateful for computational support from the High-Performance Computing Laboratory, Faculty of Computer Science & Engineering, University of Technology, Vietnam National University and the Institute for Material Research, Tohoku University. D.N.-M. acknowledges the support from the High-Performance Computer Center at the CINECA Headquarters in Bologna (Italy) for its provision of supercomputer resources on the Marconi machine. Finally, we acknowledge a financial support from Vietnam National University under grant TX-2018-50-01.

Author information

H.C.D. performed condensed-matter calculations and made Figs 2 and 3. H.L.N. retrieved the experimental data, wrote part of the paper, and made Figs 1 and 4–6. H.M.L performed localized atomic-orbital-basis calculations and wrote most part of the paper. T.N. and Y.K. contributed technical support for all calculations. D.N.-M. discussed technical details and contributed to finalize the manuscript.

Correspondence to Hung M. Le.

Ethics declarations

Competing Interests

The authors declare no competing interests.

Publisher’s note: Springer Nature remains neutral with regard to jurisdictional claims in published maps and institutional affiliations.


text:
# Implementing a function so it accepts functions, function names and expressions as an argument

I'm trying to write a Mathematica function which takes an arbitrary expression as input. More concretely, I'm trying to write an integration function (utilizing the trapezoidal method), the input of which behaves like NIntegrate. For example:

fTest[x_, y_] :=  x + y;

fNew[y_] := NIntegrate[x^2*fTest[x, y], {x, 0, 10}];

Currently, I have something like:

NInt1D[f_] :=
Module[{Num, eps, sum, a, X},
Num = 10;
eps = 10/Num;
sum = 0;
For[a = -Num, a <= +Num, a++,
X = a*eps;
sum += f[X]*eps;];
Return[sum]];

Which is problematic for me, since the above NInt1d only takes functions as input, and not expressions, preventing me from defining my function in terms of the integral, as can be done with NIntegrate.

I hope this toy example makes clear my intentions. I found another post which ask this question in the context of creating a Plot function [1]. Unfortunately, the explanation was too specific, and I found it hard to understand -- I'm somewhat new to Mathematica.

• If to fix $x$ as the integration variable, would something like this do: NInt1D[f_] := Module[{Num,eps,sum, a,g, X}, g[x_]=f; Num = 10; eps = 10/Num; sum = 0; For[a = -Num, a <= +Num, a++, X = a*eps; sum += g[X]*eps; ] Return[sum]]; ? – Andrew Dec 29 '18 at 20:27
• You might be interested in this answer, which gives a more detailed explanation of the strategies behind implementing such a function. One important thing is that it's usually better to pass in the independent variable along with the expression, such that you're not forced to always use X for example – Lukas Lang Dec 29 '18 at 23:42

## 1 Answer

I studied your code for a while and it seems to me that it does not implement the trapezoid method for evaluating an integral. So even if I showed you how to make it accept both functions and expression as arguments, it would still fail to produce correct results. So, instead, I will use

f[x_] := x^2
NIntegrate[f[x], {x, -12, 12}]

1152.

for testing. Although this is simpler than the example you gave in your question, it should still serve to demonstrate a trapezoid method that meets your requirements.

I will not use For which produces ugly and inefficient code. Rather, I will use MovingAverage and Total, which provide a reasonable functoinal solution to the problem. Further, I will give two implementations, the 1st rather prolix but easy to understand; the 2nd much more concise, but it might take some study to see that it does exactly the same thing as the 1st implementation.

### Method 1

Clear[nInt]
nInt[f_Symbol | f_Function] :=
Module[{x0 = 12, nSteps, mesh, pts, eps},
nSteps = 1000; (* should be even *)
mesh = Subdivide[-x0, x0, nSteps];
pts = f /@ mesh;
eps = mesh[[nSteps/2 + 2]];
eps Total[MovingAverage[pts, 2]] // N]
nInt[expr_, var_Symbol] :=
Module[{x0 = 12, nSteps, mesh, pts, eps},
nSteps = 1000; (* should be even *)
mesh = Subdivide[-x0, x0, nSteps];
pts = (expr /. var :> # &) /@ mesh;
eps = mesh[[nSteps/2 + 2]];
eps Total[MovingAverage[pts, 2]] // N]

What is ugly about the above code is that it violates the rule of "don't repeat code unnecessarily". Its main virtue is that it is easy to follow.

### Method 2

Clear[nInt]
nInt[args__] :=
Module[{x0 = 12, nSteps = 1000, argv, mesh, pts},
argv = {args};
mesh = Subdivide[-x0, x0, nSteps];
pts =
Switch[argv[[1]],
_Symbol | _Function, argv[[1]] /@ mesh,
_, (argv[[1]] /. argv[[2]] :> # &) /@ mesh];
mesh[[nSteps/2 + 2]] Total[MovingAverage[pts, 2] // N]]

### Tests

nInt[f]
nInt[#^2 &]
x =.; nInt[x^2, x]
x = 42; Block[{x}, nInt[x^2, x]]

When evaluated, all of the above expressions give 1152., the same value as Integrate gave.

• Thank you m_goldberg. Your response is very educational -- I learned a bit more than I asked for, which I appreciate. – Paul Eugenio Jan 1 at 21:28