Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950

951

952

953

954

955

956

957

958

959

960

961

962

963

964

965

966

967

968

969

970

971

972

973

974

975

976

977

978

979

980

981

982

983

984

985

986

987

988

989

990

991

992

993

994

995

996

997

998

999

1000

1001

1002

1003

1004

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022

1023

1024

1025

1026

1027

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1046

1047

1048

1049

1050

1051

r""" 

Interface to Mathematica 

 

The Mathematica interface will only work if Mathematica is installed on your 

computer with a command line interface that runs when you give the ``math`` 

command. The interface lets you send certain Sage objects to Mathematica, 

run Mathematica functions, import certain Mathematica expressions to Sage, 

or any combination of the above. 

 

To send a Sage object ``sobj`` to Mathematica, call ``mathematica(sobj)``. 

This exports the Sage object to Mathematica and returns a new Sage object 

wrapping the Mathematica expression/variable, so that you can use the 

Mathematica variable from within Sage. You can then call Mathematica 

functions on the new object; for example:: 

 

sage: mobj = mathematica(x^2-1) # optional - mathematica 

sage: mobj.Factor() # optional - mathematica 

(-1 + x)*(1 + x) 

 

In the above example the factorization is done using Mathematica's 

``Factor[]`` function. 

 

To see Mathematica's output you can simply print the Mathematica wrapper 

object. However if you want to import Mathematica's output back to Sage, 

call the Mathematica wrapper object's ``sage()`` method. This method returns 

a native Sage object:: 

 

sage: mobj = mathematica(x^2-1) # optional - mathematica 

sage: mobj2 = mobj.Factor(); mobj2 # optional - mathematica 

(-1 + x)*(1 + x) 

sage: mobj2.parent() # optional - mathematica 

Mathematica 

sage: sobj = mobj2.sage(); sobj # optional - mathematica 

(x + 1)*(x - 1) 

sage: sobj.parent() # optional - mathematica 

Symbolic Ring 

 

 

If you want to run a Mathematica function and don't already have the input 

in the form of a Sage object, then it might be simpler to input a string to 

``mathematica(expr)``. This string will be evaluated as if you had typed it 

into Mathematica:: 

 

sage: mathematica('Factor[x^2-1]') # optional - mathematica 

(-1 + x)*(1 + x) 

sage: mathematica('Range[3]') # optional - mathematica 

{1, 2, 3} 

 

If you don't want Sage to go to the trouble of creating a wrapper for the 

Mathematica expression, then you can call ``mathematica.eval(expr)``, which 

returns the result as a Mathematica AsciiArtString formatted string. If you 

want the result to be a string formatted like Mathematica's InputForm, call 

``repr(mobj)`` on the wrapper object ``mobj``. If you want a string 

formatted in Sage style, call ``mobj._sage_repr()``:: 

 

sage: mathematica.eval('x^2 - 1') # optional - mathematica 

2 

-1 + x 

sage: repr(mathematica('Range[3]')) # optional - mathematica 

'{1, 2, 3}' 

sage: mathematica('Range[3]')._sage_repr() # optional - mathematica 

'[1, 2, 3]' 

 

Finally, if you just want to use a Mathematica command line from within 

Sage, the function ``mathematica_console()`` dumps you into an interactive 

command-line Mathematica session. This is an enhanced version of the usual 

Mathematica command-line, in that it provides readline editing and history 

(the usual one doesn't!) 

 

Tutorial 

-------- 

 

We follow some of the tutorial from 

http://library.wolfram.com/conferences/devconf99/withoff/Basic1.html/. 

 

For any of this to work you must buy and install the Mathematica 

program, and it must be available as the command 

``math`` in your PATH. 

 

Syntax 

~~~~~~ 

 

Now make 1 and add it to itself. The result is a Mathematica 

object. 

 

:: 

 

sage: m = mathematica 

sage: a = m(1) + m(1); a # optional - mathematica 

2 

sage: a.parent() # optional - mathematica 

Mathematica 

sage: m('1+1') # optional - mathematica 

2 

sage: m(3)**m(50) # optional - mathematica 

717897987691852588770249 

 

The following is equivalent to ``Plus[2, 3]`` in 

Mathematica:: 

 

sage: m = mathematica 

sage: m(2).Plus(m(3)) # optional - mathematica 

5 

 

We can also compute `7(2+3)`. 

 

:: 

 

sage: m(7).Times(m(2).Plus(m(3))) # optional - mathematica 

35 

sage: m('7(2+3)') # optional - mathematica 

35 

 

Some typical input 

~~~~~~~~~~~~~~~~~~ 

 

We solve an equation and a system of two equations:: 

 

sage: eqn = mathematica('3x + 5 == 14') # optional - mathematica 

sage: eqn # optional - mathematica 

5 + 3*x == 14 

sage: eqn.Solve('x') # optional - mathematica 

{{x -> 3}} 

sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}') # optional - mathematica 

sage: print(sys) # optional - mathematica 

2 

{x - 3 y == 3, 2 x - y == 1} 

sage: sys.Solve('{x, y}') # optional - mathematica 

{{x -> 0, y -> -1}, {x -> 6, y -> 11}} 

 

Assignments and definitions 

~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

 

If you assign the mathematica `5` to a variable `c` 

in Sage, this does not affect the `c` in Mathematica. 

 

:: 

 

sage: c = m(5) # optional - mathematica 

sage: print(m('b + c x')) # optional - mathematica 

b + c x 

sage: print(m('b') + c*m('x')) # optional - mathematica 

b + 5 x 

 

The Sage interfaces changes Sage lists into Mathematica lists:: 

 

sage: m = mathematica 

sage: eq1 = m('x^2 - 3y == 3') # optional - mathematica 

sage: eq2 = m('2x - y == 1') # optional - mathematica 

sage: v = m([eq1, eq2]); v # optional - mathematica 

{x^2 - 3*y == 3, 2*x - y == 1} 

sage: v.Solve(['x', 'y']) # optional - mathematica 

{{x -> 0, y -> -1}, {x -> 6, y -> 11}} 

 

Function definitions 

~~~~~~~~~~~~~~~~~~~~ 

 

Define mathematica functions by simply sending the definition to 

the interpreter. 

 

:: 

 

sage: m = mathematica 

sage: _ = mathematica('f[p_] = p^2'); # optional - mathematica 

sage: m('f[9]') # optional - mathematica 

81 

 

Numerical Calculations 

~~~~~~~~~~~~~~~~~~~~~~ 

 

We find the `x` such that `e^x - 3x = 0`. 

 

:: 

 

sage: e = mathematica('Exp[x] - 3x == 0') # optional - mathematica 

sage: e.FindRoot(['x', 2]) # optional - mathematica 

{x -> 1.512134551657842} 

 

Note that this agrees with what the PARI interpreter gp produces:: 

 

sage: gp('solve(x=1,2,exp(x)-3*x)') 

1.512134551657842473896739678 # 32-bit 

1.5121345516578424738967396780720387046 # 64-bit 

 

Next we find the minimum of a polynomial using the two different 

ways of accessing Mathematica:: 

 

sage: mathematica('FindMinimum[x^3 - 6x^2 + 11x - 5, {x,3}]') # optional - mathematica 

{0.6150998205402516, {x -> 2.5773502699629733}} 

sage: f = mathematica('x^3 - 6x^2 + 11x - 5') # optional - mathematica 

sage: f.FindMinimum(['x', 3]) # optional - mathematica 

{0.6150998205402516, {x -> 2.5773502699629733}} 

 

Polynomial and Integer Factorization 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

 

We factor a polynomial of degree 200 over the integers. 

 

:: 

 

sage: R.<x> = PolynomialRing(ZZ) 

sage: f = (x**100+17*x+5)*(x**100-5*x+20) 

sage: f 

x^200 + 12*x^101 + 25*x^100 - 85*x^2 + 315*x + 100 

sage: g = mathematica(str(f)) # optional - mathematica 

sage: print(g) # optional - mathematica 

2 100 101 200 

100 + 315 x - 85 x + 25 x + 12 x + x 

sage: g # optional - mathematica 

100 + 315*x - 85*x^2 + 25*x^100 + 12*x^101 + x^200 

sage: print(g.Factor()) # optional - mathematica 

100 100 

(20 - 5 x + x ) (5 + 17 x + x ) 

 

We can also factor a multivariate polynomial:: 

 

sage: f = mathematica('x^6 + (-y - 2)*x^5 + (y^3 + 2*y)*x^4 - y^4*x^3') # optional - mathematica 

sage: print(f.Factor()) # optional - mathematica 

3 2 3 

x (x - y) (-2 x + x + y ) 

 

We factor an integer:: 

 

sage: n = mathematica(2434500) # optional - mathematica 

sage: n.FactorInteger() # optional - mathematica 

{{2, 2}, {3, 2}, {5, 3}, {541, 1}} 

sage: n = mathematica(2434500) # optional - mathematica 

sage: F = n.FactorInteger(); F # optional - mathematica 

{{2, 2}, {3, 2}, {5, 3}, {541, 1}} 

sage: F[1] # optional - mathematica 

{2, 2} 

sage: F[4] # optional - mathematica 

{541, 1} 

 

Mathematica's ECM package is no longer available.  

 

Long Input 

---------- 

 

The Mathematica interface reads in even very long input (using 

files) in a robust manner. 

 

:: 

 

sage: t = '"%s"'%10^10000 # ten thousand character string. 

sage: a = mathematica(t) # optional - mathematica 

sage: a = mathematica.eval(t) # optional - mathematica 

 

Loading and saving 

------------------ 

 

Mathematica has an excellent ``InputForm`` function, 

which makes saving and loading Mathematica objects possible. The 

first examples test saving and loading to strings. 

 

:: 

 

sage: x = mathematica(pi/2) # optional - mathematica 

sage: print(x) # optional - mathematica 

Pi 

-- 

2 

sage: loads(dumps(x)) == x # optional - mathematica 

True 

sage: n = x.N(50) # optional - mathematica 

sage: print(n) # optional - mathematica 

1.5707963267948966192313216916397514420985846996876 

sage: loads(dumps(n)) == n # optional - mathematica 

True 

 

Complicated translations 

------------------------ 

 

The ``mobj.sage()`` method tries to convert a Mathematica object to a Sage 

object. In many cases, it will just work. In particular, it should be able to 

convert expressions entirely consisting of: 

 

- numbers, i.e. integers, floats, complex numbers; 

- functions and named constants also present in Sage, where: 

 

- Sage knows how to translate the function or constant's name from 

Mathematica's, or 

- the Sage name for the function or constant is trivially related to 

Mathematica's; 

 

- symbolic variables whose names don't pathologically overlap with 

objects already defined in Sage. 

 

This method will not work when Mathematica's output includes: 

 

- strings; 

- functions unknown to Sage; 

- Mathematica functions with different parameters/parameter order to 

the Sage equivalent. 

 

If you want to convert more complicated Mathematica expressions, you can 

instead call ``mobj._sage_()`` and supply a translation dictionary:: 

 

sage: m = mathematica('NewFn[x]') # optional - mathematica 

sage: m._sage_(locals={'NewFn': sin}) # optional - mathematica 

sin(x) 

 

For more details, see the documentation for ``._sage_()``. 

 

 

OTHER Examples:: 

 

sage: def math_bessel_K(nu,x): 

....: return mathematica(nu).BesselK(x).N(20) 

sage: math_bessel_K(2,I) # optional - mathematica 

-2.5928861754911969782 + 0.1804899720669620266 I 

 

:: 

 

sage: slist = [[1, 2], 3., 4 + I] 

sage: mlist = mathematica(slist); mlist # optional - mathematica 

{{1, 2}, 3., 4 + I} 

sage: slist2 = list(mlist); slist2 # optional - mathematica 

[{1, 2}, 3., 4 + I] 

sage: slist2[0] # optional - mathematica 

{1, 2} 

sage: slist2[0].parent() # optional - mathematica 

Mathematica 

sage: slist3 = mlist.sage(); slist3 # optional - mathematica 

[[1, 2], 3.0, I + 4] 

 

:: 

 

sage: mathematica('10.^80') # optional - mathematica 

1.*^80 

sage: mathematica('10.^80').sage() # optional - mathematica 

1e+80 

 

AUTHORS: 

 

- William Stein (2005): first version 

 

- Doug Cutrell (2006-03-01): Instructions for use under Cygwin/Windows. 

 

- Felix Lawrence (2009-08-21): Added support for importing Mathematica lists 

and floats with exponents. 

""" 

 

