/**
 * A {@link DecrossTwoLayer} heuristic for reducing the number of crossings in
 * large dags efficiently.
 *
 * @packageDocumentation
 */
import { type U } from "../../utils";
import type { Twolayer } from "../twolayer";
import { type TwolayerAgg } from "../twolayer/agg";
import { type TwolayerGreedy } from "../twolayer/greedy";
import type { Decross } from ".";
import { type DecrossDfs } from "./dfs";
/** two layer operators */
export interface DecrossTwoLayerOps<N = never, L = never> {
    /** the order operator */
    order: Twolayer<N, L>;
    /** the initializers */
    inits: readonly Decross<N, L>[];
}
/**
 * a decrossing operator that reorders by looking at pairs of layers
 *
 * This method can be very fast and is a general heuristic for efficient
 * minimization. Customize with a two layer operator with {@link order},
 * different {@link inits}, or the number of {@link passes}.
 */
export interface DecrossTwoLayer<Ops extends DecrossTwoLayerOps = DecrossTwoLayerOps> extends Decross<Ops extends DecrossTwoLayerOps<infer N, never> ? N : never, Ops extends DecrossTwoLayerOps<never, infer L> ? L : never> {
    /**
     * sets the {@link Twolayer} accessor for minimizing a layer at a time
     *
     * The {@link Twolayer} operator takes pairs of layers, and reorders one.
     * There are three built-in variants:
     * - {@link twolayerGreedy} - This takes another two-layer operator, runs it,
     *   and then afterwards performs greedy swaps of nodes to reduce the number
     *   of edge crossings further. While not perfect, it can improve the results
     *   of simpler heuristics.
     * - {@link twolayerAgg} - This aggregates the indices of ancestor nodes and
     *   orders nodes according to those aggregates. This is very fast and
     *   produces a good first-order decrossing, but is best when used in
     *   conjunction with {@link twolayerGreedy}.
     * - {@link twolayerOpt} - This is the sibling to {@link decrossOpt} that
     *   only optimizes a single layer, but otherwise has similar options. Just
     *   like full optimal decrossing, this will fail on large graphs, but also
     *   rarely produces better results than the combination of {@link
     *   twolayerGreedy} and {@link twolayerAgg}.
     *
     * (default: {@link twolayerGreedy})
     */
    order<NewOrder extends Twolayer>(val: NewOrder): DecrossTwoLayer<U<Ops, "order", NewOrder>>;
    /**
     * get the current {@link Twolayer} for ordering
     */
    order(): Ops["order"];
    /**
     * sets the initialization passes before decrossings
     *
     * For every initialization operator, this will run the two layer heuristic,
     * ultimately choosing the ordering that minimized overall crossings. For
     * this reason, only quick decrossing operators should be used, not expensive
     * ones. The empty list is treated as a singleton list with a noop operator.
     *
     * (default: `[decrossDfs(), decrossDfs().topDown(false)]`)
     */
    inits<const NewInits extends readonly Decross[]>(val: NewInits): DecrossTwoLayer<U<Ops, "inits", NewInits>>;
    /**
     * get the current initialization passes
     */
    inits(): Ops["inits"];
    /**
     * sets the number of passes to make
     *
     * More passes may take longer, but might result in a better output.
     *
     * (default: `24`)
     */
    passes(val: number): DecrossTwoLayer<Ops>;
    /**
     * get the current number of passes
     */
    passes(): number;
    /** @internal flag indicating that this is built in to d3dag and shouldn't error in specific instances */
    readonly d3dagBuiltin: true;
}
/** default two layer operator */
export type DefaultDecrossTwoLayer = DecrossTwoLayer<{
    /** default order */
    order: TwolayerGreedy<TwolayerAgg>;
    /** default inits, both dfs based */
    inits: readonly [DecrossDfs, DecrossDfs];
}>;
/**
 * create a default {@link DecrossTwoLayer}
 *
 * This operator scans over the layered representation multiple times, applying
 * a heuristic to minimize the number of crossings between two layers. This
 * makes it much faster than complete methods, and produces a reasonable layout
 * in most cases, but there are some simply edge crossings that it won't
 * remove.
 *
 * It can be altered by setting both the heuristic it uses to
 * {@link DecrossTwoLayer#order} the nodes in a single layer to minimize edge
 * crossings, as well as the different {@link DecrossTwoLayer#inits} before
 * applying the two-layer heuristic. You can also tweak how many
 * {@link DecrossTwoLayer#passes} it runs. More can produce a better layout,
 * but may take longer.
 *
 * @example
 *
 * ```ts
 * const layout = sugiyama().decross(decrossTwoLayer());
 * ```
 */
export declare function decrossTwoLayer(...args: never[]): DefaultDecrossTwoLayer;
