text:
\section{Introduction}

Particle exchange statistics are normally described by the symmetric group $S_N$ of particle permutations and indistinguishable particles are classified as bosons or fermions. However, there are more exotic possibilities for particle exchange statistics in low-dimensional particle models with hard-core interactions. The most famous examples are: 1) hard-core two-body interactions in one dimension, which leads to the `fermionization' of hard-core bosons~\cite{girardeau_relationship_1960}; and 2) hard-core two-body interactions in two dimensions, which allows for particles that are neither fermions nor bosons called anyons~\cite{wilczek_quantum_1982}.

Both of these manifestations of generalized exchange statistics can be understood topologically~\cite{leinaas_theory_1977}. The removal of two-body coincidences like ${\bf x}_i = {\bf x}_j$ from configuration space reduces its connectivity, and so does identifying points in configuration space that represent indistinguishable configurations.  In one dimension, the defects introduced by hard-core two-body interactions prevent particles from passing through each other. This divides configuration space into sectors with fixed order that are disconnected from each other. The relative phases among different sectors are unobservable, and therefore the exchange symmetry of indistinguishable particles is equivalent to a gauge symmetry~\cite{polychronakos_non-relativistic_1989}. In two dimensions, the defects caused by hard-core two-body interactions leave the configuration space connected but not simply-connected~\cite{wu_general_1984}. Exchanges of indistinguishable particles acquire different topological phases (or more general path-dependent transformations) depending on how they wind around these defects, leading to anyons with generalized exchange statistics governed by the fundamental group of configuration space, called the braid group $B_N$~\cite{wilczek_fractional_1990}.

Besides these two famous examples, there is only one other case where local hard-core interactions lead to a not simply-connected configuration space: hard-core three-body interactions in one dimension~\cite{harshman_coincidence_2018}. Consider the $N$-body Hamiltonian in one-dimensional free space with the form
\begin{equation}\label{eq:sampHam}
H =  \sum_{i=1}^N \left( -\frac{\hbar^2}{2m} \frac{\partial^2}{\partial x_i^2} + V(x_i) \right) + g \sum_{\langle ijk \rangle}^N W(\rho_{ijk}^2),
\end{equation}
where $V(x)$ is a finite one-body trapping potential, the second sum is over all triplets of particles $\langle ijk \rangle$, the  quadratic form $\rho_{ijk}^2=x^2_i +x^2_j + x^2_k-x_i x_j -x_j x_k -x_k x_i$ is the square of the three-body hyperradius for the triplet $\langle ijk \rangle$, and $W(\rho^2)$ is some repulsive three body potential with finite range. Since the range of the interaction will not affect topological properties, a mathematically convenient choice for $W(\rho_{ijk}^2)$ has support at  $\rho_{ijk}=0$ and nowhere else
\begin{equation}
W(\rho_{ijk}^2) = \delta(x_i-x_j)\delta(x_j-x_k).
\end{equation}
In the limit $g\to \infty$ in (\ref{eq:sampHam}), the three-body potential becomes hard-core and therefore the two-dimensional coincidence manifolds defined by $x_i = x_j = x_k$ are excluded from the $N$-dimensional  configuration space.

There are several proposals to create tunable effective three-body interactions in the control of ultracold atoms in optical traps~\cite{cooper_exact_2004, paredes_pfaffian-like_2007, daley_atomic_2009, keilmann_statistically_2011,mahmud_dynamically_2014,paul_large_2015,paul_hubbard_2016,strater_floquet_2016}. These proposals are driving sustained theoretical interest in the dynamical and thermodynamical properties of such models~\cite{silva-valencia_first_2011,paredes_non-abelian_2012,sowinski_exact_2012,safavi-naini_first-order_2012,wright_nonequilibrium_2014,hincapie-F_mott_2016,lange_strongly_2017,andersen_hybrid_2017,sekino_quantum_2018,drut_quantum_2018,nishida_universal_2018,arcila-forero_three-body-interaction_2018,pricoupenko_pure_2018,guijarro_one-dimensional_2018,pastukhov_ground-state_2019,pricoupenko_three-body_2019}. Two-body interactions could also be added to (\ref{eq:sampHam}) without affecting the connectivity, as long as they are not also hard-core.

Hard-core three-body interactions in one dimension disrupt the connectivity of configuration space in a similar way to two-body coincidences in two-dimensions. In both cases the excluded coincidences create co-dimension $\tilde{d}= 2$ defects (see Tab.~\ref{tab:codimension}) around which paths realizing particle exchanges can wind and tangle. Because the configuration space is not simply connected, particle models with co-dimension $\tilde{d}= 2$ defects also possess anyonic solutions. Unlike fermionic and bosonic solutions, but similar to braid group anyons, these multi-valued solutions possess generalized exchange statistics realized by topological (or Berry) phases that depend on the path taken by the particle exchange.
However, instead of obeying the familiar braid group exchange statistics, the anyonic solutions  of Hamiltonians like (\ref{eq:sampHam}) obey generalized winding rules described by a group we call the \emph{traid group}. Like the braid group, the traid group is an extension of the symmetric group and its elements can be represented as strand diagrams; see Fig.~\ref{fig:braidtraidcontrast}.

\begin{table}%
\centering
\begin{tabular}{c|ccc}
\hline
 & $k=2$ & $k=3$ & $k=4$  \\
\hline
$d=1$ & $1$ & $2$ & $3$\\
$d=2$ & $2$ & $4$ & $6$\\
$d=3$ & $3$ & $6$ & $9$\\
\hline
\end{tabular}
\caption{The entries of this table are the co-dimension $\tilde{d}$ of the defect created when $k$-body coincidences are removed from the configuration space of $N$ particles in $d$ dimensions. The formula for the co-dimension $\tilde{d}= d(k-1)$ counts the number of equations necessary to establish a $k$-body coincidence in $d$ dimensions and is therefore independent of $N$. When $\tilde{d}=1$, the defect is like a line in a plane or a plane in a space and it divides configuration space into dynamically isolated sectors. When $\tilde{d}=2$, the defect is like a point in a plane or a line in a space. Configuration space remains connected, but not simply-connected and topological phases are possible. When $\tilde{d}>2$, configuration space remains simply connected and generalized exchange statistics are not possible.}
\label{tab:codimension}
\end{table}

\begin{figure}
\centering
\adjustbox{trim={.10\width} {.15\height} {0.10\width} {.12\height},clip}{\includegraphics[width= 1.2\columnwidth]{figBBB.pdf}}
\caption{This figure compares the braid group $B_N$ and traid group $T_N$ using strand diagrams. Both groups can be expressed in terms $N-1$ generators, $b_i$ and $t_i$ respectively, that exchange the $i$th and the $(i\!+\!1)$th strands. For the braid group, $b_i$ and $b_i^{-1}$ are different, i.e.\ strands must go over or under each other, whereas for the traid group (like the symmetric group) two-particle exchanges $t_i^2=1$ are square-trivial and there is no distinction between over and under. Another contrast, for the traid group any rearrangement of strands that requires moving through a triple point is not allowed, whereas for the braid group shift one can pass through a triple point to show that the arrangements $b_i b_{i+1} b_i$ and $b_{i+1} b_i b_{i+1}$ of three adjacent strands are equivalent.}\label{fig:braidtraidcontrast}
\end{figure}

Although the original physical motivation for this study is engineered three-body interactions in ultracold atoms, real indistinguishable atoms are either bosons or fermions. For the anyonic solutions to be experimentally relevant, the one-dimensional particles of the model Hamiltonian (\ref{eq:sampHam}) would themselves need to be quasiparticles with an internal structure, perhaps at a faster time scale, which provides the effective path-dependent exchange phase of traid anyons. Although it seems unlikely that there are `natural' systems with low-energy dynamics given by a one-dimensional quasiparticle model with effective hard-core three-body interactions, the surprising applicability of braid anyons to the fractional quantum Hall effect provides inspiration for the exploration of this novel form of generalized exchange statistics. Even without physical instantiations of traid anyons, their mathematical structure possesses that delightful combination of simple to express but rich in expression that begs further investigation, if only as a clarifying contrast to the more famous exchange statistics given by the symmetric group and the braid group.

The article has the following structure:  In Sect.~\ref{sect:background}, we introduce notation and terminology for describing the homotopy of configuration space by briefly presenting the braid group and braid group anyons. Using these results, we introduce the traid group and and draw contrasts between traid anyons and previous results for braid anyons in one and two dimensions. Next, in Sect.~\ref{sect:config} we describe the geometrical and topological properties of configuration spaces for $N$ distinguishable and indistinguishable particles in $d$ dimensions with hard-core $k$-body interactions and analyze its topology in the case of hard-core three-body interactions in one dimension. One technical challenge, and an important difference with the braid group, is that the configuration space whose properties determine the generalized traid group exchange statistics is not a manifold. Instead it is an orbifold, and in Sect.~\ref{sect:fund} (and the Appendix) we explain this difference and the generalization of fundamental groups that applies to orbifolds. In Sect.~\ref{sect:pres} we give the abstract presentations of the traid group and pure traid group and compare them to the symmetric and braid groups. Some representations of the traid groups corresponding to anyonic solutions and an application to three harmonically-traped abelian traid anyons are given in Sect.~\ref{sect:repres}. Summary and outlook are provided in Sect.~\ref{sect:summ}.

\section{Background and Connections}\label{sect:background}

Generalized exchange statistics can occur when the configuration space of a particle model is not simply connected~\cite{leinaas_theory_1977,sudarshan_configuration_1988,polychronakos_non-relativistic_1989,einarsson_fractional_1990}. In generalized exchange statistics, the transformation of the $N$-body wave function depends not just on which particles were exchanged, but also on \emph{how} they were exchanged. Particle exchanges are considered as paths through configuration space, and when the configuration space is not simply connected, there are inequivalent paths representing the same particle exchange. The fundamental group of the configuration space describes the equivalence classes of exchange paths and the representations of the fundamental group determine whether generalized exchange statistics are possible.