#***************************************************************************** 

# Copyright (C) 2005 William Stein <wstein@gmail.com> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# 

# This code is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

# General Public License for more details. 

# 

# The full text of the GPL is available at: 

# 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

from __future__ import print_function 

 

import os 

import re 

 

from sage.misc.cachefunc import cached_method 

from sage.interfaces.expect import (Expect, ExpectElement, ExpectFunction, 

FunctionElement, AsciiArtString) 

from sage.interfaces.tab_completion import ExtraTabCompletion 

from sage.docs.instancedoc import instancedoc 

 

 

def clean_output(s): 

if s is None: 

return '' 

i = s.find('Out[') 

j = i + s[i:].find('=') 

s = s[:i] + ' '*(j+1-i) + s[j+1:] 

s = s.replace('\\\n','') 

return s.strip('\n') 

 

def _un_camel(name): 

""" 

Convert `CamelCase` to `camel_case`. 

 

EXAMPLES:: 

 

sage: sage.interfaces.mathematica._un_camel('CamelCase') 

'camel_case' 

sage: sage.interfaces.mathematica._un_camel('EllipticE') 

'elliptic_e' 

sage: sage.interfaces.mathematica._un_camel('FindRoot') 

'find_root' 

sage: sage.interfaces.mathematica._un_camel('GCD') 

'gcd' 

""" 

