Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sheet setting to disable symbolic expression simplification #233

Merged
merged 5 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions public/dimensional_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ class StatementsAndSystems(TypedDict):
statements: list[InputStatement]
systemDefinitions: list[SystemDefinition]
customBaseUnits: NotRequired[CustomBaseUnits]
simplifySymbolicExpressions: bool

def is_code_function_query_statement(statement: InputAndSystemStatement) -> TypeGuard[CodeFunctionQueryStatement]:
return statement.get("isCodeFunctionQuery", False)
Expand Down Expand Up @@ -1680,19 +1681,27 @@ def subs_wrapper(expression: Expr, subs: dict[str, str] | dict[str, Expr | float
return cast(Expr, expression.xreplace(subs))


def get_evaluated_expression(expression: Expr, parameter_subs: dict[Symbol, Expr]) -> tuple[ExprWithAssumptions, str | list[list[str]]]:
def get_evaluated_expression(expression: Expr,
parameter_subs: dict[Symbol, Expr],
simplify_symbolic_expressions: bool) -> tuple[ExprWithAssumptions, str | list[list[str]]]:
expression = cast(Expr, expression.xreplace(parameter_subs))
expression = replace_placeholder_funcs(expression, "sympy_func")
expression = cast(Expr, expression.doit())
if not is_matrix(expression):
symbolic_expression = custom_latex(cancel(expression))
if simplify_symbolic_expressions:
symbolic_expression = custom_latex(cancel(expression))
else:
symbolic_expression = custom_latex(expression)
else:
symbolic_expression = []
for i in range(expression.rows):
row = []
symbolic_expression.append(row)
for j in range(expression.cols):
row.append(custom_latex(cancel(expression[i,j])))
if simplify_symbolic_expressions:
row.append(custom_latex(cancel(expression[i,j])))
else:
row.append(custom_latex(cast(Expr, expression[i,j])))

evaluated_expression = cast(ExprWithAssumptions, expression.evalf(PRECISION))
return evaluated_expression, symbolic_expression
Expand Down Expand Up @@ -1762,7 +1771,8 @@ def get_hashable_matrix_units(matrix_result: MatrixResult) -> tuple[tuple[str, .
return tuple(rows)

def evaluate_statements(statements: list[InputAndSystemStatement],
custom_base_units: CustomBaseUnits | None) -> tuple[list[Result | FiniteImagResult | list[PlotResult] | MatrixResult], dict[int,bool]]:
custom_base_units: CustomBaseUnits | None,
simplify_symbolic_expressions: bool) -> tuple[list[Result | FiniteImagResult | list[PlotResult] | MatrixResult], dict[int,bool]]:
num_statements = len(statements)

if num_statements == 0:
Expand Down Expand Up @@ -1986,7 +1996,7 @@ def evaluate_statements(statements: list[InputAndSystemStatement],
else:
expression = cast(Expr, item["expression"].doit())

evaluated_expression, symbolic_expression = get_evaluated_expression(expression, parameter_subs)
evaluated_expression, symbolic_expression = get_evaluated_expression(expression, parameter_subs, simplify_symbolic_expressions)
dimensional_analysis_expression, dim_sub_error = get_dimensional_analysis_expression(dimensional_analysis_subs, expression)

if not is_matrix(evaluated_expression):
Expand Down Expand Up @@ -2092,13 +2102,15 @@ def evaluate_statements(statements: list[InputAndSystemStatement],
return combine_plot_results(results_with_ranges[:num_statements], statement_plot_info), numerical_system_cell_unit_errors


def get_query_values(statements: list[InputAndSystemStatement], custom_base_units: CustomBaseUnits | None):
def get_query_values(statements: list[InputAndSystemStatement],
custom_base_units: CustomBaseUnits | None,
simplify_symbolic_expressions: bool):
error: None | str = None

results: list[Result | FiniteImagResult | list[PlotResult] | MatrixResult] = []
numerical_system_cell_errors: dict[int, bool] = {}
try:
results, numerical_system_cell_errors = evaluate_statements(statements, custom_base_units)
results, numerical_system_cell_errors = evaluate_statements(statements, custom_base_units, simplify_symbolic_expressions)
except DuplicateAssignment as e:
error = f"Duplicate assignment of variable {e}"
except ReferenceCycle as e:
Expand Down Expand Up @@ -2190,6 +2202,7 @@ def solve_sheet(statements_and_systems):
statements: list[InputAndSystemStatement] = cast(list[InputAndSystemStatement], statements_and_systems["statements"])
system_definitions = statements_and_systems["systemDefinitions"]
custom_base_units = statements_and_systems.get("customBaseUnits", None)
simplify_symbolic_expressions = statements_and_systems["simplifySymbolicExpressions"]

system_results: list[SystemResult] = []
equation_to_system_cell_map: dict[int,int] = {}
Expand Down Expand Up @@ -2234,7 +2247,7 @@ def solve_sheet(statements_and_systems):
error: str | None
results: list[Result | FiniteImagResult | list[PlotResult] | MatrixResult]
numerical_system_cell_errors: dict[int, bool]
error, results, numerical_system_cell_errors = get_query_values(statements, custom_base_units)
error, results, numerical_system_cell_errors = get_query_values(statements, custom_base_units, simplify_symbolic_expressions)

# If there was a numerical solve, check to make sure there were not unit mismatches
# between the lhs and rhs of each equality in the system
Expand Down
22 changes: 17 additions & 5 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
SkipToContent,
HeaderUtilities,
HeaderGlobalAction,
Checkbox,
Content,
SideNav,
SideNavMenuItem,
Expand Down Expand Up @@ -827,7 +828,12 @@

statements.push(...endStatements);

return {statements: statements, systemDefinitions: systemDefinitions, customBaseUnits: $config.customBaseUnits};
return {
statements: statements,
systemDefinitions: systemDefinitions,
customBaseUnits: $config.customBaseUnits,
simplifySymbolicExpressions: $config.simplifySymbolicExpressions
};
}

function checkParsingErrors() {
Expand Down Expand Up @@ -1087,9 +1093,8 @@ Please include a link to this sheet in the email to assist in debugging the prob
// old documents in database will not have the insertedSheets property or a config property
$insertedSheets = sheet.insertedSheets ?? [];
$config = sheet.config ?? getDefaultConfig();
if (!$config.customBaseUnits) {
$config.customBaseUnits = getDefaultBaseUnits();
}
$config.customBaseUnits = $config.customBaseUnits ?? getDefaultBaseUnits(); // customBaseUnits may not exist
$config.simplifySymbolicExpressions = $config.simplifySymbolicExpressions ?? true; // simplifySymboicExpressions may not exist

if (!$history.map(item => item.hash !== "file" ? getSheetHash(new URL(item.url)) : "").includes(getSheetHash(window.location))) {
$history = requestHistory;
Expand Down Expand Up @@ -2614,7 +2619,9 @@ Please include a link to this sheet in the email to assist in debugging the prob
primaryButtonText="Confirm"
secondaryButtonText="Restore Defaults"
on:click:button--primary={() => modalInfo.modalOpen = false}
on:click:button--secondary={() => {mathCellConfigDialog?.resetDefaults(); baseUnitsConfigDialog?.resetDefaults();}}
on:click:button--secondary={() => {mathCellConfigDialog?.resetDefaults();
baseUnitsConfigDialog?.resetDefaults();
$config.simplifySymbolicExpressions = true;}}
bind:open={modalInfo.modalOpen}
>
{#if modalInfo.mathCell}
Expand All @@ -2630,6 +2637,11 @@ Please include a link to this sheet in the email to assist in debugging the prob
<Tab label="Default Units" />
<svelte:fragment slot="content">
<TabContent>
<Checkbox
labelText="Automatically Simplify Symbolic Expressions (unchecking will speed up sheet updates)"
bind:checked={$config.simplifySymbolicExpressions}
on:check={() => $mathCellChanged = true}
/>
<MathCellConfigDialog
bind:this={mathCellConfigDialog}
bind:mathCellConfig={$config.mathCellConfig}
Expand Down
12 changes: 8 additions & 4 deletions src/sheet/Sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type Sheet = {
system_results: (SystemResult)[];
nextId: number;
sheetId: string;
insertedSheets?: InsertedSheet[]; // early sheets did not have an insertedSheets property
insertedSheets?: InsertedSheet[]; // early sheets did not have this property
};

export type InsertedSheet = {
Expand All @@ -21,7 +21,8 @@ export type InsertedSheet = {

export type Config = {
mathCellConfig: MathCellConfig;
customBaseUnits?: CustomBaseUnits; // same early sheets won't have this property
customBaseUnits?: CustomBaseUnits; // some early sheets won't have this property
simplifySymbolicExpressions?: boolean; // some early sheets won't have this property
};

type Notation = "auto" | "fixed" | "exponential" | "engineering";
Expand All @@ -41,7 +42,8 @@ type FormatOptions = {
export function getDefaultConfig(): Config {
return {
mathCellConfig: getDefaultMathCellConfig(),
customBaseUnits: getDefaultBaseUnits()
customBaseUnits: getDefaultBaseUnits(),
simplifySymbolicExpressions: true
};
}

Expand Down Expand Up @@ -78,7 +80,9 @@ export function isDefaultMathConfig(config: MathCellConfig): boolean {
}

export function isDefaultConfig(config: Config): boolean {
return isDefaultMathConfig(config.mathCellConfig) && isDefaultBaseUnits(config.customBaseUnits);
return isDefaultMathConfig(config.mathCellConfig) &&
isDefaultBaseUnits(config.customBaseUnits) &&
config.simplifySymbolicExpressions === true;
}

export function copyMathConfig(input: MathCellConfig): MathCellConfig {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type StatementsAndSystems = {
statements: Statement[];
systemDefinitions: SystemDefinition[];
customBaseUnits?: CustomBaseUnits;
simplifySymbolicExpressions: boolean;
}


13 changes: 0 additions & 13 deletions tests/test_basic.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,19 +1295,6 @@ test('Check parsing error handling impact on displayed results', async () => {
});


test('Symbolic result canceling', async () => {

await page.setLatex(0, String.raw`-F-F_{B}-F_{W}-\frac{F\cdot l_4-F_{B}\cdot l_2+F_{W}\cdot l_3}{l_1+l_2}+\frac{F\cdot l_1+F\cdot l_2+F\cdot l_4+F_{B}\cdot l_1+F_{W}\cdot l_1+F_{W}\cdot l_2+F_{W}\cdot l_3}{l_1+l_2}\ =`);

await page.waitForSelector('.status-footer', { state: 'detached'});

// check query result in cell 1
let content = await page.textContent('#result-value-0');
expect(content).toBe('0');

});


test('Test single character square root', async () => {

await page.locator('#cell-0 >> math-field.editable').type('sqrt4');
Expand Down
22 changes: 22 additions & 0 deletions tests/test_number_format.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ test('Test symbolic format', async () => {

});

test('Test disabling automatic expressions simplification', async () => {
// first test that automatic simplification is on by default
await page.setLatex(0, String.raw`-F-F_{B}-F_{W}-\frac{F\cdot l_4-F_{B}\cdot l_2+F_{W}\cdot l_3}{l_1+l_2}+\frac{F\cdot l_1+F\cdot l_2+F\cdot l_4+F_{B}\cdot l_1+F_{W}\cdot l_1+F_{W}\cdot l_2+F_{W}\cdot l_3}{l_1+l_2}\ =`);

await page.waitForSelector('.status-footer', { state: 'detached'});

// check query result in cell 1
let content = await page.textContent('#result-value-0');
expect(content).toBe('0');

// turn off automatic simplification
await page.getByRole('button', { name: 'Sheet Settings' }).click();
await page.locator('label').filter({ hasText: 'Automatically Simplify Symbolic Expressions' }).click();
await page.getByRole('button', { name: 'Confirm' }).click();

await page.waitForSelector('.status-footer', { state: 'detached'});

// check query result in cell 1
content = await page.textContent('#result-value-0');
expect(content).toBe(String.raw`- F - F_{B} - F_{W} - \frac{F l_{4} - F_{B} l_{2} + F_{W} l_{3}}{l_{1} + l_{2}} + \frac{F l_{1} + F l_{2} + F l_{4} + F_{B} l_{1} + F_{W} l_{1} + F_{W} l_{2} + F_{W} l_{3}}{l_{1} + l_{2}}`);

});

test('Test auto exponent', async () => {
await page.setLatex(0, String.raw`\frac{2}{3}=`);
Expand Down
Loading