In the most famous example of generalized exchange statistics, the group describing particle exchanges is the braid group $B_N$~\cite{artin_theorie_1925,arnold_cohomology_1969,birman_braids:_2005,kassel_braid_2008}. The braid group $B_N$ is an infinite, discrete group that generalizes the symmetric group $S_N$. Generalized exchange statistics obeying the braid group occur when two-body coincidences are excluded from the configuration space of $N$ indistinguishable particles in two-dimensional Euclidean space~\cite{wu_general_1984}. One reason to remove these points from configuration space is because hard-core two-body interactions exclude those coincidences. Alternatively, whenever particles have relative angular momentum in two dimensions, the $1/r^2$ singularity of the centrifugal barrier also prevents two-body coincidences. Either way, the removed points form what we call the two-body \emph{coincidence structure} $\mathcal{V}_{N,2,2}$. This structure is the union of $N(N-1)/2$ two-body coincidence manifolds $\mathcal{V}_{ij}$, one manifold for each pair of particles. Each manifold $\mathcal{V}_{ij}$ is a hyperplane with co-dimension $\tilde{d}=2$, i.e.\ there are two dimensions perpendicular to it, like a point in $\mathbb{R}^2$ or a line in $\mathbb{R}^3$. Because the two-body coincidence manifolds $\mathcal{V}_{ij}$ are co-dimension $\tilde{d}=2$ defects, they disrupt the simple connectivity of configuration space, allowing the wave function to get `wound up' when particles exchange.

After the two-body coincidence structure $\mathcal{V}_{N,2,2}$ is removed, the remaining configuration space for $N$ indistinguishable particles is $\mathcal{X}_{N,2,2}/{\mathrm{S}_N}$, where $\mathcal{X}_{N,2,2}=\mathbb{R}^{2N} - \mathcal{V}_{N,2,2}$ is the configuration space of $N$ distinguishable particles. In the quotient space $\mathcal{X}_{N,2,2}/\mathrm{S}_N$, all points in $\mathcal{X}_{N,2,2}$ that differ only by a permutation of particle coordinates are identified as the same point.
The fundamental group $\pi_1(\mathcal{X}_{N,2,2}/S_N)$ is the braid group $B_N$ and describes the generalized exchange statistics of indistinguishable particles, and the fundamental group  $\pi_1(\mathcal{X}_{N,2,2})$ is a subgroup called the pure braid group $PB_N$ and describes the generalized exchange statistics of distinguishable particles. The one-dimensional representations of the braid group have fractional exchange statistics governed  by a phase that varies from $\theta=0$ for bosons to $\theta=\pi$ for fermions. Quasiparticles obeying abelian braid statistics are central to the understanding of the fractional quantum Hall effect~~\cite{halperin_statistics_1984,arovas_fractional_1984, jain_theory_1990, wilczek_fractional_1990, canright_fractional_1990, viefers_ideal_1995, khare_fractional_1997}. Non-abelian anyons carry multi-dimensional representations of the braid group~\cite{moore_nonabelions_1991,wen_non-abelian_1991,greiter_paired_1992} and provide a model for quantum computing with topological error protection~\cite{kitaev_fault-tolerant_2003,nayak_non-abelian_2008}.

Besides two-body hard-core interactions in two dimensions, the only other case where local hard-core few-body interactions make configuration space not simply-connected and lead to anyonic physics is the much less studied case of three-body hard-core interactions in one dimension\footnote{There is also a non-local four-body interaction in one-dimension that creates co-dimension $\tilde{d}=2$ defects. This non-local hard-core interaction excludes formation of more than one pair so that the coincidence manifolds defined by two two-body coincidences like $x_i = x_j$ and $x_k = x_l$ are excluded from configuration space. Although not discussed in this article, this also leads to novel generalized exchange statistics distinct from those given by the braid or traid group. We refer to this group as the `fraid' group; Khovanov has named this the triplet group~\cite{khovanov_real_1996}.}. The simultaneous coincidence of three particles in one-dimension $x_i=x_j=x_k$ defines a linear subspace with co-dimension $\tilde{d}=2$, and the union of these is the three-body coincidence structure $\mathcal{V}_{N,1,3}$. When these forbidden coincidences are removed from the configuration space for $N$ particles in one-dimension, the remaining space $\mathcal{X}_{N,1,3} = \mathbb{R}^N - \mathcal{V}_{N,1,3}$ is not simply connected, nor (in a generalized sense described below) is the quotient  $\mathcal{X}_{N,1,3}/S_N$. Identifying the topological properties of $\mathcal{X}_{N,1,3}$ and $\mathcal{X}_{N,1,3}/S_N$ is the main technical result of this article.

In analogy with the pure braid group, we define the \emph{pure traid group} $PT_N$ as the fundamental group of the configuration space $\mathcal{X}_{N,1,3}$. We define the \emph{traid group} $T_N$ as the orbifold fundamental group \cite{thurston_geometry_2002} of $\mathcal{X}_{N,1,3}/S_N$. Like the braid groups, the traid groups are infinite non-abelian groups that have an intuitive diagrammatic representation in terms of weaving strands, see Figs.\ \ref{fig:braidtraidcontrast} and \ref{fig:pure-traid-and-braid-choreography}, but the weaving rules are different. Like the symmetric group, both the braid group $B_N$ and the traid group $T_N$ can be defined by the relations among $N-1$ generators corresponding to exchanging adjacent particles. We show below that $B_N$ and $T_N$ can be understood as two different ways of `loosening' $S_N$ symmetry: for $B_N$ the generators are no longer self-inverses; and for $T_N$ the generators no longer satisfy the Yang-Baxter relation (aka the braid relation or the third Reidemeister move). Breaking the Yang-Baxter relation allows for abelian and non-abelian representations of $T_N$ that exhibit generalized exchange statistics different from braid anyons. As we show below, $T_N$ is a linear hyperbolic Coxeter group~\cite{coxeter_regular_1973,humphreys_reflection_1992} with $N-1$ generators connected by infinitesimal angles, sometimes denoted $[\infty^{N-1}]$. The lowest traid group $T_3$ is isomorphic to the infinite dihedral group $D_\infty \sim [\infty]$ and the lowest pure traid group $PT_3$ (like $B_2$ and $PB_2$) is isomorphic to the group of integers.

\begin{figure}
 \centering
 \includegraphics[scale=0.25, angle=90]{pure-traid-vs-pure-braid.pdf}
 \caption{The pure braid group $PB_N$ and the pure traid group $PT_N$ apply to distinguishable particles and therefore group elements correspond to strand diagrams where all particles start and end at the same place. Here we depict the strand diagrams for the generators of $PB_2$ (top) and $PT_3$ (bottom). The configuration spaces for three particles with hard-core three-body interactions in one dimension
  $\mathcal{X}_{3,1,3}$ and for two particles with hard-core two-body interactions in two
  dimensions, $\mathcal{X}_{2,2,2}$ are homotopy equivalent to the circle $S^1$. Their fundamental groups $PT_3$ and $PB_2$ are both isomorphic to $\mathbb{Z}$ and generated by a choice of loop which starts at an arbitrary base point $x_0 \in S^1$ and travels around the circle once.} \label{fig:pure-traid-and-braid-choreography}
\end{figure}

In the large literature on anyons there are other generalizations of braid groups and their representations, e.g.~\cite{einarsson_fractional_1990,yamamoto_anyons_1994,read_non-abelian_2003,kauffman_virtual_2004,jacak_recovery_2010}, but the groups $PT_N$ and $T_N$ are distinct from any other groups analyzed in the context of generalized exchange statistics to the best of our knowledge.
Relevant mathematical analysis was initiated by Bj\"orner and Welker~\cite{bjorner_homology_1995}. Motivated by the complexity theory of graphs, they analyzed the topology of configuration spaces for one-dimensional $\mathcal{X}_{N, 1, k}$ and two-dimensional systems $\mathcal{X}_{N, 2, k}$ with $k$-body coincidences removed. Subsequent work by mathematicians investigated the fundamental groups of these spaces and their quotients by the symmetric group. In this previous work, the traid groups $T_N$ and pure traid group $PT_N$ have been called the twin group and pure twin group~\cite{khovanov_real_1996, khovanov_doodle_1997, bardakov_structural_2019} or the planar braid group and pure planar braid group~\cite{gonzalez_linear_2019}.
Interestingly, our results were anticipated by the earliest studies of the topological phase acquired in the adiabatic Born-Oppenheimer solutions of planar triatomic molecules~\cite{herzberg_intersection_1963, stone_spin-orbit_1976, mead_determination_1979}. Restrictions on the configuration space make this an effectively one-dimensional system with a singular three-body coincidence. As such, it provides an example of a system carrying a non-trivial representation of $PT_3$.

Despite occasional claims that anyons can only occur in two dimensions, there is a large body of previous work on one-dimensional anyons. This previous work has relied on one or more analogies to two-dimensional braid anyons, including: (1) obeying braid exchange statistics~\cite{polychronakos_non-relativistic_1989, ha_fractional_1995,zhu_topological_1996,kundu_exact_1999,girardeau_anyon-fermion_2006,hao_ground-state_2009, sree_ranjani_explicit_2009, keilmann_statistically_2011,wright_nonequilibrium_2014,zinner_strongly_2015,strater_floquet_2016,lange_strongly_2017}; (2) obeying generalized \emph{exclusion} statistics~\cite{haldane_``fractional_1991,haldane_``spinon_1991,ha_exact_1994, ha_fractional_1995, girardeau_anyon-fermion_2006,batchelor_one-dimensional_2006,patu_correlation_2007, vitoriano_fractional_2009}; or (3) having wave functions with either Laughlin (abelian braid anyons~\cite{laughlin_anomalous_1983}) or Pfaffian (non-abelian braid anyons~\cite{moore_nonabelions_1991,greiter_paired_1992}) forms~\cite{haldane_``spinon_1991,polychronakos_non-relativistic_1989,paredes_pfaffian-like_2007, girardeau_three-body_2010,paredes_non-abelian_2012}.

Note that all of these manifestations of braid anyon behavior appear naturally in the one-dimensional two-body hard-core Calogero-type models~\cite{polychronakos_non-relativistic_1989,ha_exact_1994,ha_fractional_1995, sree_ranjani_explicit_2009}.
One-dimensional models with fractional exchange statistics can also be constructed `by hand', i.e.\ inserting the phase $e^{i\theta}$ into the commutation relations of creation and annihilation operators~\cite{zhu_topological_1996}. But to emphasize, fractional exchange statistics are characteristic of abelian representations of the braid group and do not occur for the traid group, in which two-particle exchanges must be square-trivial. The abelian traid anyons we conjecture would obey a different form of generalized exchange statistics than the braid anyons.