s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) 

return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() 

 

 

class Mathematica(ExtraTabCompletion, Expect): 

""" 

Interface to the Mathematica interpreter. 

""" 

def __init__(self, maxread=None, script_subdirectory=None, logfile=None, server=None, 

server_tmpdir=None, command=None, verbose_start=False): 

# We use -rawterm to get a raw text interface in Mathematica 9 or later. 

# This works around the following issues of Mathematica 9 or later 

# (tested with Mathematica 11.0.1 for Mac OS X x86 (64-bit)) 

# 

# 1) If TERM is unset and input is a pseudoterminal, Mathematica shows no 

# prompts, so pexpect will not work. 

# 

# 2) If TERM is set (to dumb, lpr, vt100, or xterm), there will be 

# prompts; but there is bizarre echoing behavior by Mathematica (not 

# the terminal driver). For example, with TERM=dumb, many spaces and 

# \r's are echoed. With TERM=vt100 or better, in addition, many escape 

# sequences are printed. 

# 

if command is None: 

command = os.getenv('SAGE_MATHEMATICA_COMMAND') or 'math -rawterm' 

eval_using_file_cutoff = 1024 

# Removing terminal echo using "stty -echo" is not essential but it slightly 

# improves performance (system time) and eliminates races of the terminal echo 

