Online portfolio selection: the family, the geometry, the set and the state: private API

PortfolioOptimisers.budget_or_held_step — Function
budget_or_held_step(
    wn::AbstractVector,
    w::AbstractVector,
    proj::AbstractProjectionGeometry,
    set::AbstractAllocationSet
) -> Any

Returns the projected allocation wn when it meets the budget, and the Held Step otherwise.

A root found from the kinks is exact on every input whose kinks floating point can hold. The root of a barrier geometry can lose its budget to cancellation, when a base is far larger than the step it restores. This function catches that loss, so no allocation off the budget reaches the rule.

Algorithm

  1. When isapprox(sum(wn), 1) holds, return wn. The default tolerance of isapprox is a relative error of sqrt(eps) of the element type, 1.49e-8 for Float64.
  2. Otherwise, record a Held Step on the current ProjectionStep with record_held_step!. Its reason names the set, the geometry and the sum, and it has no solver trials.
  3. Return a copy of w, as a failed projection_programme does.

Arguments

  • wn: The projected allocation.
  • w: The Price-Adjusted Allocation the step trades from.
  • proj: The geometry, named in the record.
  • set: The set, named in the record.

Returns

  • w'::Vector: wn, or w copied on a Held Step.

Related

source
PortfolioOptimisers.bounded_quadratic_projection — Function
bounded_quadratic_projection(
    q::AbstractVector,
    wb::WeightBounds
) -> Any
bounded_quadratic_projection(
    q::AbstractVector,
    wb::WeightBounds,
    h::AbstractVector
) -> Any

Projects a raw step onto a bounded set in the norm of a positive diagonal h, at the exact root of the budget.

At h = 1, the default, it is the Euclidean arm of project off the simplex bounds. With the gradient mass of AdaptiveSubgradient in h, it is the DiagonalProjection on every bound.

Mathematical definition

\[\begin{align} \boldsymbol{w}^{+} &= \underset{\boldsymbol{w} \in \mathcal{W}}{\arg\min} \; \tfrac{1}{2} \sum_i h_i (w_i - q_i)^2\,, \\ w_i(\theta) &= \min\left(\max\left(q_i - \theta / h_i,\, l_i\right),\, u_i\right)\,. \end{align}\]

Where:

  • $\boldsymbol{w}^{+}$: Projected allocation, the answer of the projection onto the Allocation Set.
  • $\mathcal{W}$: Allocation Set.
  • $\boldsymbol{h}$: Positive diagonal of the norm, one entry for each asset.
  • $\boldsymbol{q}$: Raw step, the vector the rule's unconstrained step gives before the projection onto the Allocation Set.
  • $l_i$, $u_i$: Lower and upper bounds of asset $i$ on a BoundedAllocationSet.
  • $\theta$: Budget multiplier, the root of $\sum_i w_i(\theta) = 1$.

The projection is $\boldsymbol{w}(\theta)$ at the root. The budget $\sum_i w_i(\theta)$ does not increase in $\theta$, and it is linear between the kinks at $h_i (q_i - u_i)$ and $h_i (q_i - l_i)$, so the line through the two kinks that bracket the root gives the root exactly.

Algorithm

  1. Refuse a non-finite q with assert_finite_raw_step, and bounds that no allocation on the budget satisfies with assert_feasible_bounds.
  2. Find theta, the root of sum(clamp.(q .- theta ./ h, lb, ub)) at one, with breakpoint_root over the kinks h .* (q .- ub) and h .* (q .- lb).
  3. Return clamp.(q .- theta ./ h, lb, ub).

Arguments

  • q: The raw step.
  • wb: The resolved bounds.
  • h: The diagonal of the norm, positive.

Validation

  • all(isfinite, q). A DomainError is thrown otherwise.
  • Σ lb ≤ 1 ≤ Σ ub over the resolved bounds. An ArgumentError is thrown otherwise.

Returns

  • w'::Vector: The projected allocation, a new vector.

Related

source
PortfolioOptimisers.breakpoint_root — Function
breakpoint_root(f, x::AbstractVector) -> Any

Finds, from its kinks x, the point at which a non-increasing, piecewise linear budget function f crosses one.