Intriguingly, fractional exchange statistics occur `naturally' in some one-dimensional free-space models and lattice models with competing two-body \emph{and} three-body interactions, like the Kundu model~\cite{kundu_exact_1999} and the anyon-Hubbard model~\cite{paredes_pfaffian-like_2007, keilmann_statistically_2011, paredes_non-abelian_2012, wright_nonequilibrium_2014, strater_floquet_2016, lange_strongly_2017}. The Kundu model has highly-singular two-body and three-body interactions. For a certain balance of interaction strengths, the system can be transformed into an equivalent model with only two-body delta-interactions and `twisted' boundary conditions. This model is integrable and solvable by Bethe-ansatz~\cite{kundu_exact_1999,batchelor_one-dimensional_2006,patu_correlation_2007}. This is somewhat surprising, because generally three-body interactions break the Yang-Baxter relation (as in the traid group) and prevent integrability~\cite{ha_fractional_1995, sutherland_beautiful_2004}. In the anyon-Hubbard model, effective three-body interactions are created by occupation-number dependent hopping amplitudes~\cite{keilmann_statistically_2011,strater_floquet_2016} and the wave function has a Pfaffian form~\cite{paredes_pfaffian-like_2007,paredes_non-abelian_2012}. Solutions that have a Pfaffian from exhibit non-abelian braid statistics, and they can also be understood as the eigenstates of effective $k$-body hard-core interactions~\cite{greiter_paired_1991,read_beyond_1999,cooper_exact_2004,girardeau_three-body_2010}.

However, no one has considered how the connectivity of the underlying configuration space for the Kundu or anyon-Hubbard models is disrupted by the co-dimension $\tilde{d}=2$ defects created by the addition of three-body interactions. Whether any of this previous work on one-dimensional anyons with three-body interactions can be reinterpreted in terms of traid groups remains an open question for future work. Additionally, implementing models with traid statistics in tight-binding lattice models with occupation-number dependent tunneling is an intriguing possibility.

\section{Configuration space}\label{sect:config}

The possibility for generalized exchange statistics is determined by the fundamental groups of two related spaces: (1) the configuration space $\mathcal{X}_{N,d,k}$ for $N$ distinguishable particles in $d$ dimensions with $k$-body hard-core interactions; and (2) the configuration space $\mathcal{X}_{N,d,k}/S_N$ for $N$ indistinguishable particles. When there are no interactions, the free configuration space of $N$ distinguishable particles in Euclidean space is the manifold $\mathbb{R}^{dN}=\left\{ (x_1,\ldots,x_N) \in \mathbb{R}^d\times \cdots \times \mathbb{R}^d \right\}$. For indistinguishable particles, the free configuration space is the orbifold $\mathcal{X}_{N,d,k}/S_N$, the quotient of the free configuration space by the symmetric group on $N$ objects. Configurations in $\mathbb{R}^{dN}$ that differ by only a permutation of particle positions are identified by the same point in $\mathbb{R}^{dN}/S_N$~\cite{leinaas_theory_1977,thurston_geometry_2002}.

The hard-core $k$-body interactions create impenetrable defects and complicate the topology of configuration space. Since the exact functional form of an interaction does not affect the connectivity, we can model the defects as zero-range, contact interactions without loss of generality. Then the defects are described by the coincidence structure $V_{N,d,k}$, defined as the union of all $\binom{N}{k}$ linear subspaces formed by coincidences of $k$ distinct particles $x_{i_1},\ldots,x_{i_k}$ in $d$-dimensions. Each linear subspace in the coincidence structure $V_{N,d,k}$ corresponds to $x_{i_1}=\cdots=x_{i_k}$ and has a co-dimension $\tilde{d}=d(k-1)$. Note that coincidence structures for higher-body interactions are nested inside lower-body interactions, i.e.\ when $k'>k$ then $V_{N,d,k'}\subset V_{N,d,k}$. The geometry and symmetries of these structures are analyzed in \cite{harshman_coincidence_2018}.

Removing the coincidence structure $V_{N,d,k}$ from the free configuration space $\mathbb{R}^{dN}$ gives the configuration space $\mathcal{X}_{N,d,k}= \mathbb{R}^{dN} - V_{N,d,k}$. Analyzing the connectivity of $\mathcal{X}_{N,d,k}$ is made simpler by using two symmetries to trivialize two degrees of freedom. First, $\mathcal{X}_{N,d,k}$ is invariant under translation in the $d$-dimensional linear subspace where all particles coincide $x_{1}=\cdots=x_{N}$, i.e.\ translations along the coincidence structure $V_{N,d,N} = \mathbb{R}^d$ corresponding to the the center-of-mass degree of freedom are a symmetry of $\mathcal{X}_{N,d,k}$. Second, the coincidence structure $V_{N,d,k}$ is constructed from linear subspaces that are scale invariant, and so the space $\mathcal{X}_{N,d,k}$ is also scale invariant. Combining these two symmetries, the configuration space can be factored into a reduced configuration space $\overline{\mathcal{X}}_{N,d,k}$ and two other terms $\mathcal{X}_{N,d,k} = \overline{\mathcal{X}}_{N,d,k} \times \mathbb{R}^+ \times \mathbb{R}^d$. Similarly, the free configuration space factors into $\mathbb{R}^{dN} =  S^{d(N-1)-1} \times \mathbb{R}^+ \times \mathbb{R}^d$.
Since $\mathbb{R}^+$ and $\mathbb{R}^d$ are homotopically trivial, $\mathcal{X}_{N,d,k}$ and $\overline{\mathcal{X}}_{N,d,k}$ are homotopy equivalent; i.e.\ they have the same connectivity and in particular they have isomorphic fundamental groups.

The reduced coincidence structure $\overline{V}_{N,d,k}$ can be defined by projection in the almost same way, as long as $V_{N,d,N}$ is added back in by hand $V_{N,d,k} = \left(\overline{V}_{N,d,k} \times \mathbb{R}^+ \times \mathbb{R}^d \right) \cup V_{N,d,N}$. For $N>k$ the space $\overline{V}_{N,d,k}$ is an arrangement of $\binom{N}{k}$ copies of spheres $S^{d(N-k)-1}$ contained inside the reduced free configuration space $S^{d(N-1)-1}$. These results agree with Thm.~1.3 of \cite{bjorner_homology_1995}, which analyzes the topology of $V_{N,1,k}$ and $V_{N,2,k}$ and proves they are homotopically equivalent to the wedge product of spheres.

\begin{figure}
 \centering
 \includegraphics[scale=0.2]{reducedX413.png}
 \includegraphics[scale=0.2]{reducedX412.png}
 \includegraphics[scale=0.4]{2-interactions-rotated.pdf}
 \caption{From top left, $\overline{\mathcal{X}}_{4,1,3}$ with $3$-coincidence loci as the intersection of $S^2$ with rays from the origin (black). Next, brown regions are $\overline{\mathcal{X}}_{4,1,2}$; formed by cutting $S^2$ along circles of $\overline{V}_{4,1,2}$. Finally, their mutual stereographic projection shows the $4!$ fundamental regions of the symmetric group action. Note that not all intersections of the $2$-coincidence locus correspond to $3$-coincidences; some correspond to commuting generators $t_1$ and $t_3$ of the traid group $T_4$.} \label{fig:reducedX413}
\end{figure}

As a relevant example, consider four particles in one dimension with hard-core two-body or three-body interactions. The spaces $\overline{\mathcal{X}}_{4,1,2}$ and $\overline{\mathcal{X}}_{4,1,3}$ are depicted in Fig.~\ref{fig:reducedX413}. The reduced free configuration space is the sphere $S^2$. The two-body reduced coincidence structure $\overline{V}_{4,1,2}$ is six intersecting great circles $S^1$ on the sphere. Because these circles have co-dimension $\tilde{d}=1$, they segment the reduced configuration space $\bar{\mathcal{X}}_{4,1,2}$ into 24 disconnected sectors corresponding to a specific orders of particles in one dimension. In the orbifold space $\overline{\mathcal{X}}_{4,1,2}/S_4$, these 24 sectors are identified with each other into a single sector representing configurations of four indistinguishable particles. The three-body reduced coincidence structure $\overline{V}_{4,1,3}$ is four copies of $S^0$ (i.e.\ two points) and the reduced configuration space $\overline{\mathcal{X}}_{4,1,3}$ is therefore a sphere $S^2$ with eight points missing like holes. By imagining stretching one hole out to infinity, flattening the sphere to a disk, and then contracting the space between the remaining seven holes, one can demonstrate that $\overline{\mathcal{X}}_{4,1,3}$ is topologically equivalent to the wedge product of seven circles, i.e.\ seven loops that share a single point.

\section{Fundamental groups}\label{sect:fund}

The space $\mathcal{X}_{N,d,k}$ is a manifold for any $N$, $d$ and $k$, and the usual definition of the fundamental group can be applied to describe its topology~\cite{hatcher_algebraic_2001}. As stated before, only $\mathcal{X}_{N,2,2}$ and $\mathcal{X}_{N,1,3}$ have non-trivial fundamental groups $PB_N = \pi_1(\mathcal{X}_{N,2,2})$ and $PT_N = \pi_1(\mathcal{X}_{N,1,3})$. The lowest possible manifestations of the two groups are isomorphic $PB_2 = PT_3 =\mathbb{Z}$, but they are different groups after that. The next traid group $PT_4 = \pi_1(\mathcal{X}_{4,1,3})= \pi_1(\overline{\mathcal{X}}_{4,1,3}) =F_7$, the free group with seven generators. The number of generators of $PT_N$ is at least $2^{N-3} (N^2 - 5N +8) -1$, the Betti number for $\mathcal{X}_{N,1,3}$~\cite{bjorner_homology_1995,barcelo_discrete_2008}. For $N \geq  6$, the existence of disjoint triplets of particles imply $PT_N$ is no longer a free group.

Similar to the relation between the pure braid group and braid group, the pure traid group is the subgroup of the traid group that contains by all elements that do not permute the particles. The traid group $T_N$ has a much simpler structure than $PT_N$ and only $N-1$ generators for all $N$. Ideally we would like to define $T_N$ as the fundamental group of $\mathcal{X}_{N,1,3}/S_N$ and use it to analyze the subgroup $PT_N$. However, a complicating factor is that the quotient space $\mathcal{X}_{N,d,k}/S_N$ is only a manifold when $k=2$. When $k=2$, the action of any non-trivial element of $S_N$ takes some open neighborhood of any point entirely off of itself.
Therefore there is no problem defining the braid group $B_N$ as the fundamental group of $\mathcal{X}_{N,2,2}/S_N$. However, when $k>2$ the configuration space contains points with a repeated coordinate. For these points, there are non-trivial elements of the symmetric group which fix the point and act on open neighborhoods by a reflective symmetry. Therefore $\mathcal{X}_{N,d,k}/S_N$ is not a manifold and taking the quotient na\"{i}vely loses important topological information. For example, $\overline{\mathcal{X}}_{3,1,3}/S_3$ is a closed line segment and $\overline{\mathcal{X}}_{4,1,3}/S_4$ is a triangle missing two corners. To preserve the topological information, we must regard the quotient as an {\em orbifold} and define a generalization of the fundamental group called the \emph{orbifold fundamental group}~\cite{thurston_geometry_2002}. For details, see the Appendix.