# as a possible source of error. 

if server: 

command = 'stty -echo; {}'.format(command) 

else: 

command = 'sh -c "stty -echo; {}"'.format(command) 

Expect.__init__(self, 

name = 'mathematica', 

command = command, 

prompt = 'In[[0-9]+]:=', 

server = server, 

server_tmpdir = server_tmpdir, 

script_subdirectory = script_subdirectory, 

verbose_start = verbose_start, 

logfile=logfile, 

eval_using_file_cutoff=eval_using_file_cutoff) 

 

def _read_in_file_command(self, filename): 

return '<<"%s"'%filename 

 

def _keyboard_interrupt(self): 

print("Interrupting %s..." % self) 

e = self._expect 

e.sendline(chr(3)) # send ctrl-c 

e.expect('Interrupt> ') 

e.sendline("a") # a -- abort 

e.expect(self._prompt) 

return e.before 

 

def _install_hints(self): 

""" 

Hints for installing mathematica on your computer. 

 

AUTHORS: 

 

- William Stein and Justin Walker (2006-02-12) 

""" 

return """ 

In order to use the Mathematica interface you need to have Mathematica 

installed and have a script in your PATH called "math" that runs the 

command-line version of Mathematica. Alternatively, you could use a 

remote connection to a server running Mathematica -- for hints, type 

print(mathematica._install_hints_ssh()) 

 

 

(1) You might have to buy Mathematica (http://www.wolfram.com/). 

 

(2) * LINUX: The math script comes standard with your Mathematica install. 

 

* APPLE OS X: 

(a) create a file called math (in your PATH): 

#!/bin/sh 

/Applications/Mathematica.app/Contents/MacOS/MathKernel $@ 

 

The path in the above script must be modified if you installed 

Mathematica elsewhere or installed an old version of 

Mathematica that has the version in the .app name. 

 

(b) Make the file executable. 

chmod +x math 

 

* WINDOWS: 

 

Install Mathematica for Linux into the VMware virtual machine (sorry, 

that's the only way at present). 

""" 

 

## The following only works with Sage for Cygwin (not colinux). 

## Note that Sage colinux is the preferred way to run Sage in Windows, 

## and I do not know how to use Mathematica from colinux Sage (unless 

## you install Mathematica-for-linux into the colinux machine, which 

## is possible). 

 