The Euclidean, diagonal and entropic projections onto a bounded set each clip the raw step at one scalar. The budget is linear in that scalar between the kinks at which an asset reaches a bound, so the line through the two kinks that bracket the root gives the root exactly. The search reads the kinks and not the width of a bracket, so a raw step whose entries span hundreds of binades is as exact as a step near the simplex. A kink at an infinite bound is not a kink, and the budget is linear past the last finite kink.

Algorithm

  1. Drop the non-finite kinks and sort the rest, giving x. When no kink is left, use the one kink 0.
  2. Search the indices of x by bisection for lo, the last kink at which f is at least one, and hi = lo + 1. The index 0 stands for the linear tail below the first kink, and the index length(x) + 1 for the tail above the last kink.
  3. Take the segment (a, b) that holds the root with breakpoint_segment.
  4. When f(a) == f(b), return a. Otherwise, return the point at which the line through (a, f(a)) and (b, f(b)) crosses one.

Arguments

  • f: The budget as a function of the scalar, non-increasing and linear between kinks.
  • x: The kinks. The non-finite ones are dropped.

Returns

  • r: The scalar at which f crosses one.

Related

source
PortfolioOptimisers.breakpoint_segment — Function
breakpoint_segment(
    x::AbstractVector,
    lo::Integer,
    hi::Integer
) -> Tuple{Any, Any}

Returns the segment of the budget of breakpoint_root that holds the root, from the kinks x[lo] and x[hi].

An index past either end of x stands for a linear tail. The second point on a tail lies beyond the outer kink by the magnitude of that kink, and by at least one.

Algorithm

  1. When lo == 0, return (x[1] - max(1, abs(x[1])), x[1]).
  2. When hi > length(x), return (x[end], x[end] + max(1, abs(x[end]))).
  3. Otherwise, return (x[lo], x[hi]).

Related

source
PortfolioOptimisers.bounded_root — Function
bounded_root(f, lo, hi) -> Any

Finds the point on [lo, hi] at which a non-increasing budget function f crosses one, by bisection until the bracket collapses to adjacent floating-point values.

The projection of a barrier geometry onto a bounded set clips the raw step at one scalar. The budget is monotone in that scalar but not linear, so the function bisects it. bisection_cap of the type of the bracket caps the number of halvings. The cap is not less than the number of halvings in which a bracket over the whole range of the type collapses, so no bracket stops before it reaches its resolution. The midpoint is lo / 2 + hi / 2, which does not overflow on a bracket near floatmax.

Algorithm

  1. Take the midpoint mid = lo / 2 + hi / 2. Stop when mid equals lo or hi, because the bracket then holds two adjacent values.
  2. Set lo = mid when f(mid) >= 1, and hi = mid otherwise.
  3. Repeat steps 1 and 2, at most bisection_cap times.
  4. Return lo / 2 + hi / 2.

Arguments

  • f: The budget as a function of the scalar, non-increasing.
  • lo, hi: A bracket with f(lo) ≥ 1 ≥ f(hi).

Returns

  • x: The scalar at which f crosses one.

Related

source
PortfolioOptimisers.bisection_cap — Function
bisection_cap(::Type{T}) where {T <: AbstractFloat}
bisection_cap(::Type)

Returns a number of halvings that is enough for any bisection bracket of type T to collapse to adjacent values of T.

Mathematical definition

\[\begin{align} c(T) &= e_{\max}(T) - e_{\min}(T) + 2 p(T)\,. \end{align}\]

Where:

  • $c(T)$: Cap on the halvings for the type $T$.
  • $e_{\max}(T)$, $e_{\min}(T)$: Exponents of floatmax(T) and floatmin(T). Their difference counts the normal binades of $T$.
  • $p(T)$: Precision of $T$ in bits. Twice the precision covers the significand and the subnormal binades below floatmin(T).

The cap is 2151 for Float64, 301 for Float32 and 51 for Float16. The widest bracket, [-floatmax(T), floatmax(T)], collapses at the smallest subnormal after 2099, 278 and 41 halvings, so the cap is an upper bound and not the exact count.

The cap only guards bounded_root. On a floating-point type the collapse check stops the loop first. Any other type takes the cap of Float64, and the loop does not need a tight cap there. An AD dual and a quantity with units compare by their values, so the collapse check still stops the loop. A Rational bracket never collapses, so no cap comes from it, and a Rational{Int} bracket overflows its integers after about sixty halvings.

Related

source
PortfolioOptimisers.project_simplex — Function
project_simplex(v::AbstractVector) -> Any