With this generalized definition, the orbifold fundamental group $T_N = \pi_1(\mathcal{X}_{N,1,3}/S_N)$ is  the semidirect product $T_N = PT_N \ltimes S_N$ of the pure traid group $PT_N$ and the symmetric group $S_N$. The corresponding short exact sequence is $1 \to PT_N \hookrightarrow T_N \twoheadrightarrow S_N \to 1$.

\section{Presentations}\label{sect:pres}

The group $T_N$ is generated by elementary moves which pass pairs of adjacent particles through each other; these correspond to paths in the configuration space $\mathcal{X}_{N,1,3}$ which return the individual particles to their original positions as a set and which cross $V_{N,1,2}$ at a single generic point. In contrast with the braid group, there is no over/under crossing information. Since two-particle coincidences are allowed, each of the elementary swaps are square trivial and are thus their own inverse; see Fig.~\ref{fig:braidtraidcontrast}. Further, the braid group allows the third Reidemeister move (a Yang-Baxter relation from knot theory) as shown in Fig.~\ref{fig:braidtraidcontrast}, which would introduce a triple point in our context. It follows that the traid group $T_N$ has a presentation with generators, $t_1,\ldots, t_{N-1}$, and relations:
\begin{eqnarray}\label{eq:tpres}
   t_i^2 & = 1 \ &\forall i \nonumber \\
   t_it_j & = t_jt_i \ &\forall |i-j|>1 .
\end{eqnarray}
Each of the $N-1$ generators correspond to trades of the $i^{th}$ and $(i+1)^{th}$ elements. As in the braid group, all sufficiently distant generators commute. The first defining relation of the traid group $t_i^2=1$ for all $i$ means that the traid group is generated by reflections. Combined with the second defining relation of the traid group, which can be rewritten to $(t_it_j)^2=1$ for all $|i-j|>1$, mean that $T_N$ is a \emph{linear} Coxeter group, i.e.\ it does not branch or loop. See Fig.~\ref{fig:coxeter}.

\begin{figure}
\centering
 \includegraphics{coxeter-diagram}
 \caption{The Coxeter-Dynkin diagram for $T_N$ has $N-1$ nodes arranged linearly with all labels equal to $\infty$. Any of the finite-labeled linear Coxeter groups on $N-1$ generators can be considered a quotient of $T_N$. When the finite labels are multiples of $3$, the quotient is a normal subgroup contained within $PT_N$. } \label{fig:coxeter}
\end{figure}

It is interesting to note the relationships between the presentations of the traid, symmetric, and braid groups on $N$ strands. We have two slightly different presentations for the symmetric group. The first has generators $s_1, \ldots, s_{N-1}$ and relations
\begin{align*}
 s_i^2 & = 1 & \forall i \\
 s_i s_j & = s_j s_i & \forall |i-j|>1 \\
 (s_{i+1} s_i)^3 & = 1 & \forall i< N-1
\end{align*}
The traid group is then the group which is obtained by erasing the triple point relation $(s_{i+1}s_i)^3=1$.
The other symmetric group presentation rewrites the triple point relation into the Yang-Baxter relation:
\begin{displaymath}
 \Big[ (s_{i+1} s_i)^3 = 1 \Big] \to \Big[ s_is_{i+1}s_i = s_{i+1}s_is_{i+1} \Big]
\end{displaymath}
The braid group has a presentation with generators $b_1,\ldots, b_{N-1}$ and relations
\begin{align*}
 b_i b_j & = b_j b_i & \forall |i-j|>1 \\
 b_i b_{i+1} b_i & = b_{i+1} b_i b_{i+1} & \forall i< N-1
\end{align*}
which omits only the $s_i^2=1$ relation from the symmetric group. As with the traid group, we get a homomorphism $B_N \twoheadrightarrow S_N$ induced by $b_i \mapsto s_i$ whose kernel is the pure braid group $PB_N$. The preservation of the Yang-Baxter relation is important and is related to the realization of $B_N$ as the mapping class group of an $N$-fold marked disc. The traid groups have no such realization as an automorphism of the underlying space.

As the pure traid group is precisely the kernel of the homomorphism $T_N\twoheadrightarrow S_N$ given by $t_i\to s_i$ on the generators, the pure traid group $PT_N$ can be seen to be normally generated in $T_N$ by the elements of the form $(t_{i+1}t_i)^3$. For example, $PT_3$ is a copy of $\mathbb{Z}$ generated by $(t_2t_1)^3$. The next pure traid group $PT_4$ is somewhat more complicated to express in terms of traid group generators. One possible presentation of $PT_4$ has eight generators $\gamma_1,\ldots,\gamma_8$ and one relation
\begin{equation*}
 \gamma_8 \gamma_7 \gamma_6 \gamma_5 \gamma_4 \gamma_3 \gamma_2 \gamma_1 = 1.
\end{equation*}
 The eight generators of $PT_4$ can be constructed as products of the three generators of $T_4$:
\begin{equation}
\begin{aligned}
 \gamma_1 & = & (t_2t_1)^3 &&  \gamma_5 & = & t_3t_2t_1(t_2t_3)^3t_1t_2t_3\\
 \gamma_2 & = & t_2t_1(t_3t_2)^3t_1t_2 &&  \gamma_6 & = & t_3(t_1t_2)^3t_3\\
 \gamma_3 & = & t_2t_3(t_2t_1)^3t_3t_2 &&  \gamma_7 & = & t_1(t_2t_3)^3t_1\\
 \gamma_4 & = & (t_3t_2)^3 && \gamma_8 & = & t_1t_2t_3(t_1t_2)^3t_3t_2t_1
\end{aligned}\label{eq:pt4}
\end{equation}
The order of the traid group generators $t_i$ can be inferred from the pattern of paths in Fig.~\ref{fig:pt4}.

\begin{figure}
\centering
 \adjustbox{trim={.12\width} {.12\height} {0.12\width} {.10\height},clip}{\includegraphics[width= 1.2\columnwidth]{pt4_generators}}
 \caption{This figure depicts eight loops $\gamma_1$ through $\gamma_8$ that provide generators for the presentation of $PT_4$ described in Eqs.~\ref{eq:pt4}. The purple star is an arbitrarily chosen base point in $\overline{\mathcal{X}_{4,1,3}}$ (see Fig.~\ref{fig:reducedX413}) where all loops start and end and the direction of all loops travel out from the base point, then go counterclockwise around the triple coincidence point, and then return back along the same path. The colored circles correspond to the two-particle coincidences, but here they are colored by the elements of the traid group. The red arcs correspond to $t_1$ (i.e.\ exchanging the first and second particle, no matter which particle they are), the green are $t_2$, and the blue are $t_3$. For example, loop $\gamma_1$ crosses red, green, red, green, red and then green, and so $\gamma_1 = t_2 t_1 t_2 t_1 t_2 t_1 =(t_2 t_1)^3$. Loop $\gamma_2$ crosses green, red, green, blue, green, blue, green, blue, red, then finally green again and so $\gamma_2 = t_2t_1(t_3 t_2)^3 t_1t_2$.} \label{fig:pt4}
\end{figure}

\section{Representations}\label{sect:repres}

Because $t_i^2=1$ for each of the generators, the abelian representations of $T_N$ are easily classified. Any representation $\rho:T_N\to U(1)$ must have $\rho(t_i)=\pm 1$ for all $i$, and then all other constraints of the presentation (\ref{eq:tpres}) are satisfied. Consequently, there are $2^{N-1}$ abelian representations of $T_N$ corresponding to all binary choices of signs for each generator\footnote{In this paper, we have not considered projective representations of the traid group, only unitary representations.}. The simplest two are when $\rho(t_i)=+ 1$ for all $i$ (this is equivalent to the bosonic representation of $S_N$) and when $\rho(t_i)=- 1$ for all $i$ (this is equivalent to the fermionic representation of $S_N$). Novel abelian representations of $T_N$ that cannot be factored through $S_N$ representations occur when there are mixed signs.

For an example where there are wave functions that transform like these mixed representations, consider the simplest case of three identical particles in a one-dimensional harmonic trap with zero-range hard-core three-body interactions. The Hamiltonian for this system can be expressed in scaled particle coordinates as
\begin{equation}
H = \frac{\hbar \omega}{2} \sum_{i=1}^3 \left( -\frac{\partial^2}{\partial x_i^2} + x_i^2 \right) + g \delta(x_1-x_2)\delta(x_2-x_3)
\end{equation}
in the limit $g \to \infty$. Transforming to Jacobi polar relative coordinates
$\rho$ and $\varphi$~\cite{harshman_symmetries_2012}
\begin{eqnarray}
\rho^2 &=& \frac{2}{3} \left(x_1^2 + x_2^2 + x_3^2 -x_1x_2 -x_2x_3 - x_3x_1\right)\nonumber\\
\tan \varphi &=& \frac{\sqrt{3} (x_1 - x_2)}{x_1+x_2 -2 x_3},
\end{eqnarray}
the relative Hamiltonian becomes
\begin{equation}\label{eq:2dham}
H_\mathrm{rel} = \frac{\hbar \omega}{2} \left[ -\frac{1}{\rho}\frac{\partial}{\partial \rho}\left(\rho \frac{\partial}{\partial \rho}\right) - \frac{1}{\rho^2} \frac{\partial^2}{\partial \varphi^2}+ \rho^2 \right] + g \delta^{(2)}(\rho)
\end{equation}
(again in the limit $g\to \infty$). Note that this has the same functional form as the relative Hamiltonian for two-particles with zero-range hard-core two-body interactions in a two-dimensional harmonic trap, a perennial test-bed for studying fractional exchange statistics, c.f.~\cite{leinaas_theory_1977,wilczek_quantum_1982,khare_fractional_1997}. The energy spectrum for the relative Hamiltonian (\ref{eq:2dham}) is $E_\mathrm{rel} = \hbar\omega (2 \nu + \lambda + 1)$, where $\nu$ is a non-negative integer counting the radial nodes and $\lambda$ is the relative `angular momentum'. The spectrum of allowed values of $\lambda$ depends on the boundary conditions implied by the particle statistics. For bosonic $\rho(t_1)=\rho(t_2)=+ 1$ and fermionic $\rho(t_1)=\rho(t_2)=- 1$ representations, the magnitude of the three-body relative `angular momentum' $\lambda$ is restricted to values that are positive integer multiples of $3$~\cite{harshman_symmetries_2012}. However, states with relative angular momenta $\lambda = 3/2$, $9/2$, etc.\ satisfy the exchange statistics governed by the mixed abelian representations of $T_3$ where $\rho(t_1)=-\rho(t_2)$. These wave functions are double-valued on $\mathcal{X}_{3,1,3}$, but they give single-valued, anyonic wave functions on the orbifold $\mathcal{X}_{3,1,3}/S_3$ (see Fig.~\ref{fig:states}). The states have lower energy than the lowest energy fermionic and bosonic states. Extending these preliminary results and comparing to the case of braid anyons and gauge transformations is ongoing work.