## Create a file named "math", which you place in the Sage root 

## directory. The file contained a single line, which was the 

## path to the mathematica math.exe file. In my case, this might be: 

 

## C:/Program Files/Wolfram Research/Mathematica/4.0/math.exe 

 

## The key points are 

## 1) there is a file named "math.exe", and it will generally be 

## located in a place analogous to the above (depending on where 

## Mathematica has been installed). This file is used only for 

## launching the kernel with a text-based interface. 

## 2) a cygwin batch file must be created which executes this file, 

## which means using forward slashes rather than back slashes, 

## and probably surrounding everything in quotes 

## 3) this cygwin batch file must be on the path for Sage (placing 

## it in <SAGE_LOCAL>/bin/ is an easy way to ensure this). 

 

def eval(self, code, strip=True, **kwds): 

s = Expect.eval(self, code, **kwds) 

if strip: 

return AsciiArtString(clean_output(s)) 

else: 

return AsciiArtString(s) 

 

#def _keyboard_interrupt(self): 

# print("Keyboard interrupt pressed; trying to recover.") 

# E = self.expect() 

# E.sendline(chr(3)) 

# E.sendline('a') 

# E.expect(':= ') 

# raise KeyboardInterrupt, "Ctrl-c pressed while running Mathematica command" 

 

 

def set(self, var, value): 

""" 

Set the variable var to the given value. 

""" 

cmd = '%s=%s;'%(var,value) 

#out = self.eval(cmd) 

out = self._eval_line(cmd, allow_use_file=True) 

if len(out) > 8: 

raise TypeError("Error executing code in Mathematica\nCODE:\n\t%s\nMathematica ERROR:\n\t%s"%(cmd, out)) 

 

def get(self, var, ascii_art=False): 

""" 

Get the value of the variable var. 

 

AUTHORS: 

 

- William Stein 

 

- Kiran Kedlaya (2006-02-04): suggested using InputForm 

""" 

if ascii_art: 

return self.eval(var, strip=True) 

else: 

return self.eval('InputForm[%s, NumberMarks->False]'%var, strip=True) 

 

#def clear(self, var): 

# """ 

# Clear the variable named var. 

# """ 

# self.eval('Clear[%s]'%var) 

 

def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=False): 

s = Expect._eval_line(self, line, 

allow_use_file=allow_use_file, wait_for_prompt=wait_for_prompt) 

return str(s).strip('\n') 

 

def _function_call_string(self, function, args, kwds): 

""" 

Returns the string used to make function calls. 

 

EXAMPLES:: 

 

sage: mathematica._function_call_string('Sin', ['x'], []) 

'Sin[x]' 

""" 

return "%s[%s]"%(function, ",".join(args)) 

 

def _left_list_delim(self): 

return "{" 

 

def _right_list_delim(self): 

return "}" 

 

def _left_func_delim(self): 

return "[" 

 

def _right_func_delim(self): 

return "]" 

 

########################################### 

# System -- change directory, etc 

########################################### 

def chdir(self, dir): 

""" 

Change Mathematica's current working directory. 

 

EXAMPLES:: 

 

sage: mathematica.chdir('/') # optional - mathematica 

sage: mathematica('Directory[]') # optional - mathematica 

"/" 

""" 

self.eval('SetDirectory["%s"]'%dir) 

 

def _true_symbol(self): 

return ' True' 

 

def _false_symbol(self): 

return ' False' 

 

def _equality_symbol(self): 

return '==' 

 

def _assign_symbol(self): 

return ":=" 

 

def _exponent_symbol(self): 

""" 

Returns the symbol used to denote the exponent of a number in 

Mathematica. 

 

EXAMPLES:: 

 

sage: mathematica._exponent_symbol() # optional - mathematica 

'*^' 

 

:: 

 

sage: bignum = mathematica('10.^80') # optional - mathematica 

sage: repr(bignum) # optional - mathematica 

'1.*^80' 

sage: repr(bignum).replace(mathematica._exponent_symbol(), 'e').strip() # optional - mathematica 

'1.e80' 

""" 

return "*^" 

 

def _object_class(self): 

return MathematicaElement 

 

def console(self, readline=True): 

mathematica_console(readline=readline) 

 

def _tab_completion(self): 

a = self.eval('Names["*"]') 

return a.replace('$','').replace('\n \n>','').replace(',','').replace('}','').replace('{','').split() 

 

 

def help(self, cmd): 

return self.eval('? %s'%cmd) 

 