Projects a vector onto the probability simplex in Euclidean distance, by the sort of Duchi, Shalev-Shwartz, Singer and Chandra (2008).

Mathematical definition

\[\begin{align} \boldsymbol{w}^{+} &= \underset{\boldsymbol{w} \in \Delta_N}{\arg\min} \; \tfrac{1}{2} \lVert \boldsymbol{w} - \boldsymbol{v} \rVert_2^2\,, \\ w^{+}_i &= \max(v_i - \theta, 0)\,, \\ \rho &= \max \left\lbrace j : u_j - \frac{1}{j} \left( \sum_{k \leq j} u_k - 1 \right) > 0 \right\rbrace\,, \\ \theta &= \frac{1}{\rho} \left( \sum_{k \leq \rho} u_k - 1 \right)\,. \end{align}\]

Where:

  • $\boldsymbol{w}^{+}$: Projected allocation, the answer of the projection onto the Allocation Set.
  • $\Delta_N$: Probability simplex over the $N$ assets.
  • $\boldsymbol{v}$: Vector to project.
  • $\theta$: Budget multiplier, the root of $\sum_i w_i(\theta) = 1$.
  • $\rho$: Number of positive entries of the projection.
  • $\boldsymbol{u}$: Entries of $\boldsymbol{v}$ in decreasing order.

The entries of $\boldsymbol{v}$ below $\theta$ become exactly zero. That is the sparsity of every rule under the Euclidean geometry.

A non-negative $\boldsymbol{v}$ whose sum misses one by rounding alone is on the simplex already, and the projection renormalises it:

\[\begin{align} \boldsymbol{w}^{+} &= \frac{\boldsymbol{v}}{s} \quad \text{if } \boldsymbol{v} \geq 0 \text{ and } \lvert s - 1 \rvert \leq (N + 1) \varepsilon\,,\quad s = \boldsymbol{1}^\intercal \boldsymbol{v}\,. \end{align}\]

Where:

  • $s$: Sum of the entries of $\boldsymbol{v}$.
  • $\varepsilon$: Machine epsilon of the element type, twice its unit roundoff $u$.

The bound $(N + 1) \varepsilon$ is budget_rounding.

The exact projection of such a vector lifts every zero entry by $(1 - s) / N$ when $s < 1$, and a later step compounds that residue as a real holding. The quotient keeps a zero exactly zero. It differs from the exact projection by at most $\lVert \boldsymbol{v} - \boldsymbol{v} / s \rVert$, because a projection is non-expansive and $\boldsymbol{v} / s$ is its own projection. That distance is within the rounding of $\boldsymbol{v}$ itself.

Algorithm

  1. Sum v, giving s. When every entry of v is non-negative and abs(s - 1) is at most budget_rounding, return v ./ s.
  2. Sort v in decreasing order, giving u.
  3. For each j, add u[j] to the running sum css and take t = (css - 1) / j. When u[j] - t > 0, set rho = j and theta = t.
  4. Return max.(v .- theta, 0).

Arguments

  • v: The vector to project.

Returns

  • w::Vector: The projection, a new vector summing to one.

Related

References

  • [177] J. Duchi, S. Shalev-Shwartz, Y. Singer and T. Chandra. Efficient projections onto the l1-ball for learning in high dimensions. In: Proceedings of the 25th International Conference on Machine Learning, 272–279 (2008).
source
PortfolioOptimisers.budget_rounding — Function
budget_rounding(::Type{T}, n::Integer) where {T <: Union{Integer, Rational}}
budget_rounding(::Type{T}, n::Integer)

Returns the rounding bound on the sum of an n-vector of type T that sums to one in exact arithmetic.

Mathematical definition

\[\begin{align} b(T, n) &= (n + 1) \varepsilon\,. \end{align}\]

Where:

  • $b(T, n)$: Bound on $\lvert \boldsymbol{1}^\intercal \boldsymbol{v} - 1 \rvert$ for a computed $\boldsymbol{v}$ of $n$ entries of type $T$.
  • $\varepsilon$: Machine epsilon of the element type, twice its unit roundoff $u$.