\begin{figure}
\centering
\includegraphics[width= .9\columnwidth]{t3states}
 \caption{Subfigures a and b are contour plots of the relative wave function of the lowest energy eigenstates of $H_\mathrm{rel}$ (\ref{eq:2dham}) with $\lambda = 3$ for bosons $\rho(t_1)=\rho(t_2) = +1$ and fermions $\rho(t_1)=\rho(t_2) = -1$, respectively. Subfigures c and d depict the relative wave function of the lowest energy eigenstates of $H_\mathrm{rel}$ with $\lambda = 3/2$ and anyonic symmetry in the abelian representations $\rho(t_1)=-\rho(t_2) = +1$ and $\rho(t_1)=-\rho(t_2) = -1$, respectively. The solid arrows correspond to the boundaries defined by the $t_1$ generators and the dashed arrows to boundaries the $t_2$ generators. The red horizontal line in subfigures c and d is the branch cut arising from the double-covering created by fractional angular momentum; the wave function changes sign when crossing this branch.} \label{fig:states}
\end{figure}

Any representation of $T_N$ gives a representation of $PT_N$ by restriction. Mixed abelian representations of $T_N$ restrict to non-trivial representations of $PT_N$ in which a cyclic exchange of distinguishable particles leads to a sign change of the wave functions. Additionally, there are representations of $PT_N$ which do not extend to representations of $T_N$. For example, $PT_3\sim \mathbb{Z}$ and so has infinitely many abelian representations $\rho_\theta(n)=e^{in\theta}$ parametrized by $\theta\in[0,2\pi)$, similar to the fractional exchange statistics. Further, $PT_4$ has an abelian representation for any assignment $\rho(\gamma_k)=e^{i\theta_k}$ with $\sum_{k=1}^8 \theta_k = 0 \mod 2\pi$. In other words, unlike abelian representations of $B_N$, not all generators must have the same phase. In general, abelian representations of $PT_N$ must factor through the abelianization and are parametrized by the first cohomology of the configuration space with coefficients in $U(1)$, $H^1(\mathcal{X}_{N,1,3};U(1))$. The integer versions of these groups have been calculated in \cite{bjorner_homology_1995}. In particular, as the first homology is non-trivial for $N\geq 3$, $PT_N$ always has many abelian representations.

Non-abelian representations of $T_N$ and $PT_N$ are a seemingly rich topic. As shown in Fig.~\ref{fig:coxeter}, the group $T_N \sim [\infty^{N-1}]$ may be considered a kind of `universal object' in the category of Coxeter groups with linear Coxeter-Dynkin diagrams. In other words, for every irreducible representation of any linear Coxter group with $N-1$ generators, one can induce an irreducible representation of $T_N$. As an example, consider the case when $N=4$ and define $K^{[m,n]}$ as the normal subgroup of $T_4$ generated by $(t_2t_1)^m$ and $(t_3t_2)^n$ and their conjugates by elements of $T_4$. Note that this means that the normal subgroup includes the terms generated by inequivalent conjugates like those found in (\ref{eq:pt4}). Then the quotient group $T_4/K^{[m,n]}$ is the linear Coxeter group $[m,n]$. Examples include
\begin{itemize}
\item the finite Coxeter groups $[3,3]\equiv A_3 \sim S_4$, $[4,3] \equiv C_3$, and $[5,3] \equiv H_3$,
\item the affine Coxeter groups $[4,4]\equiv \tilde{C}_2$ and $[6,3]\equiv \tilde{G}_2$, and
\item the hyperbolic Coxeter groups $[p,q]$ with $2(p+q)<pq$.
\end{itemize}
Using the homomorphism $T_4 \rightarrow [m,n]$, one can construct a representation of $T_4$ from any irreducible representation of $[m,n]$ by pullback, including multi-dimensional, non-abelian representations. In particular, note that the special case $K^{[3,3]} = PT_4$ leads to the symmetric group $[3,3]\equiv A_3 \sim S_4$. This method extends to any $N$, but at this point, it is not known whether the irreducible representations constructed this way exhaust the irreducible representations of $T_N$.

As for non-abelian representations of $PT_N$ for $N>3$, we similarly expect there to be many. The groups $PT_4$ and $PT_5$ are free and so homomorphisms to any group exist and the generators of the $PT_N$'s may be sent to arbitrary values. When $N\geq 6$, there are additional commutation relations among the generators which need to be satisfied, but we have not yet determined the full set of relations.

\section{Summary and outlook}\label{sect:summ}

In summary, the anyonic physics that derives from the not-simply-connected configuration space of $N$ particles with three-body hard-core interactions in one-dimension has some similarities but also intriguing differences from the more familiar hard-core two-body interactions in two dimensions. Similarities include: 1) the braid group $B_N$ and the traid group $T_N$ are both generalizations of the symmetric group $S_N$ with one defining relation removed; 2) both $B_N$ and $T_N$ have `pure' subgroups describing distinguishable particles; 3) representations of both groups give abelian and non-abelian generalized exchange statistics; and 4) unlike fermionic and bosonic wave functions, anyonic wave functions cannot be built from the tensor product of one-particle states.

Differences between braid anyons and traid anyons include: 1) in the traid group, the Yang-Baxter relation is broken instead of the square-trivial relation as in the braid group; 2) the traid group does not have an interpretation in terms of diffeomorphisms of the underlying space; and 3) the traid group derives from the orbifold fundamental group of the identical particle configuration space instead of the more familiar notion of the fundamental group.

Two extensions of this work immediately suggest themselves. First, the representation theory of the traid groups is far from developed, and that will be necessary before model-building and analysis can elucidate the differences from braid anyons more clearly and before implementations and observables can be suggested for experiments with ultracold atoms. For example, another difference between braid anyons and traid anyons worth more exploration is what happens when parity reflections are included. Traid anyons in a parity symmetric trap should either be parity-symmetric or come in doublets that mix under parity. In contrast, braid anyons do not respect parity~\cite{khare_fractional_1997}. The mixing of traid group representations under supersymmetry also appears to be an interesting question. Second, for braid anyons, the generalized exchange statistics can be incorporated into an interaction derived from a gauge field~\cite{wilczek_quantum_1982,wilczek_fractional_1990,forte_quantum_1992,khare_fractional_1997}. The preliminary results for traid anyons in a one-dimensional harmonic trap mentioned above suggest that a similar transmutation of statistics into non-local few-body interactions is possible.

\emph{Acknowledgments.} NLH would like to thank D.\ Blume, S.\ Chandrasekharan, A.\ Eckhardt, M.A.\ Garci\'{a}-March, J.M.\ Midtgaard, M.\ Olshanii, and N.T.~Zinner for helpful discussions.

redpajama_set_name: RedPajamaArXiv


text:
Q: Compile code fully in memory with javax.tools.JavaCompiler I'm using the JavaCompiler from the javax.tools package (JDK 1.7) to compile some stuff on the fly, like this:
compiler.run(null, null, "-cp", paths, "path/to/my/file.java");

It works but I would like to do it all in memory (e.g. pass a string with the code, not the source file, and get the byte code back not a .class file). I found that extending the InputStream and OutputStream parameters is no use since it's probably just the same as in the console. Do you know a way to make the run method work like this? Or do you know a confirmed way to do this with the getTask() method? (extending the FileManager looks easy but isn't that easy :)

A: I wrote a library to do this a few years ago. It takes a String which can contain nested classes, compiles them and optionally loads them into the current class loader (so you don't need an additional class loader) If the JVM is running in debug mode it will write the generated code to a file so you can step through your generated code.
http://vanillajava.blogspot.co.uk/2010_11_01_archive.html

To paraphrase the example from erolagnab you can do
StringBuilder sourceCode = new StringBuilder();
sourceCode.append("package org.mdkt;\n")
          .append("public class HelloClass {\n")
          .append("   public String hello() { return \"hello\"; }")
          .append("}");

Class<?> helloClass = CACHED_COMPILER.compile("org.mdkt.HelloClass",
                                              sourceCode.toString());

Update, the source is available here https://github.com/OpenHFT/Java-Runtime-Compiler
And you can obtain the latest build via maven http://search.maven.org/#browse%7C842970587

A longer example.
// this writes the file to disk only when debugging is enabled.
CachedCompiler cc = CompilerUtils.DEBUGGING ?
        new CachedCompiler(new File(parent, "src/test/java"), new File(parent, "target/compiled")) :
        CompilerUtils.CACHED_COMPILER;

String text = "generated test " + new Date();
Class fooBarTeeClass = cc.loadFromJava("eg.FooBarTee", "package eg;\n" +
    '\n' +
    "import eg.components.BarImpl;\n" +
    "import eg.components.TeeImpl;\n" +
    "import eg.components.Foo;\n" +
    '\n' +
    "public class FooBarTee{\n" +
    "    public final String name;\n" +
    "    public final TeeImpl tee;\n" +
    "    public final BarImpl bar;\n" +
    "    public final BarImpl copy;\n" +
    "    public final Foo foo;\n" +
    '\n' +
    "    public FooBarTee(String name) {\n" +
    "        // when viewing this file, ensure it is synchronised with the copy on disk.\n" +
    "        System.out.println(\"" + text + "\");\n" +
    "        this.name = name;\n" +
    '\n' +
    "        tee = new TeeImpl(\"test\");\n" +
    '\n' +
    "        bar = new BarImpl(tee, 55);\n" +
    '\n' +
    "        copy = new BarImpl(tee, 555);\n" +
    '\n' +
    "        // you should see the current date here after synchronisation.\n" +
    "        foo = new Foo(bar, copy, \"" + text + "\", 5);\n" +
    "    }\n" +
    '\n' +
    "    public void start() {\n" +
    "    }\n" +
    '\n' +
    "    public void stop() {\n" +
    "    }\n" +
    '\n' +
    "    public void close() {\n" +
    "        stop();\n" +
    '\n' +
    "    }\n" +
    "}\n");

// add a debug break point here and step into this method.
FooBarTee fooBarTee = new FooBarTee("test foo bar tee");
Foo foo = fooBarTee.foo;
assertNotNull(foo);
assertEquals(text, foo.s);

A: I've run the above code in Mac OS Java 7. None of them works. So i wrote one
https://github.com/trung/InMemoryJavaCompiler
StringBuilder source = new StringBuilder()
    .append("package org.mdkt;\n")
    .append("public class HelloClass {\n")
    .append("   public String hello() { return \"hello\"; }")
    .append("}");

Class<?> helloClass = InMemoryJavaCompiler.compile("org.mdkt.HelloClass", source.toString());

A: I think this here might be of help it basically shows how to compile Java source from memory (the string is located in the class).
It uses the PrinterWriter and StringWriter to write the source to a String/in memory and then uses the JavaCompiler class (since JDK 6) to compile and run the program:
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

public class CompileSourceInMemory {
  public static void main(String args[]) throws IOException {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

    StringWriter writer = new StringWriter();
    PrintWriter out = new PrintWriter(writer);
    out.println("public class HelloWorld {");
    out.println("  public static void main(String args[]) {");
    out.println("    System.out.println(\"This is in another java file\");");
    out.println("  }");
    out.println("}");
    out.close();
    JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
    CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

    boolean success = task.call();
    for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
      System.out.println(diagnostic.getCode());
      System.out.println(diagnostic.getKind());
      System.out.println(diagnostic.getPosition());
      System.out.println(diagnostic.getStartPosition());
      System.out.println(diagnostic.getEndPosition());
      System.out.println(diagnostic.getSource());
      System.out.println(diagnostic.getMessage(null));

    }
    System.out.println("Success: " + success);

    if (success) {
      try {

          URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { new File("").toURI().toURL() });
          Class.forName("HelloWorld", true, classLoader).getDeclaredMethod("main", new Class[] { String[].class }).invoke(null, new Object[] { null });

      } catch (ClassNotFoundException e) {
        System.err.println("Class not found: " + e);
      } catch (NoSuchMethodException e) {
        System.err.println("No such method: " + e);
      } catch (IllegalAccessException e) {
        System.err.println("Illegal access: " + e);
      } catch (InvocationTargetException e) {
        System.err.println("Invocation target: " + e);
      }
    }
  }
}