def __getattr__(self, attrname): 

if attrname[:1] == "_": 

raise AttributeError 

return MathematicaFunction(self, attrname) 

 

 

@instancedoc 

class MathematicaElement(ExpectElement): 

def __getitem__(self, n): 

return self.parent().new('%s[[%s]]'%(self._name, n)) 

 

def __getattr__(self, attrname): 

self._check_valid() 

if attrname[:1] == "_": 

raise AttributeError 

return MathematicaFunctionElement(self, attrname) 

 

def __float__(self, precision=16): 

P = self.parent() 

return float(P.eval('N[%s,%s]'%(self.name(),precision))) 

 

def _reduce(self): 

return self.parent().eval('InputForm[%s]'%self.name()) 

 

def __reduce__(self): 

return reduce_load, (self._reduce(), ) 

 

def _latex_(self): 

z = self.parent().eval('TeXForm[%s]'%self.name()) 

i = z.find('=') 

return z[i+1:].strip() 

 

def _repr_(self): 

P = self.parent() 

return P.get(self._name, ascii_art=False).strip() 

 

def _sage_(self, locals={}): 

r""" 

Attempt to return a Sage version of this object. 

 

This method works successfully when Mathematica returns a result 

or list of results that consist only of: 

- numbers, i.e. integers, floats, complex numbers; 

- functions and named constants also present in Sage, where: 

- Sage knows how to translate the function or constant's name 

from Mathematica's naming scheme, or 

- you provide a translation dictionary `locals`, or 

- the Sage name for the function or constant is simply the 

Mathematica name in lower case; 

- symbolic variables whose names don't pathologically overlap with 

objects already defined in Sage. 

 

This method will not work when Mathematica's output includes: 

- strings; 

- functions unknown to Sage that are not specified in `locals`; 

- Mathematica functions with different parameters/parameter order to 

the Sage equivalent. In this case, define a function to do the 

parameter conversion, and pass it in via the locals dictionary. 

 

EXAMPLES: 

 

Mathematica lists of numbers/constants become Sage lists of 

numbers/constants:: 

 

sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}') # optional - mathematica 

sage: s = m.sage(); s # optional - mathematica 

[[1.0, 4], pi, 3.2*e100, I] 

sage: s[1].n() # optional - mathematica 

3.14159265358979 

sage: s[3]^2 # optional - mathematica 

-1 

 

:: 

 

sage: m = mathematica('x^2 + 5*y') # optional - mathematica 

sage: m.sage() # optional - mathematica 

x^2 + 5*y 

 

:: 

 

sage: m = mathematica('Sin[Sqrt[1-x^2]] * (1 - Cos[1/x])^2') # optional - mathematica 

sage: m.sage() # optional - mathematica 

(cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1)) 

 

:: 

 

sage: m = mathematica('NewFn[x]') # optional - mathematica 

sage: m._sage_(locals={'NewFn': sin}) # optional - mathematica 

sin(x) 

 

:: 

 

sage: var('bla') # optional - mathematica 

bla 

sage: m = mathematica('bla^2') # optional - mathematica 

sage: bla^2 - m.sage() # optional - mathematica 

0 

 

:: 

 

sage: m = mathematica('bla^2') # optional - mathematica 

sage: mb = m.sage() # optional - mathematica 

sage: var('bla') # optional - mathematica 

bla 

sage: bla^2 - mb # optional - mathematica 

0 

 

 

AUTHORS: 

 

- Felix Lawrence (2010-11-03): Major rewrite to use ._sage_repr() and 

sage.calculus.calculus.symbolic_expression_from_string() for greater 

compatibility, while still supporting conversion of symbolic 

expressions. 

""" 

from sage.libs.pynac.pynac import symbol_table 

from sage.symbolic.constants import constants_name_table as constants 

from sage.calculus.calculus import symbolic_expression_from_string 

from sage.calculus.calculus import _find_func as find_func 

 

# Get Mathematica's output and perform preliminary formatting 

res = self._sage_repr() 

if '"' in res: 