The bound is deterministic, to first order in $u$. The Price-Adjusted Allocation w .* x ./ ⟨w, x⟩ sums to one in exact arithmetic whatever Σ w is. Each of its entries carries a relative error of at most $(n + 2) u$: one rounding in the product, one in the quotient, and $n$ in the dot product. The pairwise sum adds at most $\lceil \log_2 n \rceil u$. The total, $(n + 2 + \lceil \log_2 n \rceil) u$, is at most $2 (n + 1) u = b(T, n)$ for every $n \geq 1$.

The probabilistic bound $\sqrt{n} \varepsilon$ holds at one step with high probability, but not at every step of a long recursion. One miss leaves a residue that later steps compound. An integer or Rational type takes zero, because its sums carry no rounding. An AD dual takes the bound of its value type, through its own eps.

Related

source
PortfolioOptimisers.HeldStep — Type
struct HeldStep{T1, T2<:AbstractString, T3}

Records a Held Step, a projection of one row that did not give an allocation on the budget, so the step traded nothing.

A projection onto a ProgrammeAllocationSet, or in a GramProjection, is a programme, and a programme can fail. It is infeasible on a day when a turnover ceiling and a cap cannot both hold. It can also time out, stop a MIP at its limit, or meet a covariance cone with no finite data on its first rows. A closed-form root can also miss the budget in floating point, as budget_or_held_step states. The step then returns the Price-Adjusted Allocation that it got, the book that the fund already holds, so the fund trades nothing. The rule's carrier still takes in the row. The head warns once with the timestamp of the row. Its Recursion Read-out carries the record of the last folded row inside an OptimisationSuccess, so a fallback chain never runs on a hold. A step never throws on a failed solve, and never falls back to a weaker set, because a constraint that the step drops on the day it binds does not constrain.

Fields

  • ts: The timestamp of the row whose projection the step held. It is the index of the row in the fold when the carrier has no timestamps, and nothing outside a fold.
  • reason: The projection of the row that the step held, and the reason.
  • trials: The solver trials of the failed programme, the trials of a JuMPResult, or nothing when the projection built no programme.

Related

source
PortfolioOptimisers.ProjectionStep — Type
struct ProjectionStep{T1, T2}

Holds the context of one row for every projection of that row: the rows carrier, the timestamp of the row, and the Held Steps recorded so far.

The projection of the Online Update is project(proj, set, q, w), with four arguments and no more. Two things must reach it outside that signature. The covariance cone and the tracking error of a programme set read the head's rows, and the head must see the record of a Held Step. Both go on the task-scoped PROJECTION_STEP. The head opens one step for each row through with_projection_step, around the whole Online Update. So every projection of that row, those of a mixture's experts and that of its blend, reads one carrier and writes one log. The carrier is the one that the update gets, a ReturnsResult of the rows as they arrived, under the pinned names and the Asset Panel of the buffer. So a programme set fits its prior through rows_carrier, as a batch head does. Outside a step, a projection reads no rows and reports a hold as a warning.

Fields

  • rows: The rows carrier that the head holds through the period, a ReturnsResult of the rows as they arrived, or nothing.
  • ts: The timestamp of the row, or the index of the row in the fold.
  • strict: The head's strict flag. A programme set reads it when it resolves its rows, so it refuses a name that an exposure row states and the universe does not carry, as the head refuses one.
  • held: The Held Steps recorded during this row, in the order in which their projections failed.

Related

source
PortfolioOptimisers.price_relative — Function
price_relative(r::Number)

Returns the price relative of one return, 1 + r, and one at a gap.

A non-finite return is a period in which the leg held cash, which is how the Held Gap reads it. So the Online Update sees a finite x at every asset, and a kernel over the rows reads the same number at the gap.

Mathematical definition

\[\begin{align} x_{tj} &= \begin{cases} 1 + r_{tj} & \text{if } r_{tj} \text{ is finite}\,, \\ 1 & \text{otherwise}\,. \end{cases} \end{align}\]

Where:

  • $x_{tj}$: Price relative of asset $j$ in period $t$.
  • $r_{tj}$: Return of asset $j$ at time $t$.

Related

source
PortfolioOptimisers.assert_rule_admits_set — Function
assert_rule_admits_set(alg::AbstractOnlinePortfolioSelectionAlgorithm, set::AbstractAllocationSet)

Refuses, when the head is built, a rule and an Allocation Set that cannot work together.

The default admits every pair. A rule that holds an optimisation estimator with no model for a programme set, such as FollowTheLeader, refuses that set by name. A rule over other rules sends the check to each of them.

Related