class JavaSourceFromString extends SimpleJavaFileObject {
  final String code;

  JavaSourceFromString(String name, String code) {
    super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
    this.code = code;
  }

  @Override
  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
    return code;
  }
}

If you have a look at the reference link you will find a few more other examples too
Reference:

*

*Compiling from Memory

A: I wanted:

*

*in-memory compilation of a java file (useful for Java as a scripting language)

*No additional dependencies (easy to setup)

*Implementation in as low number of files as possible (easy to incorporate in a project)

You can try it first here: http://ideone.com/cu1GhE#view_edit_box
The following code is based on Rekha Kumari code:
Main.java
package com.mycompany.java;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    //private static final Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        try {
            StringWriter writer = new StringWriter();
            PrintWriter out = new PrintWriter(writer);
            out.println("package com.mycompany.script;");
            out.println("");
            out.println("public class HelloWorld {");
            out.println("  public static void main(String args[]) {");
            out.println("    System.out.println(\"This is in another java file\");");
            out.println("  }");
            out.println("}");
            out.close();

            String fullName = "com.mycompany.script.HelloWorld";
            String src = writer.toString();

            DynamicCompiler uCompiler = new DynamicCompiler(fullName, src);
            uCompiler.compile();
            uCompiler.run();

        } catch (Exception e) {
            //logger.error("Exception:", e);
            System.out.print("Exception");
        }
    }
}

DynamicCompiler.java
package com.mycompany.java;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.List;

// Based on: http://javapracs.blogspot.cz/2011/06/dynamic-in-memory-compilation-using.html
public class DynamicCompiler {
    //private static final Logger logger = LoggerFactory.getLogger(DynamicCompiler.class);

    private JavaFileManager fileManager;
    private String fullName;
    private String sourceCode;

    public DynamicCompiler(String fullName, String srcCode) {
        this.fullName = fullName;
        this.sourceCode = srcCode;
        this.fileManager = initFileManager();
    }

    public JavaFileManager initFileManager() {
        if (fileManager != null)
            return fileManager;
        else {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            fileManager = new
                    ClassFileManager(compiler
                    .getStandardFileManager(null, null, null));
            return fileManager;
        }
    }

    public void compile() {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        List<JavaFileObject> files = new ArrayList<>();
        files.add(new CharSequenceJavaFileObject(fullName, sourceCode));

        compiler.getTask(
                null,
                fileManager,
                null,
                null,
                null,
                files
        ).call();
    }

    public void run() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            fileManager
                    .getClassLoader(null)
                    .loadClass(fullName)
                    .getDeclaredMethod("main", new Class[]{String[].class})
                    .invoke(null, new Object[]{null});
        } catch (InvocationTargetException e) {
            System.out.print("InvocationTargetException");
            //logger.error("InvocationTargetException:", e);
        } catch (NoSuchMethodException e) {
            System.out.print("NoSuchMethodException ");
            //logger.error("NoSuchMethodException:", e);
        }
    }

    public class CharSequenceJavaFileObject extends SimpleJavaFileObject {

        /**
         * CharSequence representing the source code to be compiled
         */
        private CharSequence content;

        public CharSequenceJavaFileObject(String className, CharSequence content) {
            super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.content = content;
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return content;
        }
    }

    public class ClassFileManager extends ForwardingJavaFileManager {
        private JavaClassObject javaClassObject;

        public ClassFileManager(StandardJavaFileManager standardManager) {
            super(standardManager);
        }

        @Override
        public ClassLoader getClassLoader(Location location) {
            return new SecureClassLoader() {
                @Override
                protected Class<?> findClass(String name) throws ClassNotFoundException {
                    byte[] b = javaClassObject.getBytes();
                    return super.defineClass(name, javaClassObject.getBytes(), 0, b.length);
                }
            };
        }

        public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
            this.javaClassObject = new JavaClassObject(className, kind);
            return this.javaClassObject;
        }
    }

    public class JavaClassObject extends SimpleJavaFileObject {
        protected final ByteArrayOutputStream bos =
                new ByteArrayOutputStream();

        public JavaClassObject(String name, Kind kind) {
            super(URI.create("string:///" + name.replace('.', '/')
                    + kind.extension), kind);
        }

        public byte[] getBytes() {
            return bos.toByteArray();
        }

        @Override
        public OutputStream openOutputStream() throws IOException {
            return bos;
        }
    }
}