raise NotImplementedError("String conversion from Mathematica \ 

does not work. Mathematica's output was: %s" % res) 

 

# Find all the mathematica functions, constants and symbolic variables 

# present in `res`. Convert MMA functions and constants to their 

# Sage equivalents (if possible), using `locals` and 

# `sage.libs.pynac.pynac.symbol_table['mathematica']` as translation 

# dictionaries. If a MMA function or constant is not either 

# dictionary, then we use a variety of tactics listed in `autotrans`. 

# If a MMA variable is not in any dictionary, then create an 

# identically named Sage equivalent. 

 

# Merge the user-specified locals dictionary and the symbol_table 

# (locals takes priority) 

lsymbols = symbol_table['mathematica'].copy() 

lsymbols.update(locals) 

 

# Strategies for translating unknown functions/constants: 

autotrans = [ str.lower, # Try it in lower case 

_un_camel, # Convert `CamelCase` to `camel_case` 

lambda x: x # Try the original name 

] 

 

# Find the MMA funcs/vars/constants - they start with a letter. 

# Exclude exponents (e.g. 'e8' from 4.e8) 

p = re.compile('(?<!\.)[a-zA-Z]\w*') 

for m in p.finditer(res): 

# If the function, variable or constant is already in the 

# translation dictionary, then just move on. 

if m.group() in lsymbols: 

pass 

# Now try to translate all other functions -- try each strategy 

# in `autotrans` and check if the function exists in Sage 

elif m.end() < len(res) and res[m.end()] == '(': 

for t in autotrans: 

f = find_func(t(m.group()), create_when_missing = False) 

if f is not None: 

lsymbols[m.group()] = f 

break 

else: 

raise NotImplementedError("Don't know a Sage equivalent \ 

for Mathematica function '%s'. Please specify one \ 

manually using the 'locals' dictionary" % m.group()) 

# Check if Sage has an equivalent constant 

else: 

for t in autotrans: 

if t(m.group()) in constants: 

lsymbols[m.group()] = constants[t(m.group())] 

break 

# If Sage has never heard of the variable, then 

# symbolic_expression_from_string will automatically create it 

try: 

return symbolic_expression_from_string(res, lsymbols, 

accept_sequence=True) 

except Exception: 

raise NotImplementedError("Unable to parse Mathematica \ 

output: %s" % res) 

 

def __str__(self): 

P = self._check_valid() 

return P.get(self._name, ascii_art=True) 

 

def __len__(self): 

""" 

Return the object's length, evaluated by mathematica. 

 

EXAMPLES:: 

 

sage: len(mathematica([1,1.,2])) # optional - mathematica 

3 

 

AUTHORS: 

- Felix Lawrence (2009-08-21) 

""" 

return self.Length() 

 

@cached_method 

def _is_graphics(self): 

""" 

Test whether the mathematica expression is graphics 

 

OUTPUT: 

 

Boolean. 

 

EXAMPLES:: 

 

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica 

sage: P._is_graphics() # optional - mathematica 

True 

""" 

P = self._check_valid() 

return P.eval('InputForm[%s]' % self.name()).strip().startswith('Graphics[') 

 

def save_image(self, filename, ImageSize=600): 

r""" 

Save a mathematica graphics 

 

INPUT: 

 

- ``filename`` -- string. The filename to save as. The 

extension determines the image file format. 

 

- ``ImageSize`` -- integer. The size of the resulting image. 

 

EXAMPLES:: 

 

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica 

sage: filename = tmp_filename() # optional - mathematica 

sage: P.save_image(filename, ImageSize=800) # optional - mathematica 

""" 

P = self._check_valid() 

if not self._is_graphics(): 

raise ValueError('mathematica expression is not graphics') 

filename = os.path.abspath(filename) 

s = 'Export["%s", %s, ImageSize->%s]'%(filename, self.name(), ImageSize) 

P.eval(s) 

 

def _rich_repr_(self, display_manager, **kwds): 

""" 

Rich Output Magic Method 

 

See :mod:`sage.repl.rich_output` for details. 

 

EXAMPLES:: 

 

sage: from sage.repl.rich_output import get_display_manager 

sage: dm = get_display_manager() 

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica 

 

The following test requires a working X display on Linux so that the 

Mathematica frontend can do the rendering (:trac:`23112`):: 

 

sage: P._rich_repr_(dm) # optional - mathematica mathematicafrontend 

OutputImagePng container 

""" 

if self._is_graphics(): 

OutputImagePng = display_manager.types.OutputImagePng 

if display_manager.preferences.graphics == 'disable': 

return 

if OutputImagePng in display_manager.supported_output(): 

return display_manager.graphics_from_save( 

self.save_image, kwds, '.png', OutputImagePng) 

else: 

OutputLatex = display_manager.types.OutputLatex 

dmp = display_manager.preferences.text 

if dmp is None or dmp == 'plain': 

return 

if dmp == 'latex' and OutputLatex in display_manager.supported_output(): 

return OutputLatex(self._latex_()) 

 

def show(self, ImageSize=600): 

r""" 

Show a mathematica expression immediately. 

 

This method attempts to display the graphics immediately, 

without waiting for the currently running code (if any) to 

return to the command line. Be careful, calling it from within 

a loop will potentially launch a large number of external 

viewer programs. 

 

INPUT: 

 

- ``ImageSize`` -- integer. The size of the resulting image. 

 

OUTPUT: 

 

This method does not return anything. Use :meth:`save` if you 

want to save the figure as an image. 

 

EXAMPLES:: 

 

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica 

sage: show(P) # optional - mathematica 

sage: P.show(ImageSize=800) # optional - mathematica 

sage: Q = mathematica('Sin[x Cos[y]]/Sqrt[1-x^2]') # optional - mathematica 

sage: show(Q) # optional - mathematica 

<html><script type="math/tex">\frac{\sin (x \cos (y))}{\sqrt{1-x^2}}</script></html> 

""" 

from sage.repl.rich_output import get_display_manager 

dm = get_display_manager() 

dm.display_immediately(self, ImageSize=ImageSize) 

 

def str(self): 

return str(self) 

 

def __cmp__(self, other): 

#if not (isinstance(other, ExpectElement) and other.parent() is self.parent()): 

# return coerce.cmp(self, other) 

P = self.parent() 

if P.eval("%s < %s"%(self.name(), other.name())).strip() == 'True': 

return -1 

elif P.eval("%s > %s"%(self.name(), other.name())).strip() == 'True': 

return 1 

elif P.eval("%s == %s"%(self.name(), other.name())).strip() == 'True': 

return 0 

else: 

return -1 # everything is supposed to be comparable in Python, so we define 

# the comparison thus when no comparable in interfaced system. 

 

def N(self, precision=None): 

r""" 

Numerical approximation by calling Mathematica's `N[]` 

 

Calling Mathematica's `N[]` function, with optional precision in decimal digits. 

Unlike Sage's `n()`, `N()` can be applied to symbolic Mathematica objects. 

 

A workaround for :trac:`18888` backtick issue, stripped away by `get()`, 

is included. 

 

.. note:: 

 

The base class way up the hierarchy defines an `N` (modeled 

after Mathematica's) which overwrites the Mathematica one, 

and doesn't work at all. We restore it here. 

 

EXAMPLES:: 

 

sage: mathematica('Pi/2').N(10) # optional -- mathematica 

1.570796327 

sage: mathematica('Pi').N(50) # optional -- mathematica 

3.1415926535897932384626433832795028841971693993751 

sage: mathematica('Pi*x^2-1/2').N() # optional -- mathematica 

2 

-0.5 + 3.14159 x 

""" 

P = self.parent() 

if precision is None: 

return P.eval('N[%s]'%self.name()) 

return P.eval('N[%s,%s]'%(self.name(),precision)) 

 

def n(self, *args, **kwargs): 

r""" 

Numerical approximation by converting to Sage object first 

 

Convert the object into a Sage object and return its numerical 

approximation. See documentation of the function 

:func:`sage.misc.functional.n` for details. 

 

EXAMPLES:: 

 

sage: mathematica('Pi').n(10) # optional -- mathematica 

3.1 

sage: mathematica('Pi').n() # optional -- mathematica 

3.14159265358979 

sage: mathematica('Pi').n(digits=10) # optional -- mathematica 

3.141592654 

""" 

return self._sage_().n(*args, **kwargs) 

 

 

@instancedoc 

class MathematicaFunction(ExpectFunction): 

def _instancedoc_(self): 

M = self._parent 

return M.help(self._name) 

 

 

@instancedoc 

class MathematicaFunctionElement(FunctionElement): 

def _instancedoc_(self): 

M = self._obj.parent() 

return M.help(self._name) 

 

 

# An instance 

mathematica = Mathematica() 

 

def reduce_load(X): 

return mathematica(X) 

 

 

def mathematica_console(readline=True): 

from sage.repl.rich_output.display_manager import get_display_manager 

if not get_display_manager().is_in_terminal(): 

raise RuntimeError('Can use the console only in the terminal. Try %%mathematica magics instead.') 

if not readline: 

os.system('math') 

return 

else: 

os.system('math-readline') 

return