source
PortfolioOptimisers.rule_state_view — Function
rule_state_view(st::Nothing, i, args...)
rule_state_view(st::AbstractPartialFitState, i, args...)
rule_state_view(st, i, args...)

Slices a rule's carrier to the selected assets.

A nothing carrier stays nothing. A carrier that subtypes AbstractPartialFitState goes to its own port_opt_view. The function refuses any other carrier.

Validation

Related

source
PortfolioOptimisers.price_adjusted_allocation — Function
price_adjusted_allocation(
    w::AbstractVector,
    x::AbstractVector
) -> Any

Returns the Price-Adjusted Allocation, the book that the fund holds at the end of a period before it trades.

It is one row of the self-financing Weight Drift at budget one. Every trade of the family starts from it. The update of BuyAndHold returns this vector, a turnover ceiling on a ProgrammeAllocationSet bounds the distance from it, and every projection gets it as its w argument.

Mathematical definition

\[\begin{align} \hat{\boldsymbol{w}}_t &= \frac{\boldsymbol{w}_t \odot \boldsymbol{x}_t}{\boldsymbol{w}_t^\intercal \boldsymbol{x}_t}\,. \end{align}\]

Where:

  • $\hat{\boldsymbol{w}}_t = \boldsymbol{w}_t \odot \boldsymbol{x}_t / \langle \boldsymbol{w}_t, \boldsymbol{x}_t \rangle$: Price-Adjusted Allocation, the wealth held in each asset at the end of period $t$.
  • $\boldsymbol{w}_t$: Iterate of the rule at period $t$, the allocation its update reads.
  • $\boldsymbol{x}_t$: Price relative vector of period $t$, each asset's price over its price one period earlier.
  • $\odot$: Elementwise product.

Arguments

  • w: The allocation held during the period.
  • x: The price relative of the period.

Returns

  • ŵ::Vector: The price-adjusted allocation, a new vector.

Related

source
PortfolioOptimisers.project_start — Function
project_start(
    proj::AbstractProjectionGeometry,
    set::Union{Nothing, AbstractAllocationSet},
    w::AbstractVector
) -> Any

Projects a start allocation w once onto the Allocation Set set in the geometry proj, with w as its own reference.

The head projects its Start Allocation with this function, and so does each expert of an ExpertMixture or a FollowTheLeadingHistory. So the allocation held during the first period lies in the set. When set is nothing, or when it reads the head's rows and so has no constraints before the first row, the function returns w as it is, and the first Online Update projects it.

Related

source
PortfolioOptimisers.OnlinePortfolioSelectionState — Type
struct OnlinePortfolioSelectionState{__T_n, __T_w, __T_st, __T_X, __T_nx, __T_pnl, __T_amsk, __T_ts, __T_hold} <: AbstractPartialFitState

Holds the Partial Fit State of an online portfolio selection head: the Rule State, the rows, the Fold Context and every folded timestamp.

The pair (st, w) is the Rule State, the unit over which the family recurses. The state holds once the rows that any rule of the tree reads, as a SampleBufferState of returns. The buffer keeps the rows of the Returns Result as they arrived, with NaN where there was no return, and under a time-varying panel it keeps the active mask of each row beside it. rows_needed of the rule tree caps the buffer, and the buffer is nothing for a tree that reads no rows. At every row the head reads the buffer out as a ReturnsResult through rows_carrier, so a statistic over the rows reduces to its Coverage Universe as a batch fit over the same window does. No cap applies to the timestamps, so Resume works for a rule with no carrier. The active mask of the last folded row is the Investable Mask on which the read-out reduces, and it is nothing under a static panel. The recursion keeps the full w and never carries a forced zero.

Fields

  • n: Number of observations folded into the state.
  • w: The allocation held during the current period. It covers the full pinned universe and sums to one.
  • st: The rule's private carrier, or nothing.
  • X: The rows of returns that any rule of the tree reads, a SampleBufferState of the rows as they arrived and of their active masks. rows_needed caps it. It is nothing when the tree reads no rows.
  • nx: Names of the asset columns, pinned by the first step.
  • pnl: The static AssetPanel of the universe, pinned by the first step, or nothing. The state never holds a time-varying panel here.
  • amsk: The active mask of the last folded row under a time-varying panel, which is the Investable Mask of the read-out, or nothing under a static panel.
  • ts: Timestamps of the folded observations, in order and with no cap, or nothing when the carrier holds none.
  • hold: The HeldStep record of the last folded row when the step held a projection of that row, or nothing when every projection of it met the budget. The return code of the Recursion Read-out carries it.