A: This is a class that compiles entirely in memory.
I've taken (almost) the entirety of this from http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html by Rekha Kumari (June 2011). Though this version is more than 100 lines shorter and has considerably more features (but no docs:P).
It can compile multiple classes at once, which is the only way to compile classes that depend on each other. If you wonder about the class "CompilerFeedback": I was working on a tiny Java IDE for coding-games where I needed that. I'm including it here because I assume that you want to do something with this compiler, and the predigestion might help with that. (I realize that some of the code in the CompilerFeedback class is complete crap. It was recycled from a years old attempt.
There's also a utility method, not needed for compilation, that derives the full class name from a class' source code (incl. package name, if it's provided). Very useful for calling the compiler, which does need this information.
DEMO CLASS:
import java.util.ArrayList;
import java.util.List;

public class Demo {

    public static void main(final String[] args) {

        final InMemoryCompiler.IMCSourceCode cls1source;
        final InMemoryCompiler.IMCSourceCode cls2source;

        final StringBuilder sb = new StringBuilder();
        sb.append("package toast;\n");
        sb.append("public class DynaClass {\n");
        sb.append("    public static void main(final String[] args) {");
        sb.append("        System.out.println(\"Based massively on the work of Rekha Kumari, http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html\");\n");
        sb.append("        System.out.println(\"This is the main method speaking.\");\n");
        sb.append("        System.out.println(\"Args: \" + java.util.Arrays.toString(args));\n");
        sb.append("        final Test test = new Test();\n");
        sb.append("    }\n");
        sb.append("    public String toString() {\n");
        sb.append("        return \"Hello, I am \" + ");
        sb.append("this.getClass().getSimpleName();\n");
        sb.append("    }\n");
        sb.append("}\n");
        cls1source = new InMemoryCompiler.IMCSourceCode("toast.DynaClass", sb.toString());

        sb.setLength(0);
        sb.append("package toast;\n");
        sb.append("public class Test {\n");
        sb.append("    public Test() {\n");
        sb.append("        System.out.println(\"class Test constructor reporting in.\");\n");
        sb.append("        System.out.println(new DynaClass());\n");
        sb.append("    }\n");
        sb.append("}\n");
        cls2source = new InMemoryCompiler.IMCSourceCode("toast.Test", sb.toString());

        final List<InMemoryCompiler.IMCSourceCode> classSources = new ArrayList<>();
        classSources.add(cls1source);
        classSources.add(cls2source);

        final InMemoryCompiler uCompiler = new InMemoryCompiler(classSources);
        final CompilerFeedback compilerFeedback = uCompiler.compile();
        System.out.println("\n\nCOMPILER FEEDBACK: " + compilerFeedback);

        if (compilerFeedback != null && compilerFeedback.success) {

            try {
                System.out.println("\nTOSTRING DEMO:");
                uCompiler.runToString(cls1source.fullClassName);
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                System.out.println("\nMAIN DEMO:");
                uCompiler.runMain(cls1source.fullClassName, new String[] { "test1", "test2" });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }
}

COMPILER CLASS:
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MASSIVELY based on http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html by Rekha Kumari
 * (June 2011)
 */
final public class InMemoryCompiler {

    final public static class IMCSourceCode {

        final public String fullClassName;
        final public String sourceCode;

        /**
         * @param fullClassName Full name of the class that will be compiled. If the class should be in some package,
         *                      fullName should contain it too, for example: "testpackage.DynaClass"
         * @param sourceCode    the source code
         */
        public IMCSourceCode(final String fullClassName, final String sourceCode) {

            this.fullClassName = fullClassName;
            this.sourceCode = sourceCode;
        }
    }

    final public boolean valid;

    final private List<IMCSourceCode> classSourceCodes;
    final private JavaFileManager fileManager;

    public InMemoryCompiler(final List<IMCSourceCode> classSourceCodes) {

        this.classSourceCodes = classSourceCodes;

        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            fileManager = null;
            valid = false;
            System.err.println("ToolProvider.getSystemJavaCompiler() returned null! This program needs to be run on a system with an installed JDK.");
            return;
        }
        valid = true;

        fileManager = new ForwardingJavaFileManager<JavaFileManager>(compiler.getStandardFileManager(null, null, null)) {

            final private Map<String, ByteArrayOutputStream> byteStreams = new HashMap<>();

            @Override
            public ClassLoader getClassLoader(final Location location) {

                return new SecureClassLoader() {

                    @Override
                    protected Class<?> findClass(final String className) throws ClassNotFoundException {

                        final ByteArrayOutputStream bos = byteStreams.get(className);
                        if (bos == null) {
                            return null;
                        }
                        final byte[] b = bos.toByteArray();
                        return super.defineClass(className, b, 0, b.length);
                    }
                };
            }

            @Override
            public JavaFileObject getJavaFileForOutput(final Location location, final String className, final JavaFileObject.Kind kind, final FileObject sibling) throws IOException {

                return new SimpleJavaFileObject(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind) {

                    @Override
                    public OutputStream openOutputStream() throws IOException {

                        ByteArrayOutputStream bos = byteStreams.get(className);
                        if (bos == null) {
                            bos = new ByteArrayOutputStream();
                            byteStreams.put(className, bos);
                        }
                        return bos;
                    }
                };
            }
        };
    }

    public CompilerFeedback compile() {

        if (!valid) {
            return null;
        }
        final List<JavaFileObject> files = new ArrayList<>();
        for (IMCSourceCode classSourceCode : classSourceCodes) {
            URI uri = null;
            try {
                uri = URI.create("string:///" + classSourceCode.fullClassName.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension);
            } catch (Exception e) {
                //                e.printStackTrace();
            }
            if (uri != null) {
                final SimpleJavaFileObject sjfo = new SimpleJavaFileObject(uri, JavaFileObject.Kind.SOURCE) {

                    @Override
                    public CharSequence getCharContent(final boolean ignoreEncodingErrors) {

                        return classSourceCode.sourceCode;
                    }
                };
                files.add(sjfo);
            }
        }

        final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        if (files.size() > 0) {
            final JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, files);
            return new CompilerFeedback(task.call(), diagnostics);
        } else {
            return null;
        }
    }

    public void runToString(final String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

        if (!valid) {
            return;
        }
        final Class<?> theClass = getCompiledClass(className);
        final Object instance = theClass.newInstance();
        System.out.println(instance);
    }

    public void runMain(final String className, final String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {

        if (!valid) {
            return;
        }
        final Class<?> theClass = getCompiledClass(className);
        final Method mainMethod = theClass.getDeclaredMethod("main", String[].class);
        mainMethod.invoke(null, new Object[] { args });
    }

    public Class<?> getCompiledClass(final String className) throws ClassNotFoundException {

        if (!valid) {
            throw new IllegalStateException("InMemoryCompiler instance not usable because ToolProvider.getSystemJavaCompiler() returned null: No JDK installed.");
        }
        final ClassLoader classLoader = fileManager.getClassLoader(null);
        final Class<?> ret = classLoader.loadClass(className);
        if (ret == null) {
            throw new ClassNotFoundException("Class returned by ClassLoader was null!");
        }
        return ret;
    }
}

COMPILERFEEDBACK CLASS:
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

final public class CompilerFeedback {

    final public boolean success;
    final public List<CompilerMessage> messages = new ArrayList<>();

    public CompilerFeedback(final Boolean success, final DiagnosticCollector<JavaFileObject> diagnostics) {

        this.success = success != null && success;
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
            messages.add(new CompilerMessage(diagnostic));
        }
    }

    public String toString() {

        final StringBuilder sb = new StringBuilder();

        sb.append("SUCCESS: ").append(success).append('\n');
        final int iTop = messages.size();
        for (int i = 0; i < iTop; i++) {
            sb.append("\n[MESSAGE ").append(i + 1).append(" OF ").append(iTop).append("]\n\n");
            // sb.append(messages.get(i).toString()).append("\n");
            // sb.append(messages.get(i).toStringForList()).append("\n");
            sb.append(messages.get(i).toStringForDebugging()).append("\n");
        }
        return sb.toString();
    }

    final public static class CompilerMessage {

        final public Diagnostic<? extends JavaFileObject> compilerInfo;

        final public String typeOfProblem;
        final public String typeOfProblem_forDebugging;

        final public String multiLineMessage;

        final public int lineNumber;
        final public int columnNumber;

        final public int textHighlightPos_lineStart;
        final public int textHighlightPos_problemStart;
        final public int textHighlightPos_problemEnd;

        final public String sourceCode;
        final public String codeOfConcern;
        final public String codeOfConcernLong;

        CompilerMessage(final Diagnostic<? extends JavaFileObject> diagnostic) {

            final JavaFileObject sourceFileObject = diagnostic.getSource();
            String sourceCodePreliminary = null;
            if (sourceFileObject instanceof SimpleJavaFileObject) {
                final SimpleJavaFileObject simpleSourceFileObject = (SimpleJavaFileObject) sourceFileObject;

                try {
                    final CharSequence charSequence = simpleSourceFileObject.getCharContent(false);
                    sourceCodePreliminary = charSequence.toString();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (sourceCodePreliminary == null) {
                sourceCode = "[SOURCE CODE UNAVAILABLE]";
            } else {
                sourceCode = sourceCodePreliminary;
            }

            compilerInfo = diagnostic;

            typeOfProblem = diagnostic.getKind().name();
            typeOfProblem_forDebugging = "toString() = " + diagnostic.getKind().toString() + "; name() = " + typeOfProblem;

            lineNumber = (int) compilerInfo.getLineNumber();
            columnNumber = (int) compilerInfo.getColumnNumber();

            final int sourceLen = sourceCode.length();
            textHighlightPos_lineStart = (int) Math.min(Math.max(0, diagnostic.getStartPosition()), sourceLen);
            textHighlightPos_problemStart = (int) Math.min(Math.max(0, diagnostic.getPosition()), sourceLen);
            textHighlightPos_problemEnd = (int) Math.min(Math.max(0, diagnostic.getEndPosition()), sourceLen);

            final StringBuilder reformattedMessage = new StringBuilder();
            final String message = diagnostic.getMessage(Locale.US);
            final int messageCutOffPosition = message.indexOf("location:");
            final String[] messageParts;
            if (messageCutOffPosition >= 0) {
                messageParts = message.substring(0, messageCutOffPosition).split("\n");
            } else {
                messageParts = message.split("\n");
            }
            for (String s : messageParts) {
                String s2 = s.trim();
                if (s2.length() > 0) {
                    boolean lengthChanged;
                    do {
                        final int lBeforeReplace = s2.length();
                        s2 = s2.replace("  ", " ");
                        lengthChanged = (s2.length() != lBeforeReplace);
                    } while (lengthChanged);
                    reformattedMessage.append(s2).append("\n");
                }
            }

            codeOfConcern = sourceCode.substring(textHighlightPos_problemStart, textHighlightPos_problemEnd);
            codeOfConcernLong = sourceCode.substring(textHighlightPos_lineStart, textHighlightPos_problemEnd);
            if (!codeOfConcern.isEmpty()) {
                reformattedMessage.append("Code of concern: \"").append(codeOfConcern).append('\"');
            }
            multiLineMessage = reformattedMessage.toString();
        }

        public String toStringForList() {

            if (compilerInfo == null) {
                return "No compiler!";
            } else {
                return compilerInfo.getCode();
            }
        }

        public String toStringForDebugging() {

            final StringBuilder ret = new StringBuilder();

            ret.append("Type of problem: ").append(typeOfProblem_forDebugging).append("\n\n");
            ret.append("Message:\n").append(multiLineMessage).append("\n\n");

            ret.append(compilerInfo.getCode()).append("\n\n");

            ret.append("line number: ").append(lineNumber).append("\n");
            ret.append("column number: ").append(columnNumber).append("\n");

            ret.append("textHighlightPos_lineStart: ").append(textHighlightPos_lineStart).append("\n");
            ret.append("textHighlightPos_problemStart: ").append(textHighlightPos_problemStart).append("\n");
            ret.append("textHighlightPos_problemEnd: ").append(textHighlightPos_problemEnd).append("\n");

            return ret.toString();
        }

        @Override
        public String toString() {

            //            return compilerInfo.getMessage(Locale.US);
            return typeOfProblem + ": " + multiLineMessage + "\n";
        }
    }
}

UTILITY METHOD (Not needed for the three classes further up.):
final public static String PREFIX_CLASSNAME = "class ";
final public static String PREFIX_PACKAGENAME = "package ";
final public static String CHARSET_JAVAKEYWORDENDERS = " \n[](){}<>;,\"\\/*+-=%!&?@:";

/**
 * @return e.g. "com.dreamspacepresident.TestClass" if the source's first root level "class" (I'm talking about {}
 * hierarchy.) is named "TestClass", and if the "package" name is "com.dreamspacepresident". Null is returned if
 * sourceCode is null or does not provide a class name. (Mind that the parsing is done in a quite crappy way.)
 */
public static String deriveFullClassNameFromSource(final String sourceCode) {

    if (sourceCode == null) {
        return null;
    }
    final int firstBr = sourceCode.indexOf('{');
    if (firstBr >= 0) {
        // DETERMINE CLASS NAME
        final int firstClass = sourceCode.indexOf(PREFIX_CLASSNAME);
        if (firstClass < firstBr) {
            String className = sourceCode.substring(firstClass + PREFIX_CLASSNAME.length(), firstBr).trim();
            final int classNameEnd = indexOfAnyOfThese(className, CHARSET_JAVAKEYWORDENDERS);
            if (classNameEnd >= 0) {
                className = className.substring(0, classNameEnd);
            }
            if (!className.isEmpty()) {
                // DETERMINE PACKAGE NAME
                String packageName = null;
                final int firstPackage = sourceCode.indexOf(PREFIX_PACKAGENAME);
                if (firstPackage >= 0 && firstPackage < firstBr && firstPackage < firstClass) {
                    packageName = sourceCode.substring(firstPackage + PREFIX_PACKAGENAME.length(), firstBr).trim();
                    final int packageNameEnd = indexOfAnyOfThese(packageName, CHARSET_JAVAKEYWORDENDERS);
                    if (packageNameEnd >= 0) {
                        packageName = packageName.substring(0, packageNameEnd);
                    }
                }
                return (packageName != null && !packageName.isEmpty() ? packageName + "." : "") + className;
            }
        }
    }
    return null;
}

/**
 * Looks for the first occurrence of ANY of the given characters, which is easier than using a bunch of
 * String.indexOf() calls.
 *
 * @return -1 if not found, otherwise the String index of the first hit
 */
public static int indexOfAnyOfThese(final String text, final String characters) {

    if (text != null && !text.isEmpty() && characters != null && !characters.isEmpty()) {
        final int lenT = text.length();
        final int lenC = characters.length();
        for (int i = 0; i < lenT; i++) {
            final char c = text.charAt(i);
            for (int ii = 0; ii < lenC; ii++) {
                if (c == characters.charAt(ii)) {
                    return i;
                }
            }
        }
    }
    return -1;
}

A: I'd like to introduce my solution which runs well in production.
Here are the three source code files.
MemoryJavaCompiler.java
package me.soulmachine.compiler;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.tools.*;

/**
 * Simple interface to Java compiler using JSR 199 Compiler API.
 */
public class MemoryJavaCompiler {
    private javax.tools.JavaCompiler tool;
    private StandardJavaFileManager stdManager;

    public MemoryJavaCompiler() {
        tool = ToolProvider.getSystemJavaCompiler();
        if (tool == null) {
            throw new RuntimeException("Could not get Java compiler. Please, ensure that JDK is used instead of JRE.");
        }
        stdManager = tool.getStandardFileManager(null, null, null);
    }

    /**
     * Compile a single static method.
     */
    public Method compileStaticMethod(final String methodName, final String className,
        final String source)
        throws ClassNotFoundException {
        final Map<String, byte[]> classBytes = compile(className + ".java", source);
        final MemoryClassLoader classLoader = new MemoryClassLoader(classBytes);
        final Class clazz = classLoader.loadClass(className);
        final Method[] methods = clazz.getDeclaredMethods();
        for (final Method method : methods) {
            if (method.getName().equals(methodName)) {
                if (!method.isAccessible()) method.setAccessible(true);
                return method;
            }
        }
        throw new NoSuchMethodError(methodName);
    }

    public Map<String, byte[]> compile(String fileName, String source) {
        return compile(fileName, source, new PrintWriter(System.err), null, null);
    }

    /**
     * compile given String source and return bytecodes as a Map.
     *
     * @param fileName source fileName to be used for error messages etc.
     * @param source Java source as String
     * @param err error writer where diagnostic messages are written
     * @param sourcePath location of additional .java source files
     * @param classPath location of additional .class files
     */
    private Map<String, byte[]> compile(String fileName, String source,
        Writer err, String sourcePath, String classPath) {
        // to collect errors, warnings etc.
        DiagnosticCollector<JavaFileObject> diagnostics =
            new DiagnosticCollector<JavaFileObject>();

        // create a new memory JavaFileManager
        MemoryJavaFileManager fileManager = new MemoryJavaFileManager(stdManager);

        // prepare the compilation unit
        List<JavaFileObject> compUnits = new ArrayList<JavaFileObject>(1);
        compUnits.add(fileManager.makeStringSource(fileName, source));

        return compile(compUnits, fileManager, err, sourcePath, classPath);
    }

    private Map<String, byte[]> compile(final List<JavaFileObject> compUnits,
        final MemoryJavaFileManager fileManager,
        Writer err, String sourcePath, String classPath) {
        // to collect errors, warnings etc.
        DiagnosticCollector<JavaFileObject> diagnostics =
            new DiagnosticCollector<JavaFileObject>();

        // javac options
        List<String> options = new ArrayList<String>();
        options.add("-Xlint:all");
        //      options.add("-g:none");
        options.add("-deprecation");
        if (sourcePath != null) {
            options.add("-sourcepath");
            options.add(sourcePath);
        }

        if (classPath != null) {
            options.add("-classpath");
            options.add(classPath);
        }

        // create a compilation task
        javax.tools.JavaCompiler.CompilationTask task =
            tool.getTask(err, fileManager, diagnostics,
                options, null, compUnits);

        if (task.call() == false) {
            PrintWriter perr = new PrintWriter(err);
            for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
                perr.println(diagnostic);
            }
            perr.flush();
            return null;
        }

        Map<String, byte[]> classBytes = fileManager.getClassBytes();
        try {
            fileManager.close();
        } catch (IOException exp) {
        }

        return classBytes;
    }
}

MemoryJavaFileManager.java
package me.soulmachine.compiler;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;

/**
 * JavaFileManager that keeps compiled .class bytes in memory.
 */
@SuppressWarnings("unchecked")
final class MemoryJavaFileManager extends ForwardingJavaFileManager {

    /** Java source file extension. */
    private final static String EXT = ".java";

    private Map<String, byte[]> classBytes;

    public MemoryJavaFileManager(JavaFileManager fileManager) {
        super(fileManager);
        classBytes = new HashMap<>();
    }

    public Map<String, byte[]> getClassBytes() {
        return classBytes;
    }

    public void close() throws IOException {
        classBytes = null;
    }

    public void flush() throws IOException {
    }

    /**
     * A file object used to represent Java source coming from a string.
     */
    private static class StringInputBuffer extends SimpleJavaFileObject {
        final String code;

        StringInputBuffer(String fileName, String code) {
            super(toURI(fileName), Kind.SOURCE);
            this.code = code;
        }

        public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
            return CharBuffer.wrap(code);
        }
    }

    /**
     * A file object that stores Java bytecode into the classBytes map.
     */
    private class ClassOutputBuffer extends SimpleJavaFileObject {
        private String name;

        ClassOutputBuffer(String name) {
            super(toURI(name), Kind.CLASS);
            this.name = name;
        }

        public OutputStream openOutputStream() {
            return new FilterOutputStream(new ByteArrayOutputStream()) {
                public void close() throws IOException {
                    out.close();
                    ByteArrayOutputStream bos = (ByteArrayOutputStream)out;
                    classBytes.put(name, bos.toByteArray());
                }
            };
        }
    }

    public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
        String className,
        Kind kind,
        FileObject sibling) throws IOException {
        if (kind == Kind.CLASS) {
            return new ClassOutputBuffer(className);
        } else {
            return super.getJavaFileForOutput(location, className, kind, sibling);
        }
    }

    static JavaFileObject makeStringSource(String fileName, String code) {
        return new StringInputBuffer(fileName, code);
    }

    static URI toURI(String name) {
        File file = new File(name);
        if (file.exists()) {
            return file.toURI();
        } else {
            try {
                final StringBuilder newUri = new StringBuilder();
                newUri.append("mfm:///");
                newUri.append(name.replace('.', '/'));
                if(name.endsWith(EXT)) newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT);
                return URI.create(newUri.toString());
            } catch (Exception exp) {
                return URI.create("mfm:///com/sun/script/java/java_source");
            }
        }
    }
}

