Spaces:
Running
Running
Download math.js from Vikingdude81/ai-math-studio: direct link, hf CLI and curl.
- Browser
- Download file 15.4 kB
-
https://huggingface.co/spaces/Vikingdude81/ai-math-studio/resolve/main/math.js
- Command line
-
hf download hf://spaces/Vikingdude81/ai-math-studio/math.js
-
curl -L -o math.js https://huggingface.co/spaces/Vikingdude81/ai-math-studio/resolve/main/math.js
15.4 kB
| (function(root){ | |
| ; | |
| const topics=[ | |
| {id:'linear',name:'Linear equations',tag:'START HERE',desc:'Find the unknown. Keep the balance.',theory:'An equation says two expressions have the same value. Applying the same reversible operation to both sides preserves the solutions. A linear equation has its unknown only to the first power.',notation:'ax + b = c → x = (c − b) / a, when a ≠ 0',terms:[['Coefficient','The number multiplying a variable. In 3x, the coefficient is 3.'],['Constant','A fixed number such as the 5 in 3x + 5.'],['Inverse operation','An operation that undoes another: subtraction undoes addition.']],connection:'A linear model predicts y = wx + b. Solving for an input x uses the same algebra when the weight w is nonzero.',pitfall:'Do the operation to both entire sides. Dividing ax + b by a means dividing both terms.',related:['both','slope']}, | |
| {id:'both',name:'Variables on both sides',tag:'ALGEBRA',desc:'Collect terms and isolate the variable.',theory:'Move variable terms to one side by subtracting them from both sides. Then collect constants and divide. Equal coefficients can produce either no solution or infinitely many solutions.',notation:'ax + b = cx + d → (a − c)x = d − b',terms:[['Like terms','Terms with the same variable and power, such as 4x and 2x.'],['Identity','An equation true for every allowed value, such as 2x + 1 = 2x + 1.'],['Contradiction','An impossible equality, such as 0 = 5; it has no solutions.']],connection:'Comparing two linear models means asking where their predictions match. That is an equation with the input on both sides.',pitfall:'If the x terms cancel, inspect the constants. Do not divide by zero.',related:['linear','systems']}, | |
| {id:'systems',name:'Systems of equations',tag:'ALGEBRA',desc:'Find values that satisfy two constraints.',theory:'A solution must satisfy every equation at once. Elimination adds or subtracts equations to cancel a variable. Two nonparallel lines have exactly one intersection.',notation:'ax + by = e; cx + dy = f ↔ A v = r',terms:[['System','Two or more equations imposed at the same time.'],['Elimination','Combining equations to remove a variable.'],['Unique solution','Exactly one pair satisfies both equations. For a 2 × 2 system, ad − bc ≠ 0 guarantees this.']],connection:'Linear systems appear in least-squares fitting and numerical optimization. Real datasets often have more equations than unknowns, so an exact solution may not exist.',pitfall:'Substitution must use the same x and y in both equations. Check both, not just one.',related:['both','matrix']}, | |
| {id:'slope',name:'Slope & straight lines',tag:'GEOMETRY',desc:'Turn change into a line equation.',theory:'Slope measures change in output per unit change in input. The intercept is the output when the input is zero. A vertical line has no finite slope.',notation:'m = (y₂ − y₁)/(x₂ − x₁); y = mx + b',terms:[['Slope','The signed rate of change Δy / Δx.'],['Intercept','Where a line crosses the vertical axis: (0, b).'],['Rate of change','How much the output changes when the input increases.']],connection:'In one-feature linear regression, the weight is the slope and the bias is the intercept. Fitting means choosing them to reduce prediction error.',pitfall:'Use the same order for both differences. If the x values are equal, this slope formula divides by zero.',related:['prediction','gradient']}, | |
| {id:'dot',name:'Vectors & dot products',tag:'LINEAR ALGEBRA',desc:'Combine features with their weights.',theory:'A vector is an ordered list of numbers. The dot product multiplies corresponding components and sums the results into one scalar.',notation:'w · x = w₁x₁ + w₂x₂ + … + wₙxₙ',terms:[['Vector','An ordered list representing features, weights, or a direction.'],['Scalar','A single number. A dot product returns a scalar.'],['Dimension','The number of components. Dot-product vectors must have equal dimension.']],connection:'A model combines feature values and weights using a dot product. Dot products also measure alignment; cosine similarity normalizes by both vector lengths.',pitfall:'Do not multiply every component by every other component. Pair matching positions, then sum.',related:['matrix','prediction']}, | |
| {id:'matrix',name:'Matrix × vector',tag:'LINEAR ALGEBRA',desc:'Perform several dot products at once.',theory:'A matrix can represent a linear transformation. Multiplying it by a vector takes one dot product per row. An m × n matrix takes an n-component input and returns m components.',notation:'A v = [row₁ · v, row₂ · v, …]ᵀ',terms:[['Matrix','A rectangular array of numbers arranged in rows and columns.'],['Shape','Rows × columns; a 2 × 2 matrix has two of each.'],['Linear transformation','A mapping that preserves vector addition and scalar multiplication.']],connection:'Neural-network layers compute W x + b. Matrix multiplication combines many weights and features efficiently; the bias makes the mapping affine.',pitfall:'Use rows of the matrix against the input vector. Check the inner dimensions before multiplying.',related:['dot','systems','prediction']}, | |
| {id:'prediction',name:'Linear model predictions',tag:'AI BRIDGE',desc:'Follow features through a tiny model.',theory:'A linear model forms a weighted sum of features and adds a bias. Weights control each feature’s contribution; bias shifts the baseline. This is affine in the input when bias is nonzero.',notation:'ŷ = w · x + b',terms:[['Feature','A measured input to the model.'],['Weight','A learned multiplier controlling a feature’s contribution.'],['Bias','An added offset. It is distinct from social or statistical uses of the word bias.']],connection:'This is the forward calculation behind linear regression and part of a neuron’s computation. Training adjusts weights and bias; prediction uses their current values.',pitfall:'Add the bias once after summing all weighted features. A prediction is not automatically a probability.',related:['dot','slope','gradient']}, | |
| {id:'gradient',name:'A first gradient step',tag:'AI BRIDGE',desc:'See how an error changes a weight.',theory:'A derivative measures the local rate of change of a function. Gradient descent subtracts a small multiple of the loss derivative to update a parameter. Here we use one example, one weight, and no bias.',notation:'ŷ = wx; L = ½(ŷ − y)²; dL/dw = (wx − y)x; wnew = w − η(dL/dw)',terms:[['Loss','A number measuring prediction error; here half the squared error.'],['Gradient','The collection of derivatives with respect to parameters. Here there is just one.'],['Learning rate η','A positive step-size multiplier. Too large a step can increase loss.']],connection:'Neural-network training uses the same update idea with many parameters. Backpropagation computes the derivatives; an optimizer uses them to update weights.',pitfall:'Use the signed error (prediction minus target). A negative derivative means subtracting it increases the weight.',related:['prediction','slope']} | |
| ]; | |
| const fmt=n=>Number.isInteger(n)?String(n):String(Number(n.toFixed(5))); | |
| const signed=n=>n<0?'− '+fmt(-n):'+ '+fmt(n); | |
| const expr=(a,b,v='x')=>`${a<0?'−':''}${Math.abs(a)===1?'':fmt(Math.abs(a))}${v} ${signed(b)}`; | |
| function generate(id,level=1,rng=Math.random){ | |
| const R=(lo,hi)=>lo+Math.floor(rng()*(hi-lo+1));const nz=()=>{let v=0;while(!v)v=R(-7,7);return v};const limit=level===1?5:level===2?10:15; | |
| let x=R(-limit,limit),a=level===1?R(2,6):nz(),b=R(-limit,limit);if(level===3)x=R(-20,20)/2; | |
| const st=(title,math,why)=>({title,math,why});let p={id,level,steps:[],labels:['x'],hint:'',graph:null}; | |
| if(id==='linear'){ | |
| const c=a*x+b;p={...p,prompt:'Solve for x',equation:`${expr(a,b)} = ${fmt(c)}`,answer:[x],hint:`Undo the constant term (${fmt(b)}) first. What operation leaves just ${fmt(a)}x?`,steps:[st('Remove the constant',`${fmt(a)}x = ${fmt(c)} − (${fmt(b)}) = ${fmt(c-b)}`,'Subtract the constant from both sides to keep the equality balanced.'),st('Undo multiplication',`x = ${fmt(c-b)} / (${fmt(a)}) = ${fmt(x)}`,'Divide both sides by the nonzero coefficient of x.'),st('Check the original equation',`${fmt(a)} × (${fmt(x)}) + (${fmt(b)}) = ${fmt(c)}`,'Substitute the result into the original left side. It matches the right side.')],graph:{lines:[[a,b,'Left side'],[0,c,'Right side']],point:[x,c]}}; | |
| }else if(id==='both'){ | |
| let c=a;while(c===a)c=nz();let d=(a-c)*x+b;p={...p,prompt:'Solve for x',equation:`${expr(a,b)} = ${expr(c,d)}`,answer:[x],hint:`Subtract ${fmt(c)}x from both sides to collect the variable terms.`,steps:[st('Collect the x terms',`${fmt(a-c)}x ${signed(b)} = ${fmt(d)}`,'Subtract the right-side variable term from both sides.'),st('Collect the constants',`${fmt(a-c)}x = ${fmt(d)} − (${fmt(b)}) = ${fmt(d-b)}`,'Subtract the remaining left-side constant from both sides.'),st('Isolate x',`x = ${fmt(d-b)} / (${fmt(a-c)}) = ${fmt(x)}`,'The coefficients differ, so the divisor is nonzero. This problem has one solution.'),st('Verify both sides',`Left = ${fmt(a*x+b)}; right = ${fmt(c*x+d)}`,'The same x makes both expressions equal.')],graph:{lines:[[a,b,'Left side'],[c,d,'Right side']],point:[x,a*x+b]}}; | |
| }else if(id==='systems'){ | |
| const y=R(-limit,limit),k=level===1?1:R(2,5),c=a+R(1,5),e=a*x+k*y,f=c*x+k*y;p={...p,prompt:'Solve for x and y',equation:`${fmt(a)}x + ${k}y = ${fmt(e)}\n${c}x + ${k}y = ${fmt(f)}`,labels:['x','y'],answer:[x,y],hint:'The y coefficients match. Subtract the first equation from the second.',steps:[st('Eliminate y',`(${c} − ${fmt(a)})x = ${fmt(f)} − (${fmt(e)})\n${c-a}x = ${fmt(f-e)}`,'Subtract equal quantities. The y terms cancel because their coefficients match.'),st('Solve for x',`x = ${fmt(f-e)} / ${c-a} = ${fmt(x)}`,'Divide by the remaining nonzero coefficient.'),st('Substitute and solve for y',`${k}y = ${fmt(e)} − (${fmt(a)} × ${fmt(x)})\ny = ${fmt(k*y)} / ${k} = ${fmt(y)}`,'Use x in the first original equation, then isolate y.'),st('Check both constraints',`${fmt(a)}(${fmt(x)}) + ${k}(${fmt(y)}) = ${fmt(e)}\n${c}(${fmt(x)}) + ${k}(${fmt(y)}) = ${fmt(f)}`,'A system solution must satisfy both original equations.')],graph:{lines:[[-a/k,e/k,'Equation 1'],[-c/k,f/k,'Equation 2']],point:[x,y]}}; | |
| }else if(id==='slope'){ | |
| const x2=x+R(1,5),y=a*x+b,y2=a*x2+b;p={...p,prompt:'Find the slope m and intercept b',equation:`Point A = (${fmt(x)}, ${fmt(y)})\nPoint B = (${fmt(x2)}, ${fmt(y2)})`,labels:['m','b'],answer:[a,b],hint:'First divide the change in y by the change in x. Then substitute either point into y = mx + b.',steps:[st('Measure the changes',`Δy = ${fmt(y2)} − (${fmt(y)}) = ${fmt(y2-y)}\nΔx = ${fmt(x2)} − (${fmt(x)}) = ${fmt(x2-x)}`,'Use B minus A consistently for both coordinates.'),st('Calculate slope',`m = ${fmt(y2-y)} / ${fmt(x2-x)} = ${fmt(a)}`,'Slope is vertical change divided by horizontal change.'),st('Find the intercept',`b = y − mx = ${fmt(y)} − (${fmt(a)} × ${fmt(x)}) = ${fmt(b)}`,'Rearrange y = mx + b and use a known point.'),st('Write and check the line',`y = ${expr(a,b)}\nAt x = ${fmt(x2)}, y = ${fmt(a*x2+b)}`,'The resulting line also passes through point B.')],graph:{lines:[[a,b,'Line through A and B']],point:[x,y],extra:[x2,y2]}}; | |
| }else if(id==='dot'||id==='prediction'){ | |
| const n=level===1?2:3,weights=Array.from({length:n},()=>nz()),v=Array.from({length:n},()=>R(-limit,limit)),products=weights.map((w,i)=>w*v[i]),sum=products.reduce((s,n)=>s+n,0),pred=id==='prediction';p={...p,prompt:pred?'Compute the prediction ŷ':'Compute the dot product',equation:`${pred?'w':'u'} = [${weights.join(', ')}]\n${pred?'x':'v'} = [${v.join(', ')}]${pred?'\nb = '+fmt(b):''}`,labels:[pred?'ŷ':'u · v'],answer:[sum+(pred?b:0)],hint:'Multiply the entries in matching positions, then add the products.'+(pred?' Add the bias once at the end.':''),steps:[st('Pair the components',weights.map((w,i)=>`${w} × (${v[i]}) = ${products[i]}`).join('\n'),'Each feature is multiplied by its corresponding weight; order matters.'),st('Sum the products',`${products.map(n=>'('+n+')').join(' + ')} = ${sum}`,'Adding the component contributions gives the dot product, a scalar.'),...(pred?[st('Add the bias',`ŷ = ${sum} + (${fmt(b)}) = ${fmt(sum+b)}`,'The bias shifts the total once; it is not multiplied by each feature.')]:[st('Interpret the result',`u · v = ${sum}`,'A positive result suggests overall alignment; negative suggests opposition. Vector lengths affect the magnitude.')])],vector:{weights,v,products,bias:pred?b:null}}; | |
| }else if(id==='matrix'){ | |
| const A=[[a,b],[nz(),R(-limit,limit)]],v=[x,R(-limit,limit)],out=A.map(row=>row[0]*v[0]+row[1]*v[1]);p={...p,prompt:'Multiply A by v',equation:`A = [ ${A[0].join(' ')} ]\n [ ${A[1].join(' ')} ]\nv = [${v.join(', ')}]ᵀ`,labels:['row 1 result','row 2 result'],answer:out,hint:'Take the first row’s dot product with v, then repeat for the second row.',steps:[st('Check the shapes','(2 × 2) × (2 × 1) → (2 × 1)','The inner dimensions match. The output has one value per matrix row.'),...A.map((row,i)=>st(`Compute output ${i+1}`,`${row[0]} × (${fmt(v[0])}) + (${row[1]}) × (${v[1]}) = ${fmt(out[i])}`,'Multiply each row component by the matching vector component, then sum.')),st('Assemble the output',`Av = [${out.map(fmt).join(', ')}]ᵀ`,'Keep the row results in order to form the output column vector.')],matrix:{A,v,out}}; | |
| }else if(id==='gradient'){ | |
| x=R(1,level===1?3:6);const w=R(-4,5),target=R(-8,12),eta=level===1?.1:level===2?.05:.01,pred=w*x,error=pred-target,g=error*x,next=w-eta*g,loss=.5*error*error,newloss=.5*(next*x-target)**2;p={...p,prompt:'Find the updated weight after one step',equation:`x = ${x}, target y = ${target}, weight w = ${w}\nLearning rate η = ${eta}\nŷ = wx; L = ½(ŷ − y)²`,labels:['new w'],answer:[next],hint:'Compute the prediction, subtract the target, multiply the error by x, then subtract η times that derivative from w.',steps:[st('Make the prediction',`ŷ = ${w} × ${x} = ${pred}`,'The current model has one weight and no bias.'),st('Measure signed error',`e = ŷ − y = ${pred} − (${target}) = ${error}\nL = ½ × (${error})² = ${fmt(loss)}`,'Squared error penalizes both positive and negative mistakes. The half simplifies the derivative.'),st('Differentiate the loss',`dL/dw = (wx − y)x = ${error} × ${x} = ${g}`,'By the chain rule, differentiate ½e² to get e, then multiply by de/dw = x.'),st('Update the weight',`wnew = ${w} − (${eta} × ${g}) = ${fmt(next)}`,'Subtract the learning rate times the derivative to move downhill locally.'),st('Inspect the new loss',`New ŷ = ${fmt(next*x)}\nNew L = ${fmt(newloss)}`,'For this generated step, loss does not increase. That is not guaranteed for arbitrary learning rates.')],loss:{before:loss,after:newloss}}; | |
| }else throw Error('Unknown topic');return p; | |
| } | |
| function parseNumber(s){s=String(s).trim().replaceAll('−','-');if(!s)return NaN;if(/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(s))return Number(s);if(/^[+-]?\d+\s*\/\s*[+-]?\d+$/.test(s)){const[a,b]=s.split('/').map(Number);return b===0?NaN:a/b}return NaN} | |
| function check(values,answer){return values.length===answer.length&&values.every((v,i)=>Number.isFinite(v)&&Math.abs(v-answer[i])<=.001)} | |
| const api={topics,generate,fmt,parseNumber,check};if(typeof module!=='undefined')module.exports=api;root.MathStudio=api; | |
| })(typeof window==='undefined'?globalThis:window); | |