mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-11 03:01:58 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 314afb0d9f | |||
| ebc0fb65dc | |||
| b62af21f09 | |||
| 5edbe4d3b7 | |||
| 238b6b46d4 |
+4
-2
@@ -2071,11 +2071,13 @@ pub fn fill_hole_counted(
|
||||
/// G1 fill at degree 9: whether its conditions can be met (`feasible`), and the least
|
||||
/// uniform violation of its normalized sector conditions over the heights (`margin_value`:
|
||||
/// `<= 0` where met; `margin` asks it), one quadratic programme each; or (`fill`) the fill as
|
||||
/// [`fill_hole`]'s, its degrees tried from the least up only.
|
||||
/// [`fill_hole`]'s, its degrees tried in the same order.
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
||||
#[allow(clippy::struct_excessive_bools)] // the fork's three switches and solidcore's margin
|
||||
pub struct Probe {
|
||||
/// `m_bFill`: the fill itself, from the least degree up (no degree-9 proof first).
|
||||
/// `m_bFill`: the fill itself, its degrees in [`fill_hole`]'s order: between planes 9
|
||||
/// first, and where 9 proves the conditions unmet no other (the fork's 3843ddb);
|
||||
/// beside a curved face from the least degree up.
|
||||
pub fill: bool,
|
||||
/// `m_bMargin`.
|
||||
pub margin: bool,
|
||||
|
||||
+7
-14
@@ -459,23 +459,16 @@ pub(super) fn graph_gk(
|
||||
})
|
||||
.collect();
|
||||
|
||||
// The degrees: 9 first, then up from the least. Proven unmet at 9 (the QP's
|
||||
// certificate), the sector conditions are unmet at every degree, and the search stops.
|
||||
// Else the least degree whose fill is certified, or 9's.
|
||||
// The degrees: 9 first, then up from the least, for the fill and for a probe that asks
|
||||
// it (the scale search's attempts, as the fork's 3843ddb fills them). Proven unmet at 9
|
||||
// (the QP's certificate), the sector conditions are unmet at every degree, and the
|
||||
// search stops. Else the least degree whose fill is certified, or 9's.
|
||||
let mut top: Vec<Net> = Vec::new();
|
||||
let mut top_degree = 0;
|
||||
let probe_only = probe.as_ref().is_some_and(|p| !p.fill);
|
||||
let probe_fill = probe.as_ref().is_some_and(|p| p.fill);
|
||||
let mut degrees: Vec<usize> = Vec::new();
|
||||
if probe.is_none() || probe_only {
|
||||
degrees.push(9);
|
||||
}
|
||||
let mut degrees: Vec<usize> = vec![9];
|
||||
if !probe_only {
|
||||
for d in nc..=9 {
|
||||
if d < 9 || probe_fill {
|
||||
degrees.push(d);
|
||||
}
|
||||
}
|
||||
degrees.extend(nc..9);
|
||||
}
|
||||
'degrees: for &d in °rees {
|
||||
let mono = monomials(d);
|
||||
@@ -977,7 +970,7 @@ pub(super) fn graph_gk(
|
||||
if certified_convex(&nets, &plane_sides, e, GRAPH_DEPTH)?.is_err() {
|
||||
continue;
|
||||
}
|
||||
if d == 9 && probe.is_none() {
|
||||
if d == 9 {
|
||||
top = nets;
|
||||
top_degree = d;
|
||||
continue;
|
||||
|
||||
+72
-16
@@ -316,6 +316,7 @@ pub(crate) fn bisect_thousandths<E>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::blend::blend_setback::fill_hole_counted;
|
||||
use crate::math::Vec3;
|
||||
|
||||
fn corner(radii: [f64; 3], frame: usize, concave: bool) -> (Vec<Face>, Vec<Edge>) {
|
||||
@@ -345,24 +346,24 @@ mod tests {
|
||||
fn thousandth_scales_and_attempt_budget() {
|
||||
let kernel = Kernel::default();
|
||||
for (radii, setbacks, most, want, want_solves) in [
|
||||
([2.0, 3.0, 4.0], [4.5, 4.75, 6.0], None, 1.056, 35),
|
||||
([1.0, 1.5, 2.0], [2.25, 2.375, 3.0], None, 1.056, 35),
|
||||
([2.0, 3.0, 4.0], [4.5, 4.75, 6.0], None, 1.056, 22),
|
||||
([1.0, 1.5, 2.0], [2.25, 2.375, 3.0], None, 1.056, 26),
|
||||
(
|
||||
[2.0, 3.0, 4.0],
|
||||
[4.5, 4.75, 4.5],
|
||||
Some([20.0, 20.0, 4.5]),
|
||||
1.046,
|
||||
39,
|
||||
21,
|
||||
),
|
||||
([2.0, 3.0, 4.0], [4.25; 3], None, 1.110, 34),
|
||||
([5.0; 3], [8.0; 3], None, 1.0, 2),
|
||||
([2.0, 3.0, 4.0], [4.25; 3], None, 1.110, 30),
|
||||
([5.0; 3], [8.0; 3], None, 1.0, 3),
|
||||
// Every edge held at its original setback: no scale can certify.
|
||||
(
|
||||
[2.0, 3.0, 4.0],
|
||||
[4.5, 4.75, 6.0],
|
||||
Some([4.5, 4.75, 6.0]),
|
||||
0.0,
|
||||
10,
|
||||
2,
|
||||
),
|
||||
] {
|
||||
let (faces, edges) = corner(radii, 0, false);
|
||||
@@ -385,26 +386,27 @@ mod tests {
|
||||
);
|
||||
assert_eq!(result.scale, want);
|
||||
assert!(result.attempts <= 12);
|
||||
assert_eq!(result.solves, want_solves, "SMLib 20b1c01 QP count");
|
||||
// Degree 9 first, as the corner's own fill: an attempt that degree 9 proves
|
||||
// unmet solves that one programme (the fork's 3843ddb solves as many).
|
||||
assert_eq!(result.solves, want_solves, "QP count");
|
||||
assert!(result.qp_rows_built > 0);
|
||||
assert!(result.qp_peak_rows_held <= result.qp_rows_built);
|
||||
assert!(result.qp_steps >= result.solves);
|
||||
// Work budgets leave room for floating-point branch differences while
|
||||
// rejecting the former full matrices (up to 693,051 retained rows).
|
||||
// rejecting the former full matrices (up to 693,051 retained rows) and the
|
||||
// degrees below 9 a failing attempt tried (#2929: on aarch64 the fork's 20b1c01
|
||||
// took 120,513 steps in one degree-7 programme of the first corner).
|
||||
assert!(result.qp_rows_built <= 12_000_000);
|
||||
assert!(result.qp_peak_rows_held <= 16_000);
|
||||
// Known failure on aarch64 (tangency-labs/solidcore#2929): the first corner finds
|
||||
// the same scale in the same attempts and solves, but its QP takes 129,085 steps
|
||||
// there. Every other assertion here runs on both targets.
|
||||
if cfg!(not(target_arch = "aarch64")) {
|
||||
assert!(result.qp_steps <= 25_000);
|
||||
}
|
||||
assert!(result.qp_steps <= 25_000);
|
||||
if want == 1.0 {
|
||||
// The r=5, setback=8 corner needs no scale search. Its dense
|
||||
// programme built 430,962 rows and retained 254,037 at peak.
|
||||
// programme built 430,962 rows and retained 254,037 at peak. Its one
|
||||
// attempt solves degree 9 before the least degree that certifies: three
|
||||
// programmes, 22 steps on x86-64.
|
||||
assert!(result.qp_rows_built <= 10_000);
|
||||
assert!(result.qp_peak_rows_held <= 2_000);
|
||||
assert!(result.qp_steps <= 16);
|
||||
assert!(result.qp_steps <= 32);
|
||||
}
|
||||
assert_eq!(
|
||||
result.attempts,
|
||||
@@ -420,6 +422,60 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// A search attempt fills its model as the corner's own fill does (`fill_hole_counted`):
|
||||
/// degree 9 first, then up from the least degree. An attempt whose degree 9 proves the
|
||||
/// sector conditions unmet stops there with that one programme, its verdict that of every
|
||||
/// degree by degree raising (#2929: from the least degree up, each failing attempt of the
|
||||
/// first corner solved five, and on aarch64 one of degree 7 took 120,513 steps).
|
||||
#[test]
|
||||
fn search_attempts_fill_as_the_corner_does() {
|
||||
let kernel = Kernel::default();
|
||||
let (faces, edges) = corner([2.0, 3.0, 4.0], 0, false);
|
||||
let setbacks = [4.5, 4.75, 6.0];
|
||||
let model = Model {
|
||||
kernel: &kernel,
|
||||
faces: &faces,
|
||||
edges: &edges,
|
||||
setbacks: &setbacks,
|
||||
most: None,
|
||||
size: setbacks.iter().copied().fold(0.0, f64::max),
|
||||
};
|
||||
// 1 fails (the search's first attempt), 1.056 is the least scale that certifies
|
||||
for (k, certifies) in [(1.0, false), (1.056, true)] {
|
||||
let mut search = FillStats::default();
|
||||
assert_eq!(model.run(k, None, &mut search).unwrap(), certifies);
|
||||
let ks = model.at(k).unwrap();
|
||||
let surfaces: Vec<Surface> = model_rounds(&faces, &edges, &ks)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(Surface::from)
|
||||
.collect();
|
||||
let rounds: Vec<Round<'_>> = surfaces
|
||||
.iter()
|
||||
.zip(&ks)
|
||||
.map(|(surface, &end)| Round {
|
||||
surface,
|
||||
along: SurfParamType::U,
|
||||
end,
|
||||
corner_above: false,
|
||||
})
|
||||
.collect();
|
||||
let tol = 1.0e-9 * (1.0 + k * model.size);
|
||||
let mut own = FillStats::default();
|
||||
let fill = fill_hole_counted(&kernel, &faces, &rounds, 1, tol, &mut own);
|
||||
println!(
|
||||
"scale {k} search solves {} steps {} own solves {} steps {}",
|
||||
search.solves, search.qp_steps, own.solves, own.qp_steps
|
||||
);
|
||||
assert_eq!(fill.is_ok(), certifies, "scale {k}");
|
||||
assert_eq!(search.solves, own.solves, "scale {k}");
|
||||
assert_eq!(search.qp_steps, own.qp_steps, "scale {k}");
|
||||
if !certifies {
|
||||
assert_eq!(search.solves, 1, "degree 9's proof ends the attempt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Separate expensive run mode, as requested by the handoff. Seventeen descriptions
|
||||
/// cover axis permutations, concavity, scale changes and room-limited growth.
|
||||
/// The smallest certifying scale on the grid whose neighbour below fails;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# blend.blend_setback: the scale search's attempts fill degree 9 first, as the corner's fill does (2026-11-07)
|
||||
|
||||
- **Unit:** the setback fill (`blend::blend_setback`, no plan unit); its scale search `certified_scale` (`blend_setback/scale.rs`) and the degree loop of `graph_gk` (`blend_setback/graph.rs`).
|
||||
- **Problem (#2929):** `thousandth_scales_and_attempt_budget` took 129,085 QP steps on aarch64 for its first corner (rounds 2, 3, 4; setbacks 4.5, 4.75, 6), against a budget of 25,000 and 9,347 on x86-64; scale, attempts and QP count were right.
|
||||
- **Cause:** each attempt of the search fills its model with `Probe { fill: true }`, and `graph_gk` tried that probe's degrees from 3 up to 9, while the corner's own fill tries 9 first and stops where 9 proves the sector conditions unmet (#2344(b) as ruled; the streamed rows of #2783 kept the probe's order). A failing attempt so solved five programmes where one decides. On aarch64 one of them, of degree 7, took 120,513 of the 129,085 steps and ended unproven before degree 9 proved the conditions unmet (#2344's brief, the fork's 20b1c01, which counts there as main does).
|
||||
|
||||

|
||||
|
||||
*Look at the second row: a failing attempt now stops at degree 9's proof. A certifying attempt solves degree 9 first, one programme more.*
|
||||
|
||||
- **Change:** one degree order for the fill and the search's probe: 9 first, a certified 9 kept while the least certifying degree is sought, stop on 9's proof.
|
||||
- **Why the verdict is the same:** conditions met at degree d are met at d + 1 (a height function of degree d is one of degree d + 1, and the raised Bernstein coefficients of `l`, `m`, `n` are convex combinations of the old), so conditions proven unmet at 9 are unmet at every lower degree.
|
||||
- **Where it can differ: the fold refusal.** `patch_curvatures` refuses the fill as folding where the sign of the projection's `o` is not certified, at the first degree that reaches it. A sign certified at a lower degree stays certified at 9 (its raised coefficients are convex combinations), so a fold at 9 is a fold below; the converse is not shown. Where a lower degree's sign fails and 9's holds, the old order refused the attempt, and so the corner, while the new one goes on to the programmes. No such corner is known: the scale tests and `setback_monotone_grid` (17 corners, each on its grid of scales) give every verdict and scale as before.
|
||||
- **Not changed: the curved fill.** Beside a curved face the fill keeps its own loop, least degree first (`curved.rs`); its conditions and its growth's trials are another construction, and degree raising is not argued there.
|
||||
- **Counts (x86-64, `cargo test --profile goldens -p solidcore --lib blend_setback::scale::tests -- --nocapture`), QPs and steps before → after:**
|
||||
- rounds 2, 3, 4 (1.056): 35 → 22, 9,347 → 6,537;
|
||||
- rounds 1, 1.5, 2 (1.056): 35 → 26, 10,137 → 8,089;
|
||||
- upright held at 4.5 (1.046): 39 → 21, 12,635 → 8,194;
|
||||
- asked 4.25 (1.110): 34 → 30, 8,025 → 7,150;
|
||||
- r 5 set back 8 (1): 2 → 3, 4 → 22 (degree 9 first costs a certifying attempt one programme);
|
||||
- every edge held (refused): 10 → 2, 2,590 → 1,324.
|
||||
- "Before" is main at a445bdaac, "after" the change on it; the "after" counts equal the fork's 3843ddb on x86-64.
|
||||
- **Open:**
|
||||
- Step counts stay platform-dependent: only libm differs by target on this path, as far as read (the fan's `cos`/`sin`, the kernel direction's `atan2`, the Givens rotations' `hypot`); the fork's 3843ddb counts 6,425 steps for the first corner on aarch64 against 6,537 here.
|
||||
- An attempt whose degree 9 ends unproven still tries 3 to 8, so a long unproven dual run like the degree-7 one stays reachable.
|
||||
- The feasibility and margin probe modes are unused (#2344(b): "probes deleted").
|
||||
- **State:** fixed in the search's order; the aarch64 counts after the change are unmeasured here.
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="820" height="450" viewBox="0 0 820 450">
|
||||
<title>2929-degree-order</title>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<rect id="background" x="0" y="0" width="820" height="450" fill="#ffffff"/>
|
||||
<text transform="matrix(1 0 0 1 20 36)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="20" font-weight="bold" fill="#000000"><tspan x="0" y="0">One attempt of the setback scale search: the degrees it solves</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 20 92)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">A failing attempt, least degree first (main)</tspan></text>
|
||||
<rect x="360" y="70" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="412" y="70" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="464" y="70" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="516" y="70" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="568" y="70" width="44" height="32" fill="#ffffff" stroke="#1f6fb2" stroke-width="3" stroke-miterlimit="10"/>
|
||||
<rect x="620" y="70" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="672" y="70" width="44" height="32" fill="#f0f0f0" stroke="#555555" stroke-width="3" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 382 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">3</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 434 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">4</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 486 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">5</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 538 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">6</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 590 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">7</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 642 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">8</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 694 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">9</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 730 91)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">5 QPs</tspan></text>
|
||||
<line x1="590" y1="102" x2="590" y2="114" fill="none" stroke="#555555" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 360 127)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">degree 7: 120,513 steps on aarch64, ends unproven (fork 20b1c01)</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 20 172)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">A failing attempt, degree 9 first (this PR)</tspan></text>
|
||||
<rect x="360" y="150" width="44" height="32" fill="#f0f0f0" stroke="#555555" stroke-width="3" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 382 171)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">9</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 416 171)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">proven unmet: the attempt stops</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 730 171)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">1 QP</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 20 252)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">A certifying attempt, least degree first (main)</tspan></text>
|
||||
<rect x="360" y="230" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="412" y="230" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="464" y="230" width="44" height="32" fill="#dce9f5" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 382 251)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">3</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 434 251)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">…</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 486 251)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">d</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 520 251)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">the least degree that certifies</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 730 251)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">up to d</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 20 332)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">A certifying attempt, degree 9 first (this PR)</tspan></text>
|
||||
<rect x="360" y="310" width="44" height="32" fill="#dce9f5" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="412" y="310" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="464" y="310" width="44" height="32" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<rect x="516" y="310" width="44" height="32" fill="#dce9f5" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 382 331)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">9</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 434 331)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">3</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 486 331)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">…</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 538 331)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000" text-anchor="middle"><tspan x="0" y="0">d</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 360 358)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">9 certified, kept while the least degree is sought</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 730 331)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="14" fill="#000000"><tspan x="0" y="0">one QP more</tspan></text>
|
||||
<rect x="20" y="384" width="20" height="16" fill="#ffffff" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 46 397)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">a degree tried</tspan></text>
|
||||
<rect x="150" y="384" width="20" height="16" fill="#ffffff" stroke="#1f6fb2" stroke-width="3" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 176 397)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">the long unproven run</tspan></text>
|
||||
<rect x="320" y="384" width="20" height="16" fill="#f0f0f0" stroke="#555555" stroke-width="3" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 346 397)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">proven unmet</tspan></text>
|
||||
<rect x="450" y="384" width="20" height="16" fill="#dce9f5" stroke="#000000" stroke-miterlimit="10"/>
|
||||
<text transform="matrix(1 0 0 1 476 397)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">certified</tspan></text>
|
||||
<text transform="matrix(1 0 0 1 20 432)" x="0" y="0" xml:space="preserve" font-family="Helvetica, sans-serif" font-size="12" fill="#000000"><tspan x="0" y="0">Raising the degree keeps met sector conditions met, so conditions proven unmet at 9 are unmet at every lower degree.</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
+4801
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user