MemoryClassLoader.java
package me.soulmachine.compiler;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * ClassLoader that loads .class bytes from memory.
 */
final class MemoryClassLoader extends URLClassLoader {
    private Map<String, byte[]> classBytes;

    public MemoryClassLoader(Map<String, byte[]> classBytes,
        String classPath, ClassLoader parent) {
        super(toURLs(classPath), parent);
        this.classBytes = classBytes;
    }

    public MemoryClassLoader(Map<String, byte[]> classBytes, String classPath) {
        this(classBytes, classPath, ClassLoader.getSystemClassLoader());
    }

    public MemoryClassLoader(Map<String, byte[]> classBytes) {
        this(classBytes, null, ClassLoader.getSystemClassLoader());
    }

    public Class load(String className) throws ClassNotFoundException {
        return loadClass(className);
    }

    public Iterable<Class> loadAll() throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>(classBytes.size());
        for (String name : classBytes.keySet()) {
            classes.add(loadClass(name));
        }
        return classes;
    }

    protected Class findClass(String className) throws ClassNotFoundException {
        byte[] buf = classBytes.get(className);
        if (buf != null) {
            // clear the bytes in map -- we don't need it anymore
            classBytes.put(className, null);
            return defineClass(className, buf, 0, buf.length);
        } else {
            return super.findClass(className);
        }
    }

    private static URL[] toURLs(String classPath) {
        if (classPath == null) {
            return new URL[0];
        }

        List<URL> list = new ArrayList<URL>();
        StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            File file = new File(token);
            if (file.exists()) {
                try {
                    list.add(file.toURI().toURL());
                } catch (MalformedURLException mue) {}
            } else {
                try {
                    list.add(new URL(token));
                } catch (MalformedURLException mue) {}
            }
        }
        URL[] res = new URL[list.size()];
        list.toArray(res);
        return res;
    }
}

Explanations:

*

*In order to represent a  Java source file in memory instead of disk, I defined a StringInputBuffer class in the MemoryJavaFileManager.java.

*To save the compiled .class files in memory, I implemented a class MemoryJavaFileManager.  The main idea is to override the function getJavaFileForOutput() to store bytecodes into a map.

*To load the bytecodes in memory, I have to implement a customized classloader MemoryClassLoader, which reads bytecodes in the map and turn them into classes.

Here is a unite test.
package me.soulmachine.compiler;

import org.junit.Test;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import static org.junit.Assert.assertEquals;

public class MemoryJavaCompilerTest {
    private final static MemoryJavaCompiler compiler = new MemoryJavaCompiler();

    @Test public void compileStaticMethodTest()
        throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
        final String source = "public final class Solution {\n"
            + "public static String greeting(String name) {\n"
            + "\treturn \"Hello \" + name;\n" + "}\n}\n";
        final Method greeting = compiler.compileStaticMethod("greeting", "Solution", source);
        final Object result = greeting.invoke(null, "soulmachine");
        assertEquals("Hello soulmachine", result.toString());
    }
}

Reference

*

*JavaCompiler.java from Cloudera Morphlines

*How to create an object from a string in Java (how to eval a string)?

*InMemoryJavaCompiler

*Java-Runtime-Compiler

*[动态的Java - 无废话JavaCompilerAPI中文指南]

*Compile and Run Java Source Code in Memory.

A: String fileToCompile = ;
JavaCompile compiler = ToolProvider.getSystemJavaCompiler();
if(
    compiler.run(null, null, null, "PACKAGE_NAME" + java.io.File.separator +"CLASS_NAME.java") == 0
)
    System.out.println("Compilation is successful");
else
    System.out.println("Compilation Failed");

redpajama_set_name: RedPajamaStackExchange


You can reach Puerto Deportivo de Marbella by calling VHF9.
Puerto Deportivo de Marbella is located in Marbella, on the Mediterranean coast of Spain, in the province of Malaga. Marina de Marbella has 377 berths available and can accomodate yachts up to 20 m in length, with a maximum draft of 3.5 m.
Puerto Deportivo de Marbella is also known as Puerto Deportivo Maritimo de Marbella, Port of Marbella or Club Nautico de Marbella. Tourists who will choose this destination will have access to a variety of attractions, thanks to its location, between the Gibraltar Strait and the base of Sierra Blanca. This is an ideal location for water sports enthusiasts and those who are passionate about yachting.
There are 27 km of coastline and 24 beaches that offer various advantages. From a historical point of view, Marbella has a rich heritage that is proudly shared with tourists each year. The Old Town, also known as Casco Antiguo, is this city's historic extension where 10 of Salvador Dali's sculptures can be admired. Also, the Golden Mile is a fascinating, luxurious area that visitors will simply adore. Marbella's cuisine is based on seafood and most of it was borrowed from the Malagueno coast.
From helpful headlines to descriptive details, you could write the kinds of reviews travelers love a look. Kindly share your feedback regarding your experience in Puerto Deportivo de Marbella to help them improve and tell future skippers / boat owners what to expect.
We strongly advise you to check the weather in Puerto Deportivo de Marbella before your trip.
Puerto Deportivo de Marbella is located in Malaga.
This map shows Puerto Deportivo de Marbella's specific location.