Constructors

OnlinePortfolioSelectionState(;    n::Integer = 0,    w::AbstractVector,    st = nothing,    X::Option{<:SampleBufferState} = nothing,    nx::Option{<:VecStr} = nothing,    pnl::Option{<:AssetPanel} = nothing,    amsk::Option{<:AbstractVector{<:Bool}} = nothing,    ts::Option{<:AbstractVector} = nothing,    hold::Option{<:HeldStep} = nothing) -> OnlinePortfolioSelectionState

Keywords correspond to the struct's fields.

Validation

  • n >= 0. A DomainError is thrown otherwise.
  • length(nx) == length(w) when nx is given, and length(amsk) == length(w) when amsk is given. A DimensionMismatch is thrown otherwise.
  • pnl is static when it is not nothing. An ArgumentError is thrown otherwise, because the buffer holds the masks of a time-varying panel with the rows.

View parameters

OnlinePortfolioSelectionState defines its own port_opt_view method rather than deriving one from field tags.

  • The method passes args... to the view of the carrier and to the view of the rows buffer.
  • w is sliced and renormalised through renormalised_view, as a copy. The recursion keeps the full w.
  • st goes to the view of the carrier through rule_state_view.
  • X, nx, pnl and amsk are sliced along the asset axis.
  • n, ts and hold pass through, and ts is copied.

Related

source
Base.copy — Method
copy(
    x::OnlinePortfolioSelectionState
) -> OnlinePortfolioSelectionState{__T_n, __T_w, _A, __T_X, __T_nx, __T_pnl, __T_amsk, __T_ts, __T_hold} where {__T_n<:Integer, __T_w<:(AbstractVector), _A, __T_X<:Union{Nothing, SampleBufferState}, __T_nx<:Union{Nothing, AbstractVector{<:AbstractString}}, __T_pnl<:Union{Nothing, AssetPanel}, __T_amsk<:Union{Nothing, AbstractVector{<:Bool}}, __T_ts<:Union{Nothing, AbstractVector}, __T_hold<:Union{Nothing, HeldStep}}

Copies an OnlinePortfolioSelectionState so that the copy shares no array with the original.

The method calls copy on w, st, X, nx, amsk and ts. A carrier and the rows buffer copy their own arrays through their Base.copy methods. n, pnl and hold pass through unchanged.

Related

source
PortfolioOptimisers.renormalised_view — Function
renormalised_view(w::Nothing, i)
renormalised_view(w::AbstractVector, i)

Slices an allocation to the selected assets and renormalises it to sum to one, as a copy. A nothing allocation stays nothing.

The function spreads the mass that the selection leaves out over the kept assets in proportion. Every per-asset view of an allocation in the family reads it this way, the read-out under a time-varying panel and the view of a rule's own allocation among them. A selection that keeps none of the mass, such as a view of a one-hot allocation to the other assets, has no proportion. It returns the uniform allocation over the kept assets, the Start Allocation of the family.

Mathematical definition

\[\begin{align} v_i &= \begin{cases} w_i \big/ \sum_{j \in I} w_j & \text{if } \sum_{j \in I} w_j \neq 0\,, \\ 1 / \lvert I \rvert & \text{otherwise}\,, \end{cases} \quad i \in I\,. \end{align}\]

Where:

  • $v_i$: Entry of the view for the kept asset $i$.
  • $w_i$: Entry of the allocation for asset $i$.
  • $I$: Set of the kept assets.

Related

source
PortfolioOptimisers.statistic_before_rate — Function
statistic_before_rate(eta, s, w::AbstractVector, x::AbstractVector)

Returns the statistic from which the rule reads the rate of the period. This is the first of the two points at which a rule writes the row of its schedule.

The row goes in here when reads_period_row returns true. Otherwise the call returns s unchanged. statistic_after_step is the other point. A rule makes both calls, and the schedule decides which one writes.

Related

source

References

[177]
J. Duchi, S. Shalev-Shwartz, Y. Singer and T. Chandra. Efficient projections onto the l1-ball for learning in high dimensions. In: Proceedings of the 25th International Conference on Machine Learning (2008); pp. 